diff --git a/doc/developers/framework.rst b/doc/developers/framework.rst deleted file mode 100644 index 0b4e074..0000000 --- a/doc/developers/framework.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0-or-later - -Implementing a new Framework -============================ - -Every testing framework has its own setup, defining tests folders, data, and -variables. For this reason, the `Framework` class provides a generic API that, -once implemented, allows you to define a specific testing framework. - -The class implementation must be included inside the `libkirk` folder and will -be used as an abstraction layer between the `kirk` scheduler and the specific -testing framewiork. diff --git a/libkirk/framework.py b/libkirk/framework.py index 15e41d1..2b923f3 100644 --- a/libkirk/framework.py +++ b/libkirk/framework.py @@ -13,11 +13,10 @@ Suite, Test, ) -from libkirk.plugin import Plugin from libkirk.results import TestResults -class Framework(Plugin): +class Framework: """ Framework definition. Implement this class if you need to support more testing frameworks inside the application. diff --git a/libkirk/ltp.py b/libkirk/ltp.py index a0a0f66..2c0f6d2 100644 --- a/libkirk/ltp.py +++ b/libkirk/ltp.py @@ -17,7 +17,6 @@ Optional, ) -import libkirk.types from libkirk.com import ComChannel from libkirk.data import ( Suite, @@ -47,56 +46,42 @@ class LTPFramework(Framework): "max_runtime", ] - _name = "ltp" - - def __init__(self) -> None: + def __init__( + self, + max_runtime: float = 0.0, + timeout: float = 30.0, + env: dict = {}, + ) -> None: + """ + :param max_runtime: filter out all tests above this time value + :type max_runtime: float + :param timeout: generic tests timeout + :type timeout: float + :param env: user environment variables + :type env: dict + """ self._logger = logging.getLogger("libkirk.ltp") - self._root = "" - self._env = {} - self._max_runtime = 0.0 - self._tc_folder = "" self._cmd_matcher = re.compile(r'(?:"[^"]*"|\'[^\']*\'|\S+)') - - @property - def config_help(self) -> Dict[str, str]: - return { - "root": "LTP install folder", - "max_runtime": "filter out all tests above this time value", - } - - def setup(self, **kwargs: Dict[str, Any]) -> None: + self._max_runtime = max_runtime self._root = os.environ.get("LTPROOT", "/opt/ltp") + self._tc_folder = os.path.join(self._root, "testcases", "bin") + self._env = { "LTPROOT": self._root, "TMPDIR": "/tmp", "LTP_COLORIZE_OUTPUT": "1", } - env = libkirk.types.dict_item(kwargs, "env", dict) + multiplier = os.environ.get("LTP_TIMEOUT_MUL", None) + if multiplier: + self._env["LTP_TIMEOUT_MUL"] = multiplier + else: + if timeout: + self._env["LTP_TIMEOUT_MUL"] = str((timeout * 0.9) / 300.0) + if env: self._env.update(env) - timeout = libkirk.types.dict_item(kwargs, "test_timeout", float) - user_timeout_mul = os.environ.get("LTP_TIMEOUT_MUL") - if timeout and not user_timeout_mul: - self._env["LTP_TIMEOUT_MUL"] = str((timeout * 0.9) / 300.0) - - root = libkirk.types.dict_item(kwargs, "root", str) - if root: - self._root = root - self._env["LTPROOT"] = self._root - - self._tc_folder = os.path.join(self._root, "testcases", "bin") - - runtime = libkirk.types.dict_item(kwargs, "max_runtime", float) - if runtime: - try: - runtime = float(runtime) - except TypeError as err: - raise FrameworkError("max_runtime must be an integer") from err - - self._max_runtime = runtime - async def _read_path(self, channel: ComChannel) -> Dict[str, str]: """ Read PATH and initialize it with testcases folder as well. diff --git a/libkirk/main.py b/libkirk/main.py index 4c43c05..96ef4f4 100644 --- a/libkirk/main.py +++ b/libkirk/main.py @@ -26,11 +26,9 @@ from libkirk.com import ComChannel from libkirk.errors import ( CommunicationError, - FrameworkError, KirkException, SUTError, ) -from libkirk.framework import Framework from libkirk.monitor import JSONFileMonitor from libkirk.session import Session from libkirk.sut import SUT @@ -44,9 +42,6 @@ # Maximum number of COM instances MAX_COM_INSTANCES = 128 -# runtime loaded Framework(s) -LOADED_FRAMEWORK = [] - # return codes of the application RC_OK = 0 RC_ERROR = 1 @@ -81,8 +76,6 @@ def _from_params_to_config(params: List[str]) -> Dict[str, str]: def _dict_config( - opt_name: str, - plugins: Union[List[ComChannel], List[SUT]], value: str, ) -> Dict[str, str]: """ @@ -107,7 +100,7 @@ def _com_config(value: str) -> Optional[Dict[str, str]]: Return the list of channels configurations. """ plugins = libkirk.com.get_channels() - config = _dict_config("com", plugins, value) + config = _dict_config(value) if "help" in config: return config @@ -231,14 +224,6 @@ def _finjection_config(value: str) -> int: return ret -def _discover_frameworks(path: str) -> None: - """ - Discover new Framework implementations. - """ - objs = libkirk.plugin.discover(Framework, path) - LOADED_FRAMEWORK.extend(objs) - - def _get_skip_tests(skip_tests: str, skip_file: str) -> str: """ Return the skipped tests regexp. @@ -316,37 +301,6 @@ def _get_sut( return sut -def _get_framework( - args: argparse.Namespace, parser: argparse.ArgumentParser -) -> Framework: - """ - Create and framework object. - """ - fw_config = args.framework.copy() - if args.env: - fw_config["env"] = args.env.copy() - - if args.exec_timeout: - fw_config["test_timeout"] = args.exec_timeout - - if args.suite_timeout: - fw_config["suite_timeout"] = args.suite_timeout - - fw_name = args.framework["name"] - fw = next((f for f in LOADED_FRAMEWORK if f.name == fw_name), None) - if not fw: - parser.error(f"'{fw_name}' framework is not available") - - try: - # pyrefly: ignore[missing-attribute] - fw.setup(**fw_config) - except FrameworkError as err: - parser.error(str(err)) - - # pyrefly: ignore[bad-return] - return fw - - def _start_session(args: argparse.Namespace, parser: argparse.ArgumentParser) -> None: """ Start the LTP session. @@ -379,15 +333,14 @@ def _start_session(args: argparse.Namespace, parser: argparse.ArgumentParser) -> if args.com: _init_channels(args, parser, tmpdir) - # create SUT and Framework objects + # create SUT sut = _get_sut(args, parser, tmpdir) - framework = _get_framework(args, parser) # start session session = Session( - sut=sut, - framework=framework, tmpdir=tmpdir, + sut=sut, + env=args.env, exec_timeout=args.exec_timeout, suite_timeout=args.suite_timeout, workers=args.workers, @@ -482,8 +435,6 @@ def run(cmd_args: Optional[List[str]] = None) -> None: libkirk.com.discover(os.path.join(currdir, "channels")) libkirk.sut.discover(currdir) - _discover_frameworks(currdir) - parser = argparse.ArgumentParser( description="Kirk - All-in-one Linux Testing Framework" ) @@ -526,16 +477,9 @@ def run(cmd_args: Optional[List[str]] = None) -> None: "--sut", "-u", default="default", - type=lambda x: _dict_config("sut", libkirk.sut.get_suts(), x), + type=lambda x: _dict_config(x), help="System Under Test parameters. For help please use '--sut help'", ) - conf_opts.add_argument( - "--framework", - "-U", - default="ltp", - type=lambda x: _dict_config("framework", LOADED_FRAMEWORK, x), - help="Framework parameters. For help please use '--framework help'", - ) conf_opts.add_argument( "--env", "-e", @@ -633,10 +577,6 @@ def run(cmd_args: Optional[List[str]] = None) -> None: _print_plugin_help("--sut", libkirk.sut.get_suts()) parser.exit(RC_OK) - if args.framework and "help" in args.framework: - _print_plugin_help("--framework", LOADED_FRAMEWORK) - parser.exit(RC_OK) - if args.json_report and os.path.exists(args.json_report): parser.error(f"JSON report file already exists: {args.json_report}") diff --git a/libkirk/session.py b/libkirk/session.py index d24dcfe..b41e133 100644 --- a/libkirk/session.py +++ b/libkirk/session.py @@ -26,8 +26,8 @@ SessionError, ) from libkirk.export import JSONExporter -from libkirk.framework import Framework from libkirk.io import AsyncFile +from libkirk.ltp import LTPFramework from libkirk.results import TestResults from libkirk.scheduler import SuiteScheduler from libkirk.sut import ( @@ -61,8 +61,8 @@ class Session: def __init__( self, tmpdir: TempDir, - framework: Framework, sut: SUT, + env: dict = {}, exec_timeout: float = 3600.0, suite_timeout: float = 3600.0, workers: int = 1, @@ -71,8 +71,8 @@ def __init__( """ :param tmpdir: Temporary directory. :type tmpdir: TempDir - :param framework: Testing framework we are using. - :type framework: Framework + :param env: user environment variables + :type env: dict :param sut: SUT communication object. :type sut: SUT :param exec_timeout: Test timeout. @@ -86,7 +86,6 @@ def __init__( """ self._logger = logging.getLogger("kirk.session") self._tmpdir = tmpdir - self._framework = framework self._sut = sut self._exec_timeout = exec_timeout self._force_parallel = force_parallel @@ -94,6 +93,10 @@ def __init__( self._exec_lock = asyncio.Lock() self._run_lock = asyncio.Lock() self._results = [] + self._framework = LTPFramework( + timeout=self._exec_timeout, + env=env, + ) self._scheduler = SuiteScheduler( sut=self._sut, diff --git a/libkirk/tests/conftest.py b/libkirk/tests/conftest.py index 547b701..774a4e3 100644 --- a/libkirk/tests/conftest.py +++ b/libkirk/tests/conftest.py @@ -3,16 +3,12 @@ """ import os -from typing import Dict, List import pytest import libkirk import libkirk.com -from libkirk.data import Suite, Test -from libkirk.framework import Framework -from libkirk.results import TestResults -from libkirk.sut import SUT +import libkirk.sut @pytest.fixture(scope="session") @@ -42,170 +38,38 @@ def _discover_plugins(): libkirk.sut.discover(os.path.join(currdir, ".."), extend=False) -class DummyFramework(Framework): +@pytest.fixture +def ltpdir(tmpdir): """ - A generic framework created for testing. + Setup the temporary folder with LTP tests. """ + os.environ["LTPROOT"] = str(tmpdir) - def __init__(self) -> None: - self._root = None - - def setup(self, **kwargs: Dict[str, str]) -> None: - self._root = kwargs.get("root", "/") - self._env = kwargs.get("env", None) - - @property - def name(self) -> str: - return "dummy" - - @property - def config_help(self) -> Dict[str, str]: - return {} - - async def get_suites(self, sut: SUT) -> List[str]: - return ["suite01", "suite02", "sleep", "environ", "kernel_panic"] - - async def find_command(self, sut: SUT, command: str) -> Test: - return Test(name=command, cmd=command) - - async def find_suite(self, sut: SUT, name: str) -> Suite: - if name in "suite01": - test0 = Test( - name="test01", - cwd=self._root, - env=self._env, - cmd="echo", - args=["-n", "ciao0"], - parallelizable=False, - ) - - test1 = Test( - name="test02", - cwd=self._root, - env=self._env, - cmd="echo", - args=["-n", "ciao0"], - parallelizable=False, - ) - - return Suite(name, [test0, test1]) - if name == "suite02": - test0 = Test( - name="test01", - cwd=self._root, - env=self._env, - cmd="echo", - args=["-n", "ciao0"], - parallelizable=False, - ) - - test1 = Test( - name="test02", - cwd=self._root, - env=self._env, - cmd="sleep", - args=["0.2", "&&", "echo", "-n", "ciao1"], - parallelizable=True, - ) - - return Suite(name, [test0, test1]) - elif name == "sleep": - test0 = Test( - name="test01", - cwd=self._root, - env=self._env, - cmd="sleep", - args=["2"], - parallelizable=False, - ) - - test1 = Test( - name="test02", - cwd=self._root, - env=self._env, - cmd="sleep", - args=["2"], - parallelizable=False, - ) - - return Suite(name, [test0, test1]) - elif name == "environ": - test0 = Test( - name="test01", - cwd=self._root, - env=self._env, - cmd="echo", - args=["-n", "$hello"], - parallelizable=False, - ) - - return Suite(name, [test0]) - elif name == "kernel_panic": - test0 = Test( - name="test01", - cwd=self._root, - env=self._env, - cmd="echo", - args=["Kernel", "panic"], - parallelizable=False, - ) - - test1 = Test( - name="test01", - cwd=self._root, - env=self._env, - cmd="sleep", - args=["0.2"], - parallelizable=False, - ) - - return Suite(name, [test0, test1]) - - return None - - async def read_result( - self, test: Test, stdout: str, retcode: int, exec_t: float - ) -> TestResults: - passed = 0 - failed = 0 - skipped = 0 - broken = 0 - skipped = 0 - warnings = 0 - error = retcode == -1 - - if retcode == 0: - passed = 1 - elif retcode == 4: - warnings = 1 - elif retcode == 32: - skipped = 1 - elif not error: - failed = 1 - - if error: - broken = 1 - - result = TestResults( - test=test, - passed=passed, - failed=failed, - broken=broken, - skipped=skipped, - warnings=warnings, - exec_time=exec_t, - retcode=retcode, - stdout=stdout, - ) - - return result + tmpdir.mkdir("testcases").mkdir("bin") + runtest = tmpdir.mkdir("runtest") + suite01 = runtest / "suite01" + suite01.write_text( + "test01 echo -n ciao\ntest02 echo -n ciao\n", + encoding="utf-8") -@pytest.fixture -def dummy_framework(): - """ - A fummy framework implementation used for testing. - """ - obj = DummyFramework() - obj.setup(root="/tmp") - yield obj + suite02 = runtest / "suite02" + suite02.write_text( + "test01 echo -n ciao\ntest02 sleep 0.2 && echo -n ciao", + encoding="utf-8") + + sleep = runtest / "sleep" + sleep.write_text( + "sleep01 sleep 2\nsleep02 sleep 2", + encoding="utf-8") + + environ = runtest / "environ" + environ.write_text("test01 echo -n $hello", + encoding="utf-8") + + kernel_panic = runtest / "kernel_panic" + kernel_panic.write_text( + "test01 echo 'Kernel panic'\ntest02 sleep 0.2", + encoding="utf-8") + + return tmpdir diff --git a/libkirk/tests/test_ltp.py b/libkirk/tests/test_ltp.py index 013989a..912e6c4 100644 --- a/libkirk/tests/test_ltp.py +++ b/libkirk/tests/test_ltp.py @@ -35,13 +35,11 @@ async def sut(self): await obj.stop() @pytest.fixture - def framework(self, tmpdir): + def framework(self): """ LTP framework object. """ fw = LTPFramework() - fw.setup(root=str(tmpdir)) - yield fw @pytest.fixture(autouse=True) @@ -49,6 +47,8 @@ def prepare_tmpdir(self, tmpdir): """ Prepare the temporary directory adding runtest folder. """ + os.environ["LTPROOT"] = str(tmpdir) + # create simple testing suites content = "" for i in range(self.TESTS_NUM): @@ -83,13 +83,7 @@ def prepare_tmpdir(self, tmpdir): test_sh = testcases / "test.sh" test_sh.write("#!/bin/bash\necho $1 $2\n") - async def test_name(self, framework): - """ - Test that name property is not empty. - """ - assert framework.name == "ltp" - - async def test_get_suites(self, framework, sut, tmpdir): + async def test_get_suites(self, framework, sut): """ Test get_suites method. """ @@ -142,12 +136,11 @@ async def test_find_suite(self, framework, sut, tmpdir): assert "TMPDIR" in test.env assert "LTP_COLORIZE_OUTPUT" in test.env - async def test_find_suite_max_runtime(self, sut, tmpdir): + async def test_find_suite_max_runtime(self, sut): """ Test find_suite method when max_runtime is defined. """ - framework = LTPFramework() - framework.setup(root=str(tmpdir), max_runtime=5) + framework = LTPFramework(max_runtime=5) suite = await framework.find_suite(sut, "slow_suite") assert len(suite.tests) == 0 diff --git a/libkirk/tests/test_main.py b/libkirk/tests/test_main.py index acb8fd0..94f2618 100644 --- a/libkirk/tests/test_main.py +++ b/libkirk/tests/test_main.py @@ -9,6 +9,8 @@ import pytest +import libkirk.sut +import libkirk.com import libkirk.main @@ -18,12 +20,11 @@ class TestMain: """ @pytest.fixture(autouse=True) - def setup(self, dummy_framework): + def setup(self, ltpdir): """ - Setup main before running tests. + Create and initialize LTP root directory. """ - if len(libkirk.main.LOADED_FRAMEWORK) < 2: - libkirk.main.LOADED_FRAMEWORK.append(dummy_framework) + pass def read_report(self, temp) -> dict: """ @@ -91,8 +92,6 @@ def test_run_suite(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", ] @@ -113,8 +112,6 @@ def test_run_suite_timeout(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", "--suite-timeout", @@ -144,8 +141,6 @@ def test_run_suite_verbose(self, tmpdir, capsys): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", "--verbose", @@ -157,7 +152,7 @@ def test_run_suite_verbose(self, tmpdir, capsys): assert excinfo.value.code == libkirk.main.RC_OK captured = capsys.readouterr() - assert "ciao0\n" in captured.out + assert "echo -n ciao\n" in captured.out @pytest.mark.xfail(reason="This test passes if run alone. capsys bug?") def test_run_suite_no_colors(self, tmpdir, capsys): @@ -168,8 +163,6 @@ def test_run_suite_no_colors(self, tmpdir, capsys): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", "--no-colors", @@ -193,8 +186,6 @@ def test_restore_suite(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", ] @@ -214,8 +205,6 @@ def test_restore_suite(self, tmpdir): str(temp), "--restore", f"{str(temp)}/kirk.{name}/latest", - "--framework", - "dummy", "--run-suite", "suite01", "environ", @@ -238,8 +227,6 @@ def test_json_report(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", "--json-report", @@ -269,8 +256,6 @@ def test_skip_tests(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", "--skip-tests", @@ -296,8 +281,6 @@ def test_skip_file(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", "--skip-file", @@ -323,8 +306,6 @@ def test_skip_tests_and_file(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", "--skip-tests", @@ -351,8 +332,6 @@ def test_workers(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", "--workers", @@ -379,19 +358,6 @@ def test_sut_help(self): assert excinfo.value.code == libkirk.main.RC_OK assert len(libkirk.sut.get_suts()) > 0 - def test_framework_help(self): - """ - Test "--framework help" command and check if Framework class(es) - are loaded. - """ - cmd_args = ["--framework", "help"] - - with pytest.raises(SystemExit) as excinfo: - libkirk.main.run(cmd_args=cmd_args) - - assert excinfo.value.code == libkirk.main.RC_OK - assert len(libkirk.main.LOADED_FRAMEWORK) > 0 - def test_env(self, tmpdir): """ Test --env option. @@ -400,8 +366,6 @@ def test_env(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "environ", "--env", @@ -425,8 +389,6 @@ def test_suite_iterate(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", "--suite-iterate", @@ -451,8 +413,6 @@ def test_randomize(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", ] cmd_args.extend(["suite01"] * num_of_suites) @@ -480,8 +440,6 @@ def test_runtime(self, tmpdir): cmd_args = [ "--tmp-dir", str(temp), - "--framework", - "dummy", "--run-suite", "suite01", "--runtime", @@ -568,8 +526,6 @@ def test_com(self, tmpdir): "shell:id=myshell", "--sut", "default:com=myshell", - "--framework", - "dummy", "--run-suite", "suite01", ] diff --git a/libkirk/tests/test_plugin.py b/libkirk/tests/test_plugin.py index ce2762d..19d27e9 100644 --- a/libkirk/tests/test_plugin.py +++ b/libkirk/tests/test_plugin.py @@ -6,7 +6,6 @@ import libkirk import libkirk.plugin from libkirk.plugin import Plugin -from libkirk.framework import Framework @pytest.fixture(autouse=True) @@ -27,29 +26,6 @@ def setup(tmpdir): ) -def test_framework(tmpdir): - """ - Test if Framework implementations are correctly loaded. - """ - suts = [] - suts.append(tmpdir / "frameworkA.py") - suts.append(tmpdir / "frameworkB.py") - suts.append(tmpdir / "frameworkC.txt") - - for index in range(0, len(suts)): - suts[index].write( - "from libkirk.framework import Framework\n\n" - f"class Framework{index}(Framework):\n" - " @property\n" - " def name(self) -> str:\n" - f" return 'fw{index}'\n" - ) - - suts = libkirk.plugin.discover(Framework, str(tmpdir)) - - assert len(suts) == 2 - - def test_clone(tmpdir): """ Test if ``clone`` method properly forks inside ``Plugin``. diff --git a/libkirk/tests/test_scheduler.py b/libkirk/tests/test_scheduler.py index 5b2bdab..fdcb7d0 100644 --- a/libkirk/tests/test_scheduler.py +++ b/libkirk/tests/test_scheduler.py @@ -2,7 +2,9 @@ Unittests for runner module. """ +from libkirk.ltp import LTPFramework import asyncio +import os import re import sys @@ -12,7 +14,6 @@ from libkirk.results import ResultStatus from libkirk.errors import KernelPanicError, KernelTaintedError, KernelTimeoutError from libkirk.sut_base import GenericSUT -from libkirk.channels.shell import ShellComChannel from libkirk.scheduler import SuiteScheduler, TestScheduler pytestmark = pytest.mark.asyncio @@ -96,11 +97,11 @@ class TestTestScheduler: """ @pytest.fixture - async def create_runner(self, sut, dummy_framework): + async def create_runner(self, sut, ltpdir): def _callback(timeout: float = 3600.0, max_workers: int = 1) -> TestScheduler: obj = MockTestScheduler( sut=sut, - framework=dummy_framework, + framework=LTPFramework(), timeout=timeout, max_workers=max_workers, ) @@ -319,7 +320,7 @@ class TestSuiteScheduler: """ @pytest.fixture - async def create_runner(self, sut, dummy_framework): + async def create_runner(self, sut, ltpdir): def _callback( suite_timeout: float = 3600.0, exec_timeout: float = 3600.0, @@ -327,7 +328,7 @@ def _callback( ) -> SuiteScheduler: obj = MockSuiteScheduler( sut=sut, - framework=dummy_framework, + framework=LTPFramework(), suite_timeout=suite_timeout, exec_timeout=exec_timeout, max_workers=max_workers, diff --git a/libkirk/tests/test_session.py b/libkirk/tests/test_session.py index 4d59216..59bb85b 100644 --- a/libkirk/tests/test_session.py +++ b/libkirk/tests/test_session.py @@ -27,16 +27,12 @@ class _TestSession: """ @pytest.fixture - async def session(self, tmpdir, sut, dummy_framework): + async def session(self, ltpdir, sut): """ Session communication object. """ - session = Session( - tmpdir=TempDir(str(tmpdir)), framework=dummy_framework, sut=sut - ) - + session = Session(tmpdir=TempDir(str(ltpdir)), sut=sut) yield session - await asyncio.wait_for(session.stop(), timeout=30) async def test_run(self, session):