From d3726bd6600e2fe8837b751642aaf675bce8acaf Mon Sep 17 00:00:00 2001 From: dekken Date: Sat, 10 Feb 2024 17:02:23 +0100 Subject: [PATCH] save/load dill test batches --- phlop/procs/runtimer.py | 3 ++- phlop/run/test_cases.py | 32 ++++++++++++++++++++++++++- phlop/testing/test_cases.py | 43 +++++++++++++++++++++++++++++++------ pyproject.toml | 4 ++-- setup.py | 2 +- tests/all_concurrent.py | 2 +- 6 files changed, 74 insertions(+), 12 deletions(-) diff --git a/phlop/procs/runtimer.py b/phlop/procs/runtimer.py index b213fb1..61a3ee0 100644 --- a/phlop/procs/runtimer.py +++ b/phlop/procs/runtimer.py @@ -17,7 +17,7 @@ class RunTimer: def __init__( self, cmd, - shell=True, + shell=False, capture_output=True, check=False, print_cmd=True, @@ -51,6 +51,7 @@ def run(): check=check, env=benv, capture_output=capture_output, + close_fds=True, **kwargs, **ekwargs, ) diff --git a/phlop/run/test_cases.py b/phlop/run/test_cases.py index 20e8568..8e7c81f 100644 --- a/phlop/run/test_cases.py +++ b/phlop/run/test_cases.py @@ -29,6 +29,8 @@ def cli_args_parser(): print_only="Print only, no execution", prefix="Prepend string to execution string", postfix="Append string to execution string", + dump="Dump discovered tests as YAML, no execution", + load="Run tests exported from dump", ) parser = argparse.ArgumentParser() @@ -42,6 +44,12 @@ def cli_args_parser(): ) parser.add_argument("--prefix", default="", help=_help.prefix) parser.add_argument("--postfix", default="", help=_help.postfix) + + parser.add_argument( + "--dump", default=None, action="store", nargs="?", help=_help.dump + ) + parser.add_argument("--load", default=None, help=_help.load) + return parser @@ -70,15 +78,37 @@ def get_test_cases(cli_args): ) +def dump_batches(cli_args): + import codecs + + import dill + + with open(cli_args.dump, "w") as f: + f.write( + codecs.encode( + dill.dumps(pp.TestBatchesList(batch_list=get_test_cases(cli_args))), + "hex", + ).decode("utf8") + ) + + def main(): parser = cli_args_parser() cli_args = verify_cli_args(parser.parse_args()) try: + if cli_args.dump and cli_args.load: + raise ValueError("Cannot use 'dump' and 'load' options simultaneously.") + + if cli_args.dump: + dump_batches(cli_args) + return + pp.process( - get_test_cases(cli_args), + pp.extract_load(cli_args) if cli_args.load else get_test_cases(cli_args), n_cores=cli_args.cores, print_only=cli_args.print_only, ) + except (Exception, SystemExit) as e: logger.exception(e) parser.print_help() diff --git a/phlop/testing/test_cases.py b/phlop/testing/test_cases.py index 45e7e9c..e04d5dc 100644 --- a/phlop/testing/test_cases.py +++ b/phlop/testing/test_cases.py @@ -9,6 +9,7 @@ import unittest from dataclasses import dataclass, field from pathlib import Path +from typing import List from phlop.app.cmake import list_tests as get_cmake_tests from phlop.os import env_sep @@ -34,10 +35,10 @@ def __post_init__(self): self.cmd = self.cmd.strip() +@dataclass class TestBatch: - def __init__(self, tests, cores=1): - self.tests = tests - self.cores = cores + tests: list + cores: int class DefaultTestCaseExtractor: @@ -127,12 +128,9 @@ def load_py_test_cases_from_cmake(ctest_test): def determine_cores_for_test_case(test_case): - cores = 1 - try: if "mpirun -n" in test_case.cmd: bits = test_case.cmd.split(" ") - # print(bits) idx = [i for i, x in enumerate(bits) if "mpirun" in x][0] test_case.cores = int(bits[idx + 2]) except Exception as e: @@ -181,3 +179,36 @@ def _add(test_cases): break return [TestBatch(v, k) for k, v in test_batches.items()] + + +@dataclass +class TestBatchesList: + batch_list: List[TestBatch] + + +def deserialize(s): + import codecs + + import dill + + return dill.loads(codecs.decode(s, "hex")) + + +def extract_load(cli_args): + test_batches = {} + + file_paths = list(Path(cli_args.dir).glob(cli_args.load)) + + if not file_paths: + raise ValueError("No load files found") + + for path in file_paths: + with open(path, "r") as file: + batch_list = deserialize(file.read()).batch_list + for batch in batch_list: + for test_case in batch.tests: + if batch.cores not in test_batches: + test_batches[test_case.cores] = [] + test_batches[test_case.cores].append(test_case) + + return [TestBatch(v, k) for k, v in test_batches.items()] diff --git a/pyproject.toml b/pyproject.toml index e0877c8..7e3c34e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "phlop" -version = "0.0.9" +version = "0.0.10" dependencies = [ @@ -21,6 +21,6 @@ classifiers = [ [build-system] requires = [ - "setuptools>=42", "wheel", "packaging", + "setuptools>=42", "wheel", "packaging", "dill" ] diff --git a/setup.py b/setup.py index 6684083..bff2dae 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name="phlop", - version="0.0.9", + version="0.0.10", cmdclass={}, classifiers=[], include_package_data=True, diff --git a/tests/all_concurrent.py b/tests/all_concurrent.py index 243caa9..24477d0 100644 --- a/tests/all_concurrent.py +++ b/tests/all_concurrent.py @@ -23,4 +23,4 @@ def get_test_classes(): if __name__ == "__main__": - pp.process(pp.TestBatch(get_test_classes()), n_cores=N_CORES, print_only=PRINT) + pp.process(pp.TestBatch(get_test_classes(), 1), n_cores=N_CORES, print_only=PRINT)