aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorEgor Tensin <egor@tensin.name>2026-06-18 15:33:27 +0200
committerEgor Tensin <egor@tensin.name>2026-06-18 15:33:27 +0200
commitb1d66075b13c40606bb2d0bd8f90275b8f2e8abb (patch)
tree95d5a5ef6b9e452fae3932699834930f1895cee9
parentworkflows/ci: add Python linting (diff)
downloadcimple-b1d66075b13c40606bb2d0bd8f90275b8f2e8abb.tar.gz
cimple-b1d66075b13c40606bb2d0bd8f90275b8f2e8abb.zip
workflows/ci: use default Black settings
-rw-r--r--.github/workflows/ci.yml4
-rwxr-xr-xsrc/generate-sql-header.py38
-rw-r--r--test/src/conftest.py44
-rw-r--r--test/src/lib/db.py6
-rw-r--r--test/src/lib/logging.py18
-rw-r--r--test/src/lib/net.py2
-rw-r--r--test/src/lib/process.py34
-rw-r--r--test/src/lib/test_repo.py62
-rw-r--r--test/src/lib/tests.py8
-rw-r--r--test/src/test_basic.py52
-rw-r--r--test/src/test_repo.py30
11 files changed, 147 insertions, 151 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bbd66de..813ceba 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -30,10 +30,6 @@ jobs:
python-version: '3.x'
- name: Run black
uses: psf/black@stable
- with:
- # > Please note that the --check flag is required so that the
- # > workflow fails if Black finds files that need to be formatted.
- options: --check --verbose --skip-string-normalization
build:
strategy:
diff --git a/src/generate-sql-header.py b/src/generate-sql-header.py
index 591baf2..ed0b56d 100755
--- a/src/generate-sql-header.py
+++ b/src/generate-sql-header.py
@@ -16,12 +16,12 @@ class Generator:
def __init__(self, fd, dir):
self.fd = fd
if not os.path.isdir(dir):
- raise RuntimeError('must be a directory: ' + dir)
+ raise RuntimeError("must be a directory: " + dir)
self.dir = os.path.abspath(dir)
self.name = os.path.basename(self.dir)
def write(self, line):
- self.fd.write(f'{line}\n')
+ self.fd.write(f"{line}\n")
def do(self):
self.include_guard_start()
@@ -29,34 +29,34 @@ class Generator:
self.include_guard_end()
def include_guard_start(self):
- self.write(f'#ifndef __{self.name.upper()}_SQL_H__')
- self.write(f'#define __{self.name.upper()}_SQL_H__')
- self.write('')
+ self.write(f"#ifndef __{self.name.upper()}_SQL_H__")
+ self.write(f"#define __{self.name.upper()}_SQL_H__")
+ self.write("")
def include_guard_end(self):
- self.write('')
- self.write(f'#endif')
+ self.write("")
+ self.write(f"#endif")
def enum_sql_files(self):
return [
os.path.join(self.dir, path)
- for path in sorted(glob('*.sql', root_dir=self.dir))
+ for path in sorted(glob("*.sql", root_dir=self.dir))
]
@property
def var_name_prefix(self):
- return f'{self.name}'
+ return f"{self.name}"
def sql_file_to_var_name(self, path):
name = os.path.splitext(os.path.basename(path))[0]
- return f'{self.var_name_prefix}_schema_{name}'
+ return f"{self.var_name_prefix}_schema_{name}"
@staticmethod
def sql_file_to_string_literal(path):
with open(path) as fd:
sql = fd.read()
sql = sql.encode().hex().upper()
- sql = ''.join((f'\\x{sql[i:i + 2]}' for i in range(0, len(sql), 2)))
+ sql = "".join((f"\\x{sql[i:i + 2]}" for i in range(0, len(sql), 2)))
return sql
def include_sql_files(self):
@@ -66,11 +66,11 @@ class Generator:
vars.append(name)
value = self.sql_file_to_string_literal(path)
self.write(f'static const char *const {name} = "{value}";')
- self.write('')
- self.write(f'static const char *const {self.var_name_prefix}_schemas[] = {{')
+ self.write("")
+ self.write(f"static const char *const {self.var_name_prefix}_schemas[] = {{")
for var in vars:
- self.write(f'\t{var},')
- self.write('};')
+ self.write(f"\t{var},")
+ self.write("};")
@contextmanager
@@ -80,7 +80,7 @@ def open_output(path):
else:
path = os.path.abspath(path)
os.makedirs(os.path.dirname(path), exist_ok=True)
- with open(path, 'w') as fd:
+ with open(path, "w") as fd:
yield fd
@@ -88,8 +88,8 @@ def parse_args(argv=None):
if argv is None:
argv = sys.argv[1:]
parser = argparse.ArgumentParser()
- parser.add_argument('-o', '--output', metavar='PATH', help='set output file path')
- parser.add_argument('dir', metavar='INPUT_DIR', help='input directory')
+ parser.add_argument("-o", "--output", metavar="PATH", help="set output file path")
+ parser.add_argument("dir", metavar="INPUT_DIR", help="input directory")
return parser.parse_args()
@@ -100,5 +100,5 @@ def main(argv=None):
generator.do()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/test/src/conftest.py b/test/src/conftest.py
index 029eeb7..d1ee91c 100644
--- a/test/src/conftest.py
+++ b/test/src/conftest.py
@@ -30,15 +30,15 @@ class Param:
PARAMS = [
- Param(f'{name}', f'cimple-{name} binary path')
- for name in ('server', 'worker', 'client')
+ Param(f"{name}", f"cimple-{name} binary path")
+ for name in ("server", "worker", "client")
]
PARAMS += [
- Param('sigsegv', 'sigsegv binary path'),
- Param('project_version', 'project version'),
- Param('valgrind', 'path to valgrind.sh', required=False),
- Param('flamegraph', 'path to flamegraph.sh', required=False),
- Param('flame_graphs_dir', 'directory to store flame graphs', required=False),
+ Param("sigsegv", "sigsegv binary path"),
+ Param("project_version", "project version"),
+ Param("valgrind", "path to valgrind.sh", required=False),
+ Param("flamegraph", "path to flamegraph.sh", required=False),
+ Param("flame_graphs_dir", "directory to store flame graphs", required=False),
]
@@ -59,7 +59,7 @@ class Params:
setattr(self, opt.codename, path)
-@fixture(scope='session')
+@fixture(scope="session")
def params(pytestconfig):
return Params(pytestconfig)
@@ -68,10 +68,10 @@ class CmdLineValgrind(CmdLine):
def __init__(self, binary):
# Signal to Valgrind that ci scripts should obviously be exempt from
# memory leak checking:
- super().__init__(binary, '--trace-children-skip=*/ci', '--')
+ super().__init__(binary, "--trace-children-skip=*/ci", "--")
-@fixture(scope='session')
+@fixture(scope="session")
def base_cmd_line(params):
cmd_line = CmdLine.unbuffered()
valgrind = params.valgrind
@@ -80,19 +80,19 @@ def base_cmd_line(params):
return cmd_line
-@fixture(scope='session')
+@fixture(scope="session")
def version(params):
return params.project_version
-@fixture(scope='session')
+@fixture(scope="session")
def server_port():
return str(random_unused_port())
@fixture
def sqlite_path(tmp_path):
- return os.path.join(tmp_path, 'cimple.sqlite')
+ return os.path.join(tmp_path, "cimple.sqlite")
@fixture
@@ -102,12 +102,12 @@ def sqlite_db(server, sqlite_path):
class CmdLineServer(CmdLine):
def log_line_means_process_ready(self, line):
- return line.endswith('Waiting for new connections')
+ 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')
+ return line.endswith("Waiting for a new command")
@fixture
@@ -127,19 +127,19 @@ def client_exe(params):
@fixture
def server_cmd(base_cmd_line, params, server_port, sqlite_path):
- args = ['--port', server_port, '--sqlite', sqlite_path]
+ args = ["--port", server_port, "--sqlite", sqlite_path]
return CmdLineServer.wrap(base_cmd_line, CmdLine(params.server, *args))
@fixture
def worker_cmd(base_cmd_line, params, server_port):
- args = ['--host', '127.0.0.1', '--port', server_port]
+ args = ["--host", "127.0.0.1", "--port", server_port]
return CmdLineWorker.wrap(base_cmd_line, CmdLine(params.worker, *args))
@fixture
def client(base_cmd_line, params, server_port):
- args = ['--host', '127.0.0.1', '--port', server_port]
+ args = ["--host", "127.0.0.1", "--port", server_port]
return CmdLine.wrap(base_cmd_line, CmdLine(params.client, *args))
@@ -167,9 +167,9 @@ def workers(worker_cmd):
def flame_graph_svg(params, tmp_path, flame_graph_repo):
dir = params.flame_graphs_dir
if dir is None:
- return os.path.join(tmp_path, 'flame_graph.svg')
+ return os.path.join(tmp_path, "flame_graph.svg")
os.makedirs(dir, exist_ok=True)
- return os.path.join(dir, f'flame_graph_{flame_graph_repo.codename()}.svg')
+ return os.path.join(dir, f"flame_graph_{flame_graph_repo.codename()}.svg")
@fixture
@@ -184,7 +184,7 @@ def profiler(params, server, workers, flame_graph_svg):
@fixture
def repo_path(tmp_path):
- return os.path.join(tmp_path, 'repo')
+ return os.path.join(tmp_path, "repo")
TEST_REPOS = [
@@ -223,7 +223,7 @@ def flame_graph_repo(stress_test_repo):
return stress_test_repo
-Env = namedtuple('Env', ['server', 'workers', 'client', 'db'])
+Env = namedtuple("Env", ["server", "workers", "client", "db"])
@fixture
diff --git a/test/src/lib/db.py b/test/src/lib/db.py
index de6960a..0e47901 100644
--- a/test/src/lib/db.py
+++ b/test/src/lib/db.py
@@ -10,8 +10,8 @@ import sqlite3
class Database:
def __init__(self, path):
- logging.info('Opening SQLite database: %s', path)
- self.conn = sqlite3.connect(f'file:{path}?mode=ro', uri=True)
+ logging.info("Opening SQLite database: %s", path)
+ self.conn = sqlite3.connect(f"file:{path}?mode=ro", uri=True)
def __enter__(self):
return self
@@ -26,5 +26,5 @@ class Database:
def get_all_runs(self):
with self.get_cursor() as cur:
- cur.execute('SELECT * FROM cimple_runs_view')
+ cur.execute("SELECT * FROM cimple_runs_view")
return cur.fetchall()
diff --git a/test/src/lib/logging.py b/test/src/lib/logging.py
index 663eb3a..aed0eeb 100644
--- a/test/src/lib/logging.py
+++ b/test/src/lib/logging.py
@@ -13,7 +13,7 @@ import multiprocessing as mp
@contextmanager
def child_logging_thread():
# Delegating logging to the parent logger.
- ctx = mp.get_context('spawn')
+ ctx = mp.get_context("spawn")
queue = ctx.Queue()
listener = logging.handlers.QueueListener(queue, logging.getLogger())
listener.start()
@@ -26,16 +26,16 @@ def child_logging_thread():
@contextmanager
def configure_logging_in_child(queue):
config = {
- 'version': 1,
- 'handlers': {
- 'sink': {
- 'class': 'logging.handlers.QueueHandler',
- 'queue': queue,
+ "version": 1,
+ "handlers": {
+ "sink": {
+ "class": "logging.handlers.QueueHandler",
+ "queue": queue,
},
},
- 'root': {
- 'handlers': ['sink'],
- 'level': 'DEBUG',
+ "root": {
+ "handlers": ["sink"],
+ "level": "DEBUG",
},
}
logging.config.dictConfig(config)
diff --git a/test/src/lib/net.py b/test/src/lib/net.py
index 06bfda0..96979f7 100644
--- a/test/src/lib/net.py
+++ b/test/src/lib/net.py
@@ -10,6 +10,6 @@ import socket
def random_unused_port():
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- sock.bind(('0.0.0.0', 0))
+ sock.bind(("0.0.0.0", 0))
port = sock.getsockname()[1]
return port
diff --git a/test/src/lib/process.py b/test/src/lib/process.py
index cea109d..72a13c6 100644
--- a/test/src/lib/process.py
+++ b/test/src/lib/process.py
@@ -21,7 +21,7 @@ class LoggingEvent(Event):
def wait(self):
if not super().wait(self.timeout):
- raise RuntimeError('timed out while waiting for an event')
+ raise RuntimeError("timed out while waiting for an event")
class LoggingThread(Thread):
@@ -41,8 +41,8 @@ class LoggingThread(Thread):
def process_output_lines(self):
for line in self.process.stdout:
- line = line.removesuffix('\n')
- logging.info('%s: %s', self.process.log_id, line)
+ line = line.removesuffix("\n")
+ logging.info("%s: %s", self.process.log_id, line)
with self.events_lock:
for event in self.events:
if event.is_set():
@@ -66,7 +66,7 @@ class CmdLine:
@staticmethod
def unbuffered():
- return CmdLine('stdbuf', '-o0')
+ return CmdLine("stdbuf", "-o0")
def __init__(self, binary, *args, name=None):
binary = self.which(binary)
@@ -104,7 +104,7 @@ class LoggingEventProcessReady(LoggingEvent):
super().__init__()
def set(self):
- logging.info('Process %s is ready', self.process.log_id)
+ logging.info("Process %s is ready", self.process.log_id)
super().set()
def log_line_matches(self, line):
@@ -113,15 +113,15 @@ class LoggingEventProcessReady(LoggingEvent):
class Process(subprocess.Popen):
_COMMON_ARGS = {
- 'text': True,
- 'stdin': subprocess.DEVNULL,
- 'stdout': subprocess.PIPE,
- 'stderr': subprocess.STDOUT,
+ "text": True,
+ "stdin": subprocess.DEVNULL,
+ "stdout": subprocess.PIPE,
+ "stderr": subprocess.STDOUT,
}
@staticmethod
def _log_process_start(argv):
- logging.info('Executing command: %s', argv)
+ logging.info("Executing command: %s", argv)
@staticmethod
def _log_process_end(argv, ec, output):
@@ -129,11 +129,11 @@ class Process(subprocess.Popen):
if ec:
log = logging.error
if ec:
- log('Command %s exited with code %s', argv, ec)
+ log("Command %s exited with code %s", argv, ec)
else:
- log('Command %s completed successfully', argv)
+ log("Command %s completed successfully", argv)
if output:
- log('Output:\n%s', output)
+ log("Output:\n%s", output)
@staticmethod
def run(*args, **kwargs):
@@ -163,7 +163,7 @@ class Process(subprocess.Popen):
self._log_process_start(argv)
super().__init__(argv, **Process._COMMON_ARGS)
- logging.info('Process %s has started', self.log_id)
+ logging.info("Process %s has started", self.log_id)
ready_event = LoggingEventProcessReady(self)
self.logger = LoggingThread(self, [ready_event])
@@ -171,7 +171,7 @@ class Process(subprocess.Popen):
@property
def log_id(self):
- return f'{self.pid}/{self.cmd_line.process_name}'
+ return f"{self.pid}/{self.cmd_line.process_name}"
def __exit__(self, *args):
try:
@@ -189,13 +189,13 @@ class Process(subprocess.Popen):
ec = self.poll()
if ec is not None:
return
- logging.info('Terminating process %s', self.log_id)
+ logging.info("Terminating process %s", self.log_id)
self.terminate()
try:
self.wait(timeout=Process.SHUT_DOWN_TIMEOUT_SEC)
return
except subprocess.TimeoutExpired:
pass
- logging.info('Process %s failed to terminate in time, killing it', self.log_id)
+ logging.info("Process %s failed to terminate in time, killing it", self.log_id)
self.kill()
self.wait(timeout=Process.SHUT_DOWN_TIMEOUT_SEC)
diff --git a/test/src/lib/test_repo.py b/test/src/lib/test_repo.py
index f295e91..063043d 100644
--- a/test/src/lib/test_repo.py
+++ b/test/src/lib/test_repo.py
@@ -15,43 +15,43 @@ from .process import Process
class Repo:
- BRANCH = 'main'
+ BRANCH = "main"
def __init__(self, path):
self.path = os.path.abspath(path)
os.makedirs(path, exist_ok=True)
- self.run('git', 'init', '-q', f'--initial-branch={Repo.BRANCH}')
- self.run('git', 'config', 'user.name', 'Test User')
- self.run('git', 'config', 'user.email', 'test@example.com')
+ self.run("git", "init", "-q", f"--initial-branch={Repo.BRANCH}")
+ self.run("git", "config", "user.name", "Test User")
+ self.run("git", "config", "user.email", "test@example.com")
def run(self, *args, **kwargs):
Process.run(*args, cwd=self.path, **kwargs)
-CI_SCRIPT = r'''#!/usr/bin/env bash
+CI_SCRIPT = r"""#!/usr/bin/env bash
set -o errexit -o nounset -o pipefail
readonly runs_dir={runs_dir}
readonly run_output_template=run_XXXXXX
run_output_path="$( mktemp --tmpdir="$runs_dir" "$run_output_template" )"
touch -- "$run_output_path"
-'''
+"""
class TestRepo(Repo):
# Prevent Pytest from discovering test cases in this class:
__test__ = False
- def __init__(self, path, ci_script='ci'):
+ def __init__(self, path, ci_script="ci"):
super().__init__(path)
- self.runs_dir = os.path.join(self.path, 'runs')
+ self.runs_dir = os.path.join(self.path, "runs")
os.makedirs(self.runs_dir, exist_ok=True)
self.ci_script_path = os.path.join(self.path, ci_script)
self.write_ci_script()
- self.run('git', 'add', '--', ci_script)
- self.run('git', 'commit', '-q', '-m', 'add CI script')
+ self.run("git", "add", "--", ci_script)
+ self.run("git", "commit", "-q", "-m", "add CI script")
@staticmethod
@abc.abstractmethod
@@ -67,7 +67,7 @@ class TestRepo(Repo):
pass
def write_ci_script(self):
- with open(self.ci_script_path, mode='x') as f:
+ with open(self.ci_script_path, mode="x") as f:
f.write(self.format_ci_script())
os.chmod(self.ci_script_path, 0o755)
@@ -91,25 +91,25 @@ class TestRepo(Repo):
class TestRepoOutput(TestRepo, abc.ABC):
__test__ = False
- OUTPUT_SCRIPT_NAME = 'generate-output'
+ OUTPUT_SCRIPT_NAME = "generate-output"
def __init__(self, path):
self.output_script_path = os.path.join(path, TestRepoOutput.OUTPUT_SCRIPT_NAME)
super().__init__(path)
self.write_output_script()
- self.run('git', 'add', '--', TestRepoOutput.OUTPUT_SCRIPT_NAME)
- self.run('git', 'commit', '-q', '-m', 'add output script')
+ self.run("git", "add", "--", TestRepoOutput.OUTPUT_SCRIPT_NAME)
+ self.run("git", "commit", "-q", "-m", "add output script")
def format_ci_script(self):
script = super().format_ci_script()
added = r'{output_script} | tee -a "$run_output_path"'.format(
output_script=shlex.quote(self.output_script_path)
)
- return f'{script}\n{added}\n'
+ return f"{script}\n{added}\n"
def write_output_script(self):
- with open(self.output_script_path, mode='x') as f:
+ with open(self.output_script_path, mode="x") as f:
f.write(self.format_output_script())
os.chmod(self.output_script_path, 0o755)
@@ -121,10 +121,10 @@ class TestRepoOutput(TestRepo, abc.ABC):
return ec == 0
-OUTPUT_SCRIPT_SIMPLE = r'''#!/bin/sh -e
+OUTPUT_SCRIPT_SIMPLE = r"""#!/bin/sh -e
timestamp="$( date --iso-8601=ns )"
echo "A CI run happened at $timestamp"
-'''
+"""
class TestRepoOutputSimple(TestRepoOutput):
@@ -132,17 +132,17 @@ class TestRepoOutputSimple(TestRepoOutput):
@staticmethod
def codename():
- return 'output_simple'
+ return "output_simple"
def format_output_script(self):
return OUTPUT_SCRIPT_SIMPLE
def run_output_matches(self, output):
- return output.decode().startswith('A CI run happened at ')
+ return output.decode().startswith("A CI run happened at ")
-OUTPUT_SCRIPT_EMPTY = r'''#!/bin/sh
-'''
+OUTPUT_SCRIPT_EMPTY = r"""#!/bin/sh
+"""
class TestRepoOutputEmpty(TestRepoOutput):
@@ -150,7 +150,7 @@ class TestRepoOutputEmpty(TestRepoOutput):
@staticmethod
def codename():
- return 'output_empty'
+ return "output_empty"
def format_output_script(self):
return OUTPUT_SCRIPT_EMPTY
@@ -159,9 +159,9 @@ class TestRepoOutputEmpty(TestRepoOutput):
return len(output) == 0
-OUTPUT_SCRIPT_LONG = r'''#!/bin/sh -e
+OUTPUT_SCRIPT_LONG = r"""#!/bin/sh -e
dd if=/dev/urandom count={output_len_kb} bs=1024 | base64
-'''
+"""
class TestRepoOutputLong(TestRepoOutput):
@@ -171,7 +171,7 @@ class TestRepoOutputLong(TestRepoOutput):
@staticmethod
def codename():
- return 'output_long'
+ return "output_long"
def format_output_script(self):
output_len = TestRepoOutputLong.OUTPUT_LEN_KB
@@ -182,18 +182,18 @@ class TestRepoOutputLong(TestRepoOutput):
return len(output) > TestRepoOutputLong.OUTPUT_LEN_KB * 1024
-OUTPUT_SCRIPT_NULL = r'''#!/usr/bin/env python3
+OUTPUT_SCRIPT_NULL = r"""#!/usr/bin/env python3
output = {output}
import sys
sys.stdout.buffer.write(output)
sys.exit(-2)
-'''
+"""
class TestRepoOutputNull(TestRepoOutput):
__test__ = False
- OUTPUT = b'123\x00456\x00789'
+ OUTPUT = b"123\x00456\x00789"
def __init__(self, *args, **kwargs):
assert len(TestRepoOutputNull.OUTPUT) == 11
@@ -202,7 +202,7 @@ class TestRepoOutputNull(TestRepoOutput):
@staticmethod
def codename():
- return 'output_null'
+ return "output_null"
def format_output_script(self):
return OUTPUT_SCRIPT_NULL.format(output=repr(self.output))
@@ -223,7 +223,7 @@ class TestRepoSegfault(TestRepo):
@staticmethod
def codename():
- return 'segfault'
+ return "segfault"
def write_ci_script(self):
shutil.copy(self.prog_path, self.ci_script_path)
diff --git a/test/src/lib/tests.py b/test/src/lib/tests.py
index b20ecc5..c71a3ea 100644
--- a/test/src/lib/tests.py
+++ b/test/src/lib/tests.py
@@ -9,17 +9,17 @@ import pytest
# Reference: https://github.com/pytest-dev/pytest/issues/3628
# Automatic generation of readable test IDs.
def my_parametrize(names, values, ids=None, **kwargs):
- _names = names.split(',') if isinstance(names, str) else names
+ _names = names.split(",") if isinstance(names, str) else names
if not ids:
if len(_names) == 1:
- ids = [f'{names}={v}' for v in values]
+ ids = [f"{names}={v}" for v in values]
else:
_values = [
- combination.values if hasattr(combination, 'values') else combination
+ combination.values if hasattr(combination, "values") else combination
for combination in values
]
ids = [
- '-'.join(f'{k}={v}' for k, v in zip(_names, combination))
+ "-".join(f"{k}={v}" for k, v in zip(_names, combination))
for combination in _values
]
return pytest.mark.parametrize(names, values, ids=ids, **kwargs)
diff --git a/test/src/test_basic.py b/test/src/test_basic.py
index 26732fe..d092e1d 100644
--- a/test/src/test_basic.py
+++ b/test/src/test_basic.py
@@ -7,58 +7,58 @@ import re
def _test_cmd_line_version_internal(cmd_line, name, version):
- for flag in ('--version', '-V'):
- output = cmd_line.run(flag).removesuffix('\n')
- match = re.match(r'^cimple-(\w+) v(\d+\.\d+\.\d+) \([0-9a-f]{40,}\)$', output)
- assert match, f'Invalid {flag} output:\n{output}'
+ for flag in ("--version", "-V"):
+ output = cmd_line.run(flag).removesuffix("\n")
+ match = re.match(r"^cimple-(\w+) v(\d+\.\d+\.\d+) \([0-9a-f]{40,}\)$", output)
+ assert match, f"Invalid {flag} output:\n{output}"
assert match.group(1) == name
assert match.group(2) == version
def test_cmd_line_version(server_exe, worker_exe, client_exe, version):
- _test_cmd_line_version_internal(server_exe, 'server', version)
- _test_cmd_line_version_internal(worker_exe, 'worker', version)
- _test_cmd_line_version_internal(client_exe, 'client', version)
+ _test_cmd_line_version_internal(server_exe, "server", version)
+ _test_cmd_line_version_internal(worker_exe, "worker", version)
+ _test_cmd_line_version_internal(client_exe, "client", version)
def _test_cmd_line_help_internal(cmd_line, name):
- for flag in ('--help', '-h'):
- output = cmd_line.run(flag).removesuffix('\n')
- match = re.match(r'^usage: cimple-(\w+) ', output)
- assert match, f'Invalid {flag} output:\n{output}'
+ for flag in ("--help", "-h"):
+ output = cmd_line.run(flag).removesuffix("\n")
+ match = re.match(r"^usage: cimple-(\w+) ", output)
+ assert match, f"Invalid {flag} output:\n{output}"
assert match.group(1) == name
def test_cmd_line_help(server_exe, worker_exe, client_exe):
- _test_cmd_line_help_internal(server_exe, 'server')
- _test_cmd_line_help_internal(worker_exe, 'worker')
- _test_cmd_line_help_internal(client_exe, 'client')
+ _test_cmd_line_help_internal(server_exe, "server")
+ _test_cmd_line_help_internal(worker_exe, "worker")
+ _test_cmd_line_help_internal(client_exe, "client")
def _test_cmd_line_invalid_option_internal(cmd_line, name):
- for args in (['-x'], ['--invalid', 'value']):
+ for args in (["-x"], ["--invalid", "value"]):
ec, output = cmd_line.try_run(*args)
- assert ec != 0, f'Invalid exit code {ec}, output:\n{output}'
+ assert ec != 0, f"Invalid exit code {ec}, output:\n{output}"
def test_cmd_line_invalid_option(server_exe, worker_exe, client_exe):
- _test_cmd_line_invalid_option_internal(server_exe, 'server')
- _test_cmd_line_invalid_option_internal(worker_exe, 'worker')
- _test_cmd_line_invalid_option_internal(client_exe, 'client')
+ _test_cmd_line_invalid_option_internal(server_exe, "server")
+ _test_cmd_line_invalid_option_internal(worker_exe, "worker")
+ _test_cmd_line_invalid_option_internal(client_exe, "client")
def test_run_client_no_action(client):
ec, output = client.try_run()
- assert ec != 0, f'Invalid exit code {ec}, output:\n{output}'
- prefix = 'usage error: no action specified\n'
- assert output.startswith(prefix), f'Invalid output:\n{output}'
+ assert ec != 0, f"Invalid exit code {ec}, output:\n{output}"
+ prefix = "usage error: no action specified\n"
+ assert output.startswith(prefix), f"Invalid output:\n{output}"
def test_run_client_invalid_request(server, client):
- ec, output = client.try_run('hello')
- assert ec != 0, f'Invalid exit code {ec}, output:\n{output}'
- prefix = 'usage error: invalid request\n'
- assert output.startswith(prefix), f'Invalid output:\n{output}'
+ ec, output = client.try_run("hello")
+ assert ec != 0, f"Invalid exit code {ec}, output:\n{output}"
+ prefix = "usage error: invalid request\n"
+ assert output.startswith(prefix), f"Invalid output:\n{output}"
def test_run_noop_server(server):
diff --git a/test/src/test_repo.py b/test/src/test_repo.py
index ef45103..419dd1f 100644
--- a/test/src/test_repo.py
+++ b/test/src/test_repo.py
@@ -18,7 +18,7 @@ from lib.tests import my_parametrize
def test_sigsegv(sigsegv):
ec, output = sigsegv.try_run()
assert ec == -11
- assert output.startswith('Started the test program.\n')
+ assert output.startswith("Started the test program.\n")
assert "You shouldn't see this." not in output
@@ -26,7 +26,7 @@ class LoggingEventRunComplete(LoggingEvent):
def __init__(self, target):
self.counter = 0
self.target = target
- self.re = re.compile(r'run \d+ as finished')
+ self.re = re.compile(r"run \d+ as finished")
super().__init__(timeout=150)
def log_line_matches(self, line):
@@ -40,9 +40,9 @@ class LoggingEventRunComplete(LoggingEvent):
def client_runner_process(log_queue, client, runs_per_process, repo):
with configure_logging_in_child(log_queue):
- logging.info('Executing %s clients', runs_per_process)
+ logging.info("Executing %s clients", runs_per_process)
for i in range(runs_per_process):
- client.run('queue-run', repo.path, 'HEAD')
+ client.run("queue-run", repo.path, "HEAD")
def _test_repo_internal(env, repo, numof_processes, runs_per_process):
@@ -53,7 +53,7 @@ def _test_repo_internal(env, repo, numof_processes, runs_per_process):
env.server.logger.add_event(event)
with child_logging_thread() as log_queue:
- ctx = mp.get_context('spawn')
+ ctx = mp.get_context("spawn")
args = (log_queue, env.client, runs_per_process, repo)
processes = [
ctx.Process(target=client_runner_process, args=args)
@@ -72,33 +72,33 @@ def _test_repo_internal(env, repo, numof_processes, runs_per_process):
assert numof_runs == len(runs)
for id, status, ec, output, url, rev in runs:
- assert status == 'finished', f'Invalid status for run {id}: {status}'
+ assert status == "finished", f"Invalid status for run {id}: {status}"
assert repo.run_exit_code_matches(ec), f"Exit code doesn't match: {ec}"
assert repo.run_output_matches(output), f"Output doesn't match: {output}"
- runs = env.client.run('get-runs')
- runs = json.loads(runs)['result']
+ runs = env.client.run("get-runs")
+ runs = json.loads(runs)["result"]
assert len(runs) == numof_runs
for run in runs:
- id = run['id']
- ec = run['exit_code']
+ id = run["id"]
+ ec = run["exit_code"]
assert repo.run_exit_code_matches(ec), f"Exit code doesn't match: {ec}"
# Not implemented yet:
- assert 'status' not in run
- assert 'output' not in run
+ assert "status" not in run
+ assert "output" not in run
-@my_parametrize('runs_per_client', [1, 5])
-@my_parametrize('numof_clients', [1, 5])
+@my_parametrize("runs_per_client", [1, 5])
+@my_parametrize("numof_clients", [1, 5])
def test_repo(env, test_repo, numof_clients, runs_per_client):
_test_repo_internal(env, test_repo, numof_clients, runs_per_client)
@pytest.mark.stress
@my_parametrize(
- 'numof_clients,runs_per_client',
+ "numof_clients,runs_per_client",
[
(10, 50),
(1, 2000),