X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=tests%2Futils%2Flttngtest%2Fenvironment.py;h=f0e894a69e14c470c7ac56a0f98b8fc3dab3dad4;hb=cebde614e5805e89341ba75d276b4d3e2da7225f;hp=4be5fb4faa356add20c59709800d6d1df6ef2541;hpb=c661f2f4c022314efcdc76b18f084cb42275370b;p=lttng-tools.git diff --git a/tests/utils/lttngtest/environment.py b/tests/utils/lttngtest/environment.py index 4be5fb4fa..f0e894a69 100644 --- a/tests/utils/lttngtest/environment.py +++ b/tests/utils/lttngtest/environment.py @@ -93,6 +93,7 @@ class _WaitTraceTestApplication: wait_before_exit=False, # type: bool wait_before_exit_file_path=None, # type: Optional[pathlib.Path] ): + self._process = None self._environment = environment # type: Environment self._iteration_count = event_count # File that the application will wait to see before tracing its events. @@ -100,7 +101,7 @@ class _WaitTraceTestApplication: tempfile.mktemp( prefix="app_", suffix="_start_tracing", - dir=self._compat_open_path(environment.lttng_home_location), + dir=self._compat_pathlike(environment.lttng_home_location), ) ) # File that the application will create when all events have been emitted. @@ -108,7 +109,7 @@ class _WaitTraceTestApplication: tempfile.mktemp( prefix="app_", suffix="_done_tracing", - dir=self._compat_open_path(environment.lttng_home_location), + dir=self._compat_pathlike(environment.lttng_home_location), ) ) @@ -117,7 +118,7 @@ class _WaitTraceTestApplication: tempfile.mktemp( prefix="app_", suffix="_exit", - dir=self._compat_open_path(environment.lttng_home_location), + dir=self._compat_pathlike(environment.lttng_home_location), ) ) @@ -133,7 +134,7 @@ class _WaitTraceTestApplication: app_ready_file_path = tempfile.mktemp( prefix="app_", suffix="_ready", - dir=self._compat_open_path(environment.lttng_home_location), + dir=self._compat_pathlike(environment.lttng_home_location), ) # type: str test_app_args = [str(binary_path)] @@ -165,7 +166,7 @@ class _WaitTraceTestApplication: def _wait_for_file_to_be_created(self, sync_file_path): # type: (pathlib.Path) -> None while True: - if os.path.exists(sync_file_path): + if os.path.exists(self._compat_pathlike(sync_file_path)): break if self._process.poll() is not None: @@ -187,7 +188,7 @@ class _WaitTraceTestApplication: return_code=self._process.returncode ) ) - open(self._compat_open_path(self._app_start_tracing_file_path), mode="x") + open(self._compat_pathlike(self._app_start_tracing_file_path), mode="x") def wait_for_tracing_done(self): # type: () -> None @@ -209,12 +210,13 @@ class _WaitTraceTestApplication: return self._process.pid @staticmethod - def _compat_open_path(path): + def _compat_pathlike(path): # type: (pathlib.Path) -> pathlib.Path | str """ - The builtin open() in python >= 3.6 expects a path-like object while - prior versions expect a string or bytes object. Return the correct type - based on the presence of the "__fspath__" attribute specified in PEP-519. + The builtin open() and many methods of the 'os' library in Python >= 3.6 + expect a path-like object while prior versions expect a string or + bytes object. Return the correct type based on the presence of the + "__fspath__" attribute specified in PEP-519. """ if hasattr(path, "__fspath__"): return path @@ -222,7 +224,7 @@ class _WaitTraceTestApplication: return str(path) def __del__(self): - if not self._has_returned: + if self._process is not None and not self._has_returned: # This is potentially racy if the pid has been recycled. However, # we can't use pidfd_open since it is only available in python >= 3.9. self._process.kill() @@ -243,7 +245,7 @@ class WaitTraceTestApplicationGroup: tempfile.mktemp( prefix="app_group_", suffix="_exit", - dir=_WaitTraceTestApplication._compat_open_path( + dir=_WaitTraceTestApplication._compat_pathlike( environment.lttng_home_location ), ) @@ -294,7 +296,7 @@ class WaitTraceTestApplicationGroup: app.wait_for_tracing_done() open( - _WaitTraceTestApplication._compat_open_path( + _WaitTraceTestApplication._compat_pathlike( self._wait_before_exit_file_path ), mode="x", @@ -314,6 +316,7 @@ class _TraceTestApplication: def __init__(self, binary_path, environment): # type: (pathlib.Path, Environment) + self._process = None self._environment = environment # type: Environment self._has_returned = False @@ -340,7 +343,7 @@ class _TraceTestApplication: self._has_returned = True def __del__(self): - if not self._has_returned: + if self._process is not None and not self._has_returned: # This is potentially racy if the pid has been recycled. However, # we can't use pidfd_open since it is only available in python >= 3.9. self._process.kill() @@ -374,6 +377,7 @@ class _Environment(logger._Logger): self, with_sessiond, # type: bool log=None, # type: Optional[Callable[[str], None]] + with_relayd=False, # type: bool ): super().__init__(log) signal.signal(signal.SIGTERM, self._handle_termination_signal) @@ -388,6 +392,11 @@ class _Environment(logger._Logger): "lttng_test_env_home" ) # type: Optional[TemporaryDirectory] + self._relayd = ( + self._launch_lttng_relayd() if with_relayd else None + ) # type: Optional[subprocess.Popen[bytes]] + self._relayd_output_consumer = None + self._sessiond = ( self._launch_lttng_sessiond() if with_sessiond else None ) # type: Optional[subprocess.Popen[bytes]] @@ -404,6 +413,21 @@ class _Environment(logger._Logger): # type: () -> pathlib.Path return self._project_root / "src" / "bin" / "lttng" / "lttng" + @property + def lttng_relayd_control_port(self): + # type: () -> int + return 5400 + + @property + def lttng_relayd_data_port(self): + # type: () -> int + return 5401 + + @property + def lttng_relayd_live_port(self): + # type: () -> int + return 5402 + def create_temporary_directory(self, prefix=None): # type: (Optional[str]) -> pathlib.Path # Simply return a path that is contained within LTTNG_HOME; it will @@ -439,6 +463,53 @@ class _Environment(logger._Logger): return unpacked_vars + def _launch_lttng_relayd(self): + # type: () -> Optional[subprocess.Popen] + relayd_path = ( + self._project_root / "src" / "bin" / "lttng-relayd" / "lttng-relayd" + ) + if os.environ.get("LTTNG_TEST_NO_RELAYD", "0") == "1": + # Run without a relay daemon; the user may be running one + # under gdb, for example. + return None + + relayd_env_vars = os.environ.get("LTTNG_RELAYD_ENV_VARS") + relayd_env = os.environ.copy() + if relayd_env_vars: + self._log("Additional lttng-relayd environment variables:") + for name, value in self._unpack_env_vars(relayd_env_vars): + self._log("{}={}".format(name, value)) + relayd_env[name] = value + + assert self._lttng_home is not None + relayd_env["LTTNG_HOME"] = str(self._lttng_home.path) + self._log( + "Launching relayd with LTTNG_HOME='${}'".format(str(self._lttng_home.path)) + ) + process = subprocess.Popen( + [ + str(relayd_path), + "-C", + "tcp://0.0.0.0:{}".format(self.lttng_relayd_control_port), + "-D", + "tcp://0.0.0.0:{}".format(self.lttng_relayd_data_port), + "-L", + "tcp://localhost:{}".format(self.lttng_relayd_live_port), + ], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=relayd_env, + ) + + if self._logging_function: + self._relayd_output_consumer = ProcessOutputConsumer( + process, "lttng-relayd", self._logging_function + ) + self._relayd_output_consumer.daemon = True + self._relayd_output_consumer.start() + + return process + def _launch_lttng_sessiond(self): # type: () -> Optional[subprocess.Popen] is_64bits_host = sys.maxsize > 2**32 @@ -576,6 +647,15 @@ class _Environment(logger._Logger): self._log("Session daemon killed") self._sessiond = None + if self._relayd and self._relayd.poll() is None: + self._relayd.terminate() + self._relayd.wait() + if self._relayd_output_consumer: + self._relayd_output_consumer.join() + self._relayd_output_consumer = None + self._log("Relayd killed") + self._relayd = None + self._lttng_home = None def __del__(self): @@ -583,9 +663,9 @@ class _Environment(logger._Logger): @contextlib.contextmanager -def test_environment(with_sessiond, log=None): - # type: (bool, Optional[Callable[[str], None]]) -> Iterator[_Environment] - env = _Environment(with_sessiond, log) +def test_environment(with_sessiond, log=None, with_relayd=False): + # type: (bool, Optional[Callable[[str], None]], bool) -> Iterator[_Environment] + env = _Environment(with_sessiond, log, with_relayd) try: yield env finally: