diff options
Diffstat (limited to 'test/config.py')
-rw-r--r-- | test/config.py | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/test/config.py b/test/config.py new file mode 100644 index 00000000000..b91973f7f95 --- /dev/null +++ b/test/config.py @@ -0,0 +1,290 @@ +import argparse +import os +import psutil +import textwrap +import time + + +def positive_int_or_default(default): + def positive_integer(v): + if v is None or v == "": + return default + return int(v) + return positive_integer + + +def positive_int_or_auto(v): + if v is None or v in ("", "auto"): + return "auto" + if int(v) <= 0: + raise ValueError("value must be positive or auto") + return int(v) + + +def int_or_auto(v): + if v is None or v in ("", "auto"): + return "auto" + if int(v) < 0: + raise ValueError("value must be positive or auto") + return int(v) + + +def int_choice_or_default(options, default): + assert default in options + + def choice(v): + if v is None or v == "": + return default + if int(v) in options: + return int(v) + raise ValueError("invalid choice") + return choice + + +def worker_config(v): + if v is None or v == "": + return 0 + if v.startswith("workers "): + return(int(v.split(" ")[1])) + return int(v) + + +def directory(v): + if not os.path.isdir(v): + raise ValueError(f"provided path '{v}' doesn't exist " + "or is not a directory") + return v + + +def directory_verify_or_create(v): + if not os.path.isdir(v): + os.mkdir(v) + return v + + +parser = argparse.ArgumentParser(description="VPP unit tests", + formatter_class=argparse.RawTextHelpFormatter) + +parser.add_argument("--failfast", action="store_true", + help="stop running tests on first failure") + +parser.add_argument("--test-src-dir", action="append", type=directory, + help="directory containing test files " + "(may be specified multiple times) " + "(VPP_WS_DIR/test is added automatically to the set)") + +default_verbose = 0 + +parser.add_argument("--verbose", action="store", default=default_verbose, + type=int_choice_or_default((0, 1, 2), default_verbose), + help="verbosity setting - 0 - least verbose, " + "2 - most verbose (default: 0)") + +default_test_run_timeout = 600 + +parser.add_argument("--timeout", action="store", + type=positive_int_or_default(default_test_run_timeout), + default=default_test_run_timeout, + metavar="TEST_RUN_TIMEOUT", + help="test run timeout in seconds - per test " + f"(default: {default_test_run_timeout})") + +parser.add_argument("--failed-dir", action="store", type=directory, + help="directory containing failed tests") + +filter_help_string = """\ +expression consists of 3 string selectors separated by '.' separators: + + <file>.<class>.<function> + +- selectors restrict which files/classes/functions are run +- selector can be replaced with '*' or omitted entirely if not needed +- <file> selector is automatically prepended with 'test_' if required +- '.' separators are required only if selector(s) follow(s) + +examples: + +1. all of the following expressions are equivalent and will select + all test classes and functions from test_bfd.py: + 'test_bfd' 'bfd' 'test_bfd..' 'bfd.' 'bfd.*.*' 'test_bfd.*.*' +2. 'bfd.BFDAPITestCase' selects all tests from test_bfd.py, + which are part of BFDAPITestCase class +3. 'bfd.BFDAPITestCase.test_add_bfd' selects a single test named + test_add_bfd from test_bfd.py/BFDAPITestCase +4. '.*.test_add_bfd' selects all test functions named test_add_bfd + from all files/classes +""" +parser.add_argument("--filter", action="store", + metavar="FILTER_EXPRESSION", help=filter_help_string) + +default_retries = 0 + +parser.add_argument("--retries", action="store", default=default_retries, + type=positive_int_or_default(default_retries), + help="retry failed tests RETRIES times") + +parser.add_argument("--step", action="store_true", default=False, + help="enable stepping through tests") + +debug_help_string = """\ +attach - attach to already running vpp +core - detect coredump and load core in gdb on crash +gdb - print VPP PID and pause allowing attaching gdb +gdbserver - same as above, but run gdb in gdbserver +""" + +parser.add_argument("--debug", action="store", + choices=["attach", "core", "gdb", "gdbserver"], + help=debug_help_string) + +parser.add_argument("--debug-framework", action="store_true", + help="enable internal test framework debugging") + +parser.add_argument("--compress-core", action="store_true", + help="compress core files if not debugging them") + +parser.add_argument("--extended", action="store_true", + help="run extended tests") + +parser.add_argument("--sanity", action="store_true", + help="perform sanity vpp run before running tests") + +parser.add_argument("--force-foreground", action="store_true", + help="force running in foreground - don't fork") + +parser.add_argument("--jobs", action="store", type=positive_int_or_auto, + default="auto", help="maximum concurrent test jobs") + +parser.add_argument("--venv-dir", action="store", + type=directory, help="path to virtual environment") + +default_rnd_seed = time.time() +parser.add_argument("--rnd-seed", action="store", default=default_rnd_seed, + type=positive_int_or_default(default_rnd_seed), + help="random generator seed (default: current time)") + +parser.add_argument("--vpp-worker-count", action="store", type=worker_config, + default=0, help="number of vpp workers") + +parser.add_argument("--gcov", action="store_true", + default=False, help="running gcov tests") + +parser.add_argument("--cache-vpp-output", action="store_true", default=False, + help="cache VPP stdout/stderr and log as one block " + "after test finishes") + +parser.add_argument("--vpp-ws-dir", action="store", required=True, + type=directory, help="vpp workspace directory") + +parser.add_argument("--vpp-tag", action="store", default="vpp_debug", + metavar="VPP_TAG", required=True, + help="vpp tag (e.g. vpp, vpp_debug, vpp_gcov)") + +parser.add_argument("--vpp", action="store", help="path to vpp binary " + "(default: derive from VPP_WS_DIR and VPP_TAG)") + +parser.add_argument("--vpp-install-dir", type=directory, + action="store", help="path to vpp install directory" + "(default: derive from VPP_WS_DIR and VPP_TAG)") + +parser.add_argument("--vpp-build-dir", action="store", type=directory, + help="vpp build directory" + "(default: derive from VPP_WS_DIR and VPP_TAG)") + +parser.add_argument("--vpp-plugin-dir", action="append", type=directory, + help="directory containing vpp plugins" + "(default: derive from VPP_WS_DIR and VPP_TAG)") + +parser.add_argument("--vpp-test-plugin-dir", action="append", type=directory, + help="directory containing vpp api test plugins" + "(default: derive from VPP_WS_DIR and VPP_TAG)") + +parser.add_argument("--extern-plugin-dir", action="append", type=directory, + default=[], help="directory containing external plugins") + +parser.add_argument("--coredump-size", action="store", default="unlimited", + help="specify vpp coredump size") + +parser.add_argument("--max-vpp-cpus", action="store", type=int_or_auto, + default=0, help="max cpus used by vpp") + +variant_help_string = """\ +specify which march node variant to unit test + e.g. --variant=skx - test the skx march variants + e.g. --variant=icl - test the icl march variants +""" + +parser.add_argument("--variant", action="store", help=variant_help_string) + +parser.add_argument("--api-fuzz", action="store", default=None, + help="specify api fuzzing parameters") + +parser.add_argument("--wipe-tmp-dir", action="store_true", default=True, + help="remove test tmp directory before running test") + +parser.add_argument("--tmp-dir", action="store", default="/tmp", + type=directory_verify_or_create, + help="directory where to store test temporary directories") + +parser.add_argument("--log-dir", action="store", + type=directory_verify_or_create, + help="directory where to store directories " + "containing log files (default: --tmp-dir)") + +default_keep_pcaps = False +parser.add_argument("--keep-pcaps", action="store_true", + default=default_keep_pcaps, + help="if set, keep all pcap files from a test run" + f" (default: {default_keep_pcaps})") + +config = parser.parse_args() + +ws = config.vpp_ws_dir +br = f"{ws}/build-root" +tag = config.vpp_tag + +if config.vpp_install_dir is None: + config.vpp_install_dir = f"{br}/install-{tag}-native" + +if config.vpp is None: + config.vpp = f"{config.vpp_install_dir}/vpp/bin/vpp" + +if config.vpp_build_dir is None: + config.vpp_build_dir = f"{br}/build-{tag}-native" + +libs = ["lib", "lib64"] + +if config.vpp_plugin_dir is None: + config.vpp_plugin_dir = [ + f"{config.vpp_install_dir}/vpp/{lib}/vpp_plugins" for lib in libs] + +if config.vpp_test_plugin_dir is None: + config.vpp_test_plugin_dir = [ + f"{config.vpp_install_dir}/vpp/{lib}/vpp_api_test_plugins" + for lib in libs] + +test_dirs = [f"{ws}/test"] + +if config.test_src_dir is not None: + test_dirs.extend(config.test_src_dir) + +config.test_src_dir = test_dirs + + +if config.venv_dir is None: + config.venv_dir = f"{ws}/test/venv" + +available_cpus = psutil.Process().cpu_affinity() +num_cpus = len(available_cpus) + +if config.max_vpp_cpus == 'auto': + max_vpp_cpus = num_cpus +elif config.max_vpp_cpus > 0: + max_vpp_cpus = min(config.max_vpp_cpus, num_cpus) +else: + max_vpp_cpus = num_cpus + +if __name__ == "__main__": + print("Provided arguments:") + for i in config.__dict__: + print(f" {i} is {config.__dict__[i]}") |