aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/test/py/conftest.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/py/conftest.py')
-rw-r--r--test/py/conftest.py170
1 files changed, 170 insertions, 0 deletions
diff --git a/test/py/conftest.py b/test/py/conftest.py
new file mode 100644
index 0000000..355bd83
--- /dev/null
+++ b/test/py/conftest.py
@@ -0,0 +1,170 @@
+# Copyright (c) 2023 Egor Tensin <Egor.Tensin@gmail.com>
+# This file is part of the "cimple" project.
+# For details, see https://github.com/egor-tensin/cimple.
+# Distributed under the MIT License.
+
+import logging
+import os
+import random
+
+from pytest import fixture
+
+from lib.process import CmdLine
+from lib.test_repo import TestRepo
+
+
+class Param:
+ def __init__(self, codename, help_string, required=True):
+ self.codename = codename
+ self.help_string = help_string
+ self.required = required
+
+ @property
+ def cmd_line(self):
+ return f"--{self.codename.replace('_', '-')}"
+
+ def add_to_parser(self, parser):
+ parser.addoption(self.cmd_line, required=self.required, help=self.help_string)
+
+
+class ParamBinary(Param):
+ def __init__(self, name, **kwargs):
+ self.name = name
+ super().__init__(self.get_code_name(), self.get_help_string(), **kwargs)
+
+ def get_code_name(self):
+ return f'{self.name}_binary'
+
+ @property
+ def basename(self):
+ return f'cimple-{self.name}'
+
+ def get_help_string(self):
+ return f'{self.basename} binary path'
+
+
+BINARY_PARAMS = [
+ ParamBinary(name) for name in ('server', 'worker', 'client')
+]
+
+PARAM_VALGRIND = ParamBinary('valgrind', required=False)
+
+
+class ParamVersion(Param):
+ def __init__(self):
+ super().__init__('project_version', 'project version')
+
+
+PARAM_VERSION = ParamVersion()
+
+PARAMS = list(BINARY_PARAMS)
+PARAMS += [
+ PARAM_VALGRIND,
+ PARAM_VERSION,
+]
+
+
+def pytest_addoption(parser):
+ for opt in PARAMS:
+ opt.add_to_parser(parser)
+
+
+def pytest_generate_tests(metafunc):
+ for opt in PARAMS:
+ if opt.codename in metafunc.fixturenames:
+ metafunc.parametrize(opt.codename, metafunc.config.getoption(opt.codename))
+
+
+@fixture(scope='session')
+def rng():
+ random.seed()
+
+
+class Paths:
+ def __init__(self, pytestconfig):
+ for opt in BINARY_PARAMS:
+ setattr(self, opt.codename, None)
+ for opt in BINARY_PARAMS:
+ path = pytestconfig.getoption(opt.codename)
+ if path is None:
+ continue
+ logging.info('%s path: %s', opt.basename, path)
+ setattr(self, opt.codename, path)
+
+
+@fixture(scope='session')
+def paths(pytestconfig):
+ return Paths(pytestconfig)
+
+
+@fixture(scope='session')
+def base_cmd_line(pytestconfig):
+ cmd_line = CmdLine.unbuffered()
+ valgrind = pytestconfig.getoption(PARAM_VALGRIND.codename)
+ if valgrind is not None:
+ # Signal to Valgrind that ci.sh should obviously be exempt from memory
+ # leak checking:
+ cmd_line = CmdLine.wrap(CmdLine(valgrind, '--trace-children-skip=*/ci.sh', '--'), cmd_line)
+ return cmd_line
+
+
+@fixture(scope='session')
+def version(pytestconfig):
+ return pytestconfig.getoption(PARAM_VERSION.codename)
+
+
+@fixture
+def server_port(rng):
+ return str(random.randint(2000, 50000))
+
+
+@fixture
+def sqlite_path(tmp_path):
+ return os.path.join(tmp_path, 'cimple.sqlite')
+
+
+class CmdLineServer(CmdLine):
+ def log_line_means_process_ready(self, line):
+ return line.endswith('Waiting for new connections')
+
+
+class CmdLineWorker(CmdLine):
+ def log_line_means_process_ready(self, line):
+ return line.endswith('Waiting for a new command')
+
+
+@fixture
+def server(base_cmd_line, paths, server_port, sqlite_path):
+ args = ['--port', server_port, '--sqlite', sqlite_path]
+ cmd_line = CmdLineServer.wrap(base_cmd_line, CmdLine(paths.server_binary, *args))
+ with cmd_line.run_async() as server:
+ yield server
+ assert server.returncode == 0
+
+
+@fixture
+def workers(base_cmd_line, paths, server_port):
+ args = ['--host', '127.0.0.1', '--port', server_port]
+ cmd_line = CmdLineWorker.wrap(base_cmd_line, CmdLine(paths.worker_binary, *args))
+ with cmd_line.run_async() as worker1, \
+ cmd_line.run_async() as worker2:
+ yield [worker1, worker2]
+ assert worker1.returncode == 0
+ assert worker2.returncode == 0
+
+
+@fixture
+def server_and_workers(server, workers):
+ yield server, workers
+
+
+@fixture
+def client(base_cmd_line, paths, server_port):
+ args = ['--host', '127.0.0.1', '--port', server_port]
+ cmd_line = CmdLine.wrap(base_cmd_line, CmdLine(paths.client_binary, *args))
+ return cmd_line
+
+
+@fixture
+def test_repo(tmp_path):
+ return TestRepo(tmp_path)