1995fb337SOwen Hilyard# SPDX-License-Identifier: BSD-3-Clause 2995fb337SOwen Hilyard# Copyright(c) 2010-2021 Intel Corporation 378534506SJuraj Linkeš# Copyright(c) 2022-2023 PANTHEON.tech s.r.o. 4995fb337SOwen Hilyard# Copyright(c) 2022 University of New Hampshire 57f86be25SLuca Vizzarro# Copyright(c) 2024 Arm Limited 6995fb337SOwen Hilyard 76ef07151SJuraj Linkeš"""Environment variables and command line arguments parsing. 86ef07151SJuraj Linkeš 96ef07151SJuraj LinkešThis is a simple module utilizing the built-in argparse module to parse command line arguments, 106ef07151SJuraj Linkešaugment them with values from environment variables and make them available across the framework. 116ef07151SJuraj Linkeš 126ef07151SJuraj LinkešThe command line value takes precedence, followed by the environment variable value, 136ef07151SJuraj Linkešfollowed by the default value defined in this module. 146ef07151SJuraj Linkeš 156ef07151SJuraj LinkešThe command line arguments along with the supported environment variables are: 166ef07151SJuraj Linkeš 176ef07151SJuraj Linkeš.. option:: --config-file 186ef07151SJuraj Linkeš.. envvar:: DTS_CFG_FILE 196ef07151SJuraj Linkeš 206ef07151SJuraj Linkeš The path to the YAML test run configuration file. 216ef07151SJuraj Linkeš 226ef07151SJuraj Linkeš.. option:: --output-dir, --output 236ef07151SJuraj Linkeš.. envvar:: DTS_OUTPUT_DIR 246ef07151SJuraj Linkeš 256ef07151SJuraj Linkeš The directory where DTS logs and results are saved. 266ef07151SJuraj Linkeš 276ef07151SJuraj Linkeš.. option:: --compile-timeout 286ef07151SJuraj Linkeš.. envvar:: DTS_COMPILE_TIMEOUT 296ef07151SJuraj Linkeš 306ef07151SJuraj Linkeš The timeout for compiling DPDK. 316ef07151SJuraj Linkeš 326ef07151SJuraj Linkeš.. option:: -t, --timeout 336ef07151SJuraj Linkeš.. envvar:: DTS_TIMEOUT 346ef07151SJuraj Linkeš 356ef07151SJuraj Linkeš The timeout for all DTS operation except for compiling DPDK. 366ef07151SJuraj Linkeš 376ef07151SJuraj Linkeš.. option:: -v, --verbose 386ef07151SJuraj Linkeš.. envvar:: DTS_VERBOSE 396ef07151SJuraj Linkeš 406ef07151SJuraj Linkeš Set to any value to enable logging everything to the console. 416ef07151SJuraj Linkeš 42f9957667STomáš Ďurovec.. option:: --dpdk-tree 43f9957667STomáš Ďurovec.. envvar:: DTS_DPDK_TREE 446ef07151SJuraj Linkeš 45187a9447STomáš Ďurovec The path to the DPDK source tree directory to test. Cannot be used in conjunction with 46187a9447STomáš Ďurovec --tarball. 476ef07151SJuraj Linkeš 48a23f2245SLuca Vizzarro.. option:: --tarball, --snapshot 496ef07151SJuraj Linkeš.. envvar:: DTS_DPDK_TARBALL 506ef07151SJuraj Linkeš 51f9957667STomáš Ďurovec The path to the DPDK source tarball to test. DPDK must be contained in a folder with the same 52187a9447STomáš Ďurovec name as the tarball file. Cannot be used in conjunction with --dpdk-tree. 53f9957667STomáš Ďurovec 54f9957667STomáš Ďurovec.. option:: --remote-source 55f9957667STomáš Ďurovec.. envvar:: DTS_REMOTE_SOURCE 56f9957667STomáš Ďurovec 57f9957667STomáš Ďurovec Set this option if either the DPDK source tree or tarball to be used are located on the SUT 58f9957667STomáš Ďurovec node. Can only be used with --dpdk-tree or --tarball. 59f9957667STomáš Ďurovec 60f9957667STomáš Ďurovec.. option:: --precompiled-build-dir 61f9957667STomáš Ďurovec.. envvar:: DTS_PRECOMPILED_BUILD_DIR 62f9957667STomáš Ďurovec 63*b935bdc3SLuca Vizzarro Define the subdirectory under the DPDK tree root directory or tarball where the pre-compiled 64*b935bdc3SLuca Vizzarro binaries are located. 656ef07151SJuraj Linkeš 664a4678c7SJuraj Linkeš.. option:: --test-suite 674a4678c7SJuraj Linkeš.. envvar:: DTS_TEST_SUITES 686ef07151SJuraj Linkeš 694a4678c7SJuraj Linkeš A test suite with test cases which may be specified multiple times. 704a4678c7SJuraj Linkeš In the environment variable, the suites are joined with a comma. 716ef07151SJuraj Linkeš 726ef07151SJuraj Linkeš.. option:: --re-run, --re_run 736ef07151SJuraj Linkeš.. envvar:: DTS_RERUN 746ef07151SJuraj Linkeš 756ef07151SJuraj Linkeš Re-run each test case this many times in case of a failure. 766ef07151SJuraj Linkeš 77cfe40bacSLuca Vizzarro.. option:: --random-seed 78cfe40bacSLuca Vizzarro.. envvar:: DTS_RANDOM_SEED 79cfe40bacSLuca Vizzarro 80cfe40bacSLuca Vizzarro The seed to use with the pseudo-random generator. If not specified, the configuration value is 81cfe40bacSLuca Vizzarro used instead. If that's also not specified, a random seed is generated. 82cfe40bacSLuca Vizzarro 836ef07151SJuraj LinkešThe module provides one key module-level variable: 846ef07151SJuraj Linkeš 856ef07151SJuraj LinkešAttributes: 866ef07151SJuraj Linkeš SETTINGS: The module level variable storing framework-wide DTS settings. 876ef07151SJuraj Linkeš 886ef07151SJuraj LinkešTypical usage example:: 896ef07151SJuraj Linkeš 906ef07151SJuraj Linkeš from framework.settings import SETTINGS 916ef07151SJuraj Linkeš foo = SETTINGS.foo 926ef07151SJuraj Linkeš""" 936ef07151SJuraj Linkeš 94995fb337SOwen Hilyardimport argparse 95995fb337SOwen Hilyardimport os 967f86be25SLuca Vizzarroimport sys 977f86be25SLuca Vizzarrofrom argparse import Action, ArgumentDefaultsHelpFormatter, _get_action_name 98840b1e01SJuraj Linkešfrom dataclasses import dataclass, field 99680d8a24SJuraj Linkešfrom pathlib import Path 1007f86be25SLuca Vizzarrofrom typing import Callable 101995fb337SOwen Hilyard 102*b935bdc3SLuca Vizzarrofrom pydantic import ValidationError 103*b935bdc3SLuca Vizzarro 104*b935bdc3SLuca Vizzarrofrom .config import ( 105*b935bdc3SLuca Vizzarro DPDKLocation, 106*b935bdc3SLuca Vizzarro LocalDPDKTarballLocation, 107*b935bdc3SLuca Vizzarro LocalDPDKTreeLocation, 108*b935bdc3SLuca Vizzarro RemoteDPDKTarballLocation, 109*b935bdc3SLuca Vizzarro RemoteDPDKTreeLocation, 110*b935bdc3SLuca Vizzarro TestSuiteConfig, 111*b935bdc3SLuca Vizzarro) 112680d8a24SJuraj Linkeš 113995fb337SOwen Hilyard 114840b1e01SJuraj Linkeš@dataclass(slots=True) 115840b1e01SJuraj Linkešclass Settings: 1166ef07151SJuraj Linkeš """Default framework-wide user settings. 1176ef07151SJuraj Linkeš 1186ef07151SJuraj Linkeš The defaults may be modified at the start of the run. 1196ef07151SJuraj Linkeš """ 1206ef07151SJuraj Linkeš 1216ef07151SJuraj Linkeš #: 122840b1e01SJuraj Linkeš config_file_path: Path = Path(__file__).parent.parent.joinpath("conf.yaml") 1236ef07151SJuraj Linkeš #: 124840b1e01SJuraj Linkeš output_dir: str = "output" 1256ef07151SJuraj Linkeš #: 126840b1e01SJuraj Linkeš timeout: float = 15 1276ef07151SJuraj Linkeš #: 128840b1e01SJuraj Linkeš verbose: bool = False 1296ef07151SJuraj Linkeš #: 130f9957667STomáš Ďurovec dpdk_location: DPDKLocation | None = None 1316ef07151SJuraj Linkeš #: 132*b935bdc3SLuca Vizzarro precompiled_build_dir: str | None = None 133*b935bdc3SLuca Vizzarro #: 134840b1e01SJuraj Linkeš compile_timeout: float = 1200 1356ef07151SJuraj Linkeš #: 1364a4678c7SJuraj Linkeš test_suites: list[TestSuiteConfig] = field(default_factory=list) 1376ef07151SJuraj Linkeš #: 138840b1e01SJuraj Linkeš re_run: int = 0 139cfe40bacSLuca Vizzarro #: 140cfe40bacSLuca Vizzarro random_seed: int | None = None 141840b1e01SJuraj Linkeš 142840b1e01SJuraj Linkeš 143840b1e01SJuraj LinkešSETTINGS: Settings = Settings() 144995fb337SOwen Hilyard 145995fb337SOwen Hilyard 1467f86be25SLuca Vizzarro#: Attribute name representing the env variable name to augment :class:`~argparse.Action` with. 1477f86be25SLuca Vizzarro_ENV_VAR_NAME_ATTR = "env_var_name" 1487f86be25SLuca Vizzarro#: Attribute name representing the value origin to augment :class:`~argparse.Action` with. 1497f86be25SLuca Vizzarro_IS_FROM_ENV_ATTR = "is_from_env" 1507f86be25SLuca Vizzarro 1517f86be25SLuca Vizzarro#: The prefix to be added to all of the environment variables. 1527f86be25SLuca Vizzarro_ENV_PREFIX = "DTS_" 1537f86be25SLuca Vizzarro 1547f86be25SLuca Vizzarro 1557f86be25SLuca Vizzarrodef _make_env_var_name(action: Action, env_var_name: str | None) -> str: 1567f86be25SLuca Vizzarro """Make and assign an environment variable name to the given action.""" 1577f86be25SLuca Vizzarro env_var_name = f"{_ENV_PREFIX}{env_var_name or action.dest.upper()}" 1587f86be25SLuca Vizzarro setattr(action, _ENV_VAR_NAME_ATTR, env_var_name) 1597f86be25SLuca Vizzarro return env_var_name 1607f86be25SLuca Vizzarro 1617f86be25SLuca Vizzarro 1627f86be25SLuca Vizzarrodef _get_env_var_name(action: Action) -> str | None: 1637f86be25SLuca Vizzarro """Get the environment variable name of the given action.""" 1647f86be25SLuca Vizzarro return getattr(action, _ENV_VAR_NAME_ATTR, None) 1657f86be25SLuca Vizzarro 1667f86be25SLuca Vizzarro 1677f86be25SLuca Vizzarrodef _set_is_from_env(action: Action) -> None: 1687f86be25SLuca Vizzarro """Make the environment the given action's value origin.""" 1697f86be25SLuca Vizzarro setattr(action, _IS_FROM_ENV_ATTR, True) 1707f86be25SLuca Vizzarro 1717f86be25SLuca Vizzarro 1727f86be25SLuca Vizzarrodef _is_from_env(action: Action) -> bool: 1737f86be25SLuca Vizzarro """Check if the given action's value originated from the environment.""" 1747f86be25SLuca Vizzarro return getattr(action, _IS_FROM_ENV_ATTR, False) 1757f86be25SLuca Vizzarro 1767f86be25SLuca Vizzarro 1777f86be25SLuca Vizzarrodef _is_action_in_args(action: Action) -> bool: 1787f86be25SLuca Vizzarro """Check if the action is invoked in the command line arguments.""" 1797f86be25SLuca Vizzarro for option in action.option_strings: 1807f86be25SLuca Vizzarro if option in sys.argv: 1817f86be25SLuca Vizzarro return True 1827f86be25SLuca Vizzarro return False 1837f86be25SLuca Vizzarro 1847f86be25SLuca Vizzarro 1857f86be25SLuca Vizzarrodef _add_env_var_to_action( 1867f86be25SLuca Vizzarro action: Action, 1877f86be25SLuca Vizzarro env_var_name: str | None = None, 1887f86be25SLuca Vizzarro) -> None: 1897f86be25SLuca Vizzarro """Add an argument with an environment variable to the parser.""" 1907f86be25SLuca Vizzarro env_var_name = _make_env_var_name(action, env_var_name) 1917f86be25SLuca Vizzarro 1927f86be25SLuca Vizzarro if not _is_action_in_args(action): 1937f86be25SLuca Vizzarro env_var_value = os.environ.get(env_var_name) 1947f86be25SLuca Vizzarro if env_var_value is not None: 1957f86be25SLuca Vizzarro _set_is_from_env(action) 1967f86be25SLuca Vizzarro sys.argv[1:0] = [action.format_usage(), env_var_value] 1977f86be25SLuca Vizzarro 1987f86be25SLuca Vizzarro 1997f86be25SLuca Vizzarroclass _DTSArgumentParser(argparse.ArgumentParser): 2007f86be25SLuca Vizzarro """ArgumentParser with a custom error message. 2017f86be25SLuca Vizzarro 2027f86be25SLuca Vizzarro This custom version of ArgumentParser changes the error message to accurately reflect the origin 2037f86be25SLuca Vizzarro of the value of its arguments. If it was supplied through the command line nothing changes, but 2047f86be25SLuca Vizzarro if it was supplied as an environment variable this is correctly communicated. 2057f86be25SLuca Vizzarro """ 2067f86be25SLuca Vizzarro 2077f86be25SLuca Vizzarro def find_action( 2087f86be25SLuca Vizzarro self, action_dest: str, filter_fn: Callable[[Action], bool] | None = None 2097f86be25SLuca Vizzarro ) -> Action | None: 2107f86be25SLuca Vizzarro """Find and return an action by its destination variable name. 2117f86be25SLuca Vizzarro 2127f86be25SLuca Vizzarro Arguments: 2137f86be25SLuca Vizzarro action_dest: the destination variable name of the action to find. 2147f86be25SLuca Vizzarro filter_fn: if an action is found it is passed to this filter function, which must 2157f86be25SLuca Vizzarro return a boolean value. 2167f86be25SLuca Vizzarro """ 2177f86be25SLuca Vizzarro it = (action for action in self._actions if action.dest == action_dest) 2187f86be25SLuca Vizzarro action = next(it, None) 2197f86be25SLuca Vizzarro 2207f86be25SLuca Vizzarro if action and filter_fn: 2217f86be25SLuca Vizzarro return action if filter_fn(action) else None 2227f86be25SLuca Vizzarro 2237f86be25SLuca Vizzarro return action 2247f86be25SLuca Vizzarro 2257f86be25SLuca Vizzarro def error(self, message): 2267f86be25SLuca Vizzarro """Augments :meth:`~argparse.ArgumentParser.error` with environment variable awareness.""" 2277f86be25SLuca Vizzarro for action in self._actions: 2287f86be25SLuca Vizzarro if _is_from_env(action): 2297f86be25SLuca Vizzarro action_name = _get_action_name(action) 2307f86be25SLuca Vizzarro env_var_name = _get_env_var_name(action) 2317f86be25SLuca Vizzarro env_var_value = os.environ.get(env_var_name) 2327f86be25SLuca Vizzarro 2337f86be25SLuca Vizzarro message = message.replace( 2347f86be25SLuca Vizzarro f"argument {action_name}", 2357f86be25SLuca Vizzarro f"environment variable {env_var_name} (value: {env_var_value})", 2367f86be25SLuca Vizzarro ) 2377f86be25SLuca Vizzarro 2387f86be25SLuca Vizzarro print(f"{self.prog}: error: {message}\n", file=sys.stderr) 2397f86be25SLuca Vizzarro self.exit(2, "For help and usage, " "run the command with the --help flag.\n") 2407f86be25SLuca Vizzarro 2417f86be25SLuca Vizzarro 2427f86be25SLuca Vizzarroclass _EnvVarHelpFormatter(ArgumentDefaultsHelpFormatter): 2437f86be25SLuca Vizzarro """Custom formatter to add environment variables to the help page.""" 2447f86be25SLuca Vizzarro 2457f86be25SLuca Vizzarro def _get_help_string(self, action): 2467f86be25SLuca Vizzarro """Overrides :meth:`ArgumentDefaultsHelpFormatter._get_help_string`.""" 2477f86be25SLuca Vizzarro help = super()._get_help_string(action) 2487f86be25SLuca Vizzarro 2497f86be25SLuca Vizzarro env_var_name = _get_env_var_name(action) 2507f86be25SLuca Vizzarro if env_var_name is not None: 2517f86be25SLuca Vizzarro help = f"[{env_var_name}] {help}" 2527f86be25SLuca Vizzarro 2537f86be25SLuca Vizzarro env_var_value = os.environ.get(env_var_name) 2547f86be25SLuca Vizzarro if env_var_value is not None: 2557f86be25SLuca Vizzarro help = f"{help} (env value: {env_var_value})" 2567f86be25SLuca Vizzarro 2577f86be25SLuca Vizzarro return help 2587f86be25SLuca Vizzarro 2597f86be25SLuca Vizzarro 260f9957667STomáš Ďurovecdef _required_with_one_of(parser: _DTSArgumentParser, action: Action, *required_dests: str) -> None: 261f9957667STomáš Ďurovec """Verify that `action` is listed together with at least one of `required_dests`. 262f9957667STomáš Ďurovec 263f9957667STomáš Ďurovec Verify that when `action` is among the command-line arguments or 264f9957667STomáš Ďurovec environment variables, at least one of `required_dests` is also among 265f9957667STomáš Ďurovec the command-line arguments or environment variables. 266f9957667STomáš Ďurovec 267f9957667STomáš Ďurovec Args: 268f9957667STomáš Ďurovec parser: The custom ArgumentParser object which contains `action`. 269f9957667STomáš Ďurovec action: The action to be verified. 270f9957667STomáš Ďurovec *required_dests: Destination variable names of the required arguments. 271f9957667STomáš Ďurovec 272f9957667STomáš Ďurovec Raises: 273f9957667STomáš Ďurovec argparse.ArgumentTypeError: When none of the required_dest are defined. 274f9957667STomáš Ďurovec 275f9957667STomáš Ďurovec Example: 276f9957667STomáš Ďurovec We have ``--option1`` and we only want it to be a passed alongside 277f9957667STomáš Ďurovec either ``--option2`` or ``--option3`` (meaning if ``--option1`` is 278f9957667STomáš Ďurovec passed without either ``--option2`` or ``--option3``, that's an error). 279f9957667STomáš Ďurovec 280f9957667STomáš Ďurovec parser = _DTSArgumentParser() 281f9957667STomáš Ďurovec option1_arg = parser.add_argument('--option1', dest='option1', action='store_true') 282f9957667STomáš Ďurovec option2_arg = parser.add_argument('--option2', dest='option2', action='store_true') 283f9957667STomáš Ďurovec option2_arg = parser.add_argument('--option3', dest='option3', action='store_true') 284f9957667STomáš Ďurovec 285f9957667STomáš Ďurovec _required_with_one_of(parser, option1_arg, 'option2', 'option3') 286f9957667STomáš Ďurovec """ 287f9957667STomáš Ďurovec if _is_action_in_args(action): 288f9957667STomáš Ďurovec for required_dest in required_dests: 289f9957667STomáš Ďurovec required_action = parser.find_action(required_dest) 290f9957667STomáš Ďurovec if required_action is None: 291f9957667STomáš Ďurovec continue 292f9957667STomáš Ďurovec 293f9957667STomáš Ďurovec if _is_action_in_args(required_action): 294f9957667STomáš Ďurovec return None 295f9957667STomáš Ďurovec 296f9957667STomáš Ďurovec raise argparse.ArgumentTypeError( 297f9957667STomáš Ďurovec f"The '{action.dest}' is required at least with one of '{', '.join(required_dests)}'." 298f9957667STomáš Ďurovec ) 299f9957667STomáš Ďurovec 300f9957667STomáš Ďurovec 3017f86be25SLuca Vizzarrodef _get_parser() -> _DTSArgumentParser: 3024a4678c7SJuraj Linkeš """Create the argument parser for DTS. 3034a4678c7SJuraj Linkeš 3044a4678c7SJuraj Linkeš Command line options take precedence over environment variables, which in turn take precedence 3054a4678c7SJuraj Linkeš over default values. 3064a4678c7SJuraj Linkeš 3074a4678c7SJuraj Linkeš Returns: 3087f86be25SLuca Vizzarro _DTSArgumentParser: The configured argument parser with defined options. 3094a4678c7SJuraj Linkeš """ 3107f86be25SLuca Vizzarro parser = _DTSArgumentParser( 311517b4b26SJuraj Linkeš description="Run DPDK test suites. All options may be specified with the environment " 312517b4b26SJuraj Linkeš "variables provided in brackets. Command line arguments have higher priority.", 3137f86be25SLuca Vizzarro formatter_class=_EnvVarHelpFormatter, 3147f86be25SLuca Vizzarro allow_abbrev=False, 31578534506SJuraj Linkeš ) 316995fb337SOwen Hilyard 3177f86be25SLuca Vizzarro action = parser.add_argument( 318995fb337SOwen Hilyard "--config-file", 3197f86be25SLuca Vizzarro default=SETTINGS.config_file_path, 320840b1e01SJuraj Linkeš type=Path, 321ecaff610STomáš Ďurovec help="The configuration file that describes the test cases, SUTs and DPDK build configs.", 3227f86be25SLuca Vizzarro metavar="FILE_PATH", 3237f86be25SLuca Vizzarro dest="config_file_path", 324995fb337SOwen Hilyard ) 3257f86be25SLuca Vizzarro _add_env_var_to_action(action, "CFG_FILE") 326995fb337SOwen Hilyard 3277f86be25SLuca Vizzarro action = parser.add_argument( 328179d7059SJuraj Linkeš "--output-dir", 329179d7059SJuraj Linkeš "--output", 3307f86be25SLuca Vizzarro default=SETTINGS.output_dir, 3317f86be25SLuca Vizzarro help="Output directory where DTS logs and results are saved.", 3327f86be25SLuca Vizzarro metavar="DIR_PATH", 333179d7059SJuraj Linkeš ) 3347f86be25SLuca Vizzarro _add_env_var_to_action(action) 335179d7059SJuraj Linkeš 3367f86be25SLuca Vizzarro action = parser.add_argument( 33734dfd265SJuraj Linkeš "-t", 33834dfd265SJuraj Linkeš "--timeout", 3397f86be25SLuca Vizzarro default=SETTINGS.timeout, 340680d8a24SJuraj Linkeš type=float, 3417f86be25SLuca Vizzarro help="The default timeout for all DTS operations except for compiling DPDK.", 3427f86be25SLuca Vizzarro metavar="SECONDS", 34334dfd265SJuraj Linkeš ) 3447f86be25SLuca Vizzarro _add_env_var_to_action(action) 34534dfd265SJuraj Linkeš 3467f86be25SLuca Vizzarro action = parser.add_argument( 347179d7059SJuraj Linkeš "-v", 348179d7059SJuraj Linkeš "--verbose", 3494a4678c7SJuraj Linkeš action="store_true", 3507f86be25SLuca Vizzarro default=SETTINGS.verbose, 3517f86be25SLuca Vizzarro help="Specify to enable verbose output, logging all messages to the console.", 352179d7059SJuraj Linkeš ) 3537f86be25SLuca Vizzarro _add_env_var_to_action(action) 354179d7059SJuraj Linkeš 355f9957667STomáš Ďurovec dpdk_build = parser.add_argument_group( 356f9957667STomáš Ďurovec "DPDK Build Options", 357f9957667STomáš Ďurovec description="Arguments in this group (and subgroup) will be applied to a " 358f9957667STomáš Ďurovec "DPDKLocation when the DPDK tree, tarball or revision will be provided, " 359f9957667STomáš Ďurovec "other arguments like remote source and build dir are optional. A DPDKLocation " 360f9957667STomáš Ďurovec "from settings are used instead of from config if construct successful.", 361680d8a24SJuraj Linkeš ) 362680d8a24SJuraj Linkeš 363f9957667STomáš Ďurovec dpdk_source = dpdk_build.add_mutually_exclusive_group() 364f9957667STomáš Ďurovec action = dpdk_source.add_argument( 365f9957667STomáš Ďurovec "--dpdk-tree", 366f9957667STomáš Ďurovec help="The path to the DPDK source tree directory to test. Cannot be used in conjunction " 367187a9447STomáš Ďurovec "with --tarball.", 368f9957667STomáš Ďurovec metavar="DIR_PATH", 369f9957667STomáš Ďurovec dest="dpdk_tree_path", 370f9957667STomáš Ďurovec ) 371f9957667STomáš Ďurovec _add_env_var_to_action(action, "DPDK_TREE") 372a23f2245SLuca Vizzarro 373a23f2245SLuca Vizzarro action = dpdk_source.add_argument( 374680d8a24SJuraj Linkeš "--tarball", 375680d8a24SJuraj Linkeš "--snapshot", 376f9957667STomáš Ďurovec help="The path to the DPDK source tarball to test. DPDK must be contained in a folder with " 377187a9447STomáš Ďurovec "the same name as the tarball file. Cannot be used in conjunction with --dpdk-tree.", 3787f86be25SLuca Vizzarro metavar="FILE_PATH", 3797f86be25SLuca Vizzarro dest="dpdk_tarball_path", 380680d8a24SJuraj Linkeš ) 3817f86be25SLuca Vizzarro _add_env_var_to_action(action, "DPDK_TARBALL") 382680d8a24SJuraj Linkeš 383f9957667STomáš Ďurovec action = dpdk_build.add_argument( 384f9957667STomáš Ďurovec "--remote-source", 385f9957667STomáš Ďurovec action="store_true", 386f9957667STomáš Ďurovec default=False, 387f9957667STomáš Ďurovec help="Set this option if either the DPDK source tree or tarball to be used are located on " 388f9957667STomáš Ďurovec "the SUT node. Can only be used with --dpdk-tree or --tarball.", 389f9957667STomáš Ďurovec ) 390f9957667STomáš Ďurovec _add_env_var_to_action(action) 391187a9447STomáš Ďurovec _required_with_one_of(parser, action, "dpdk_tarball_path", "dpdk_tree_path") 392f9957667STomáš Ďurovec 393f9957667STomáš Ďurovec action = dpdk_build.add_argument( 394f9957667STomáš Ďurovec "--precompiled-build-dir", 395*b935bdc3SLuca Vizzarro help="Define the subdirectory under the DPDK tree root directory or tarball where the " 396*b935bdc3SLuca Vizzarro "pre-compiled binaries are located.", 397f9957667STomáš Ďurovec metavar="DIR_NAME", 398f9957667STomáš Ďurovec ) 399f9957667STomáš Ďurovec _add_env_var_to_action(action) 400f9957667STomáš Ďurovec 4017f86be25SLuca Vizzarro action = parser.add_argument( 402680d8a24SJuraj Linkeš "--compile-timeout", 4037f86be25SLuca Vizzarro default=SETTINGS.compile_timeout, 404680d8a24SJuraj Linkeš type=float, 4057f86be25SLuca Vizzarro help="The timeout for compiling DPDK.", 4067f86be25SLuca Vizzarro metavar="SECONDS", 407680d8a24SJuraj Linkeš ) 4087f86be25SLuca Vizzarro _add_env_var_to_action(action) 409680d8a24SJuraj Linkeš 4107f86be25SLuca Vizzarro action = parser.add_argument( 4114a4678c7SJuraj Linkeš "--test-suite", 4124a4678c7SJuraj Linkeš action="append", 4134a4678c7SJuraj Linkeš nargs="+", 4144a4678c7SJuraj Linkeš metavar=("TEST_SUITE", "TEST_CASES"), 4157f86be25SLuca Vizzarro default=SETTINGS.test_suites, 4167f86be25SLuca Vizzarro help="A list containing a test suite with test cases. " 4174a4678c7SJuraj Linkeš "The first parameter is the test suite name, and the rest are test case names, " 4184a4678c7SJuraj Linkeš "which are optional. May be specified multiple times. To specify multiple test suites in " 4194a4678c7SJuraj Linkeš "the environment variable, join the lists with a comma. " 4204a4678c7SJuraj Linkeš "Examples: " 4214a4678c7SJuraj Linkeš "--test-suite suite case case --test-suite suite case ... | " 4224a4678c7SJuraj Linkeš "DTS_TEST_SUITES='suite case case, suite case, ...' | " 4234a4678c7SJuraj Linkeš "--test-suite suite --test-suite suite case ... | " 4244a4678c7SJuraj Linkeš "DTS_TEST_SUITES='suite, suite case, ...'", 4257f86be25SLuca Vizzarro dest="test_suites", 4266fc05ca7SJuraj Linkeš ) 4277f86be25SLuca Vizzarro _add_env_var_to_action(action) 4286fc05ca7SJuraj Linkeš 4297f86be25SLuca Vizzarro action = parser.add_argument( 4306fc05ca7SJuraj Linkeš "--re-run", 4316fc05ca7SJuraj Linkeš "--re_run", 4327f86be25SLuca Vizzarro default=SETTINGS.re_run, 4336fc05ca7SJuraj Linkeš type=int, 4347f86be25SLuca Vizzarro help="Re-run each test case the specified number of times if a test failure occurs.", 4357f86be25SLuca Vizzarro metavar="N_TIMES", 4366fc05ca7SJuraj Linkeš ) 4377f86be25SLuca Vizzarro _add_env_var_to_action(action, "RERUN") 4386fc05ca7SJuraj Linkeš 439cfe40bacSLuca Vizzarro action = parser.add_argument( 440cfe40bacSLuca Vizzarro "--random-seed", 441cfe40bacSLuca Vizzarro type=int, 442cfe40bacSLuca Vizzarro help="The seed to use with the pseudo-random generator. If not specified, the configuration" 443cfe40bacSLuca Vizzarro " value is used instead. If that's also not specified, a random seed is generated.", 444cfe40bacSLuca Vizzarro metavar="NUMBER", 445cfe40bacSLuca Vizzarro ) 446cfe40bacSLuca Vizzarro _add_env_var_to_action(action) 447cfe40bacSLuca Vizzarro 448995fb337SOwen Hilyard return parser 449995fb337SOwen Hilyard 450995fb337SOwen Hilyard 451f9957667STomáš Ďurovecdef _process_dpdk_location( 452*b935bdc3SLuca Vizzarro parser: _DTSArgumentParser, 453f9957667STomáš Ďurovec dpdk_tree: str | None, 454f9957667STomáš Ďurovec tarball: str | None, 455f9957667STomáš Ďurovec remote: bool, 456*b935bdc3SLuca Vizzarro) -> DPDKLocation | None: 457f9957667STomáš Ďurovec """Process and validate DPDK build arguments. 458f9957667STomáš Ďurovec 459f9957667STomáš Ďurovec Ensures that either `dpdk_tree` or `tarball` is provided. Validate existence and format of 460f9957667STomáš Ďurovec `dpdk_tree` or `tarball` on local filesystem, if `remote` is False. Constructs and returns 461*b935bdc3SLuca Vizzarro any valid :class:`DPDKLocation` with the provided parameters if validation is successful. 462f9957667STomáš Ďurovec 463f9957667STomáš Ďurovec Args: 464*b935bdc3SLuca Vizzarro dpdk_tree: The path to the DPDK source tree directory. 465*b935bdc3SLuca Vizzarro tarball: The path to the DPDK tarball. 466f9957667STomáš Ďurovec remote: If :data:`True`, `dpdk_tree` or `tarball` is located on the SUT node, instead of the 467f9957667STomáš Ďurovec execution host. 468f9957667STomáš Ďurovec 469f9957667STomáš Ďurovec Returns: 470f9957667STomáš Ďurovec A DPDK location if construction is successful, otherwise None. 471f9957667STomáš Ďurovec """ 472f9957667STomáš Ďurovec if dpdk_tree: 473*b935bdc3SLuca Vizzarro action = parser.find_action("dpdk_tree", _is_from_env) 474*b935bdc3SLuca Vizzarro 475*b935bdc3SLuca Vizzarro try: 476*b935bdc3SLuca Vizzarro if remote: 477*b935bdc3SLuca Vizzarro return RemoteDPDKTreeLocation.model_validate({"dpdk_tree": dpdk_tree}) 478*b935bdc3SLuca Vizzarro else: 479*b935bdc3SLuca Vizzarro return LocalDPDKTreeLocation.model_validate({"dpdk_tree": dpdk_tree}) 480*b935bdc3SLuca Vizzarro except ValidationError as e: 481*b935bdc3SLuca Vizzarro print( 482*b935bdc3SLuca Vizzarro "An error has occurred while validating the DPDK tree supplied in the " 483*b935bdc3SLuca Vizzarro f"{'environment variable' if action else 'arguments'}:", 484*b935bdc3SLuca Vizzarro file=sys.stderr, 485f9957667STomáš Ďurovec ) 486*b935bdc3SLuca Vizzarro print(e, file=sys.stderr) 487*b935bdc3SLuca Vizzarro sys.exit(1) 488f9957667STomáš Ďurovec 489f9957667STomáš Ďurovec if tarball: 490*b935bdc3SLuca Vizzarro action = parser.find_action("tarball", _is_from_env) 491f9957667STomáš Ďurovec 492*b935bdc3SLuca Vizzarro try: 493*b935bdc3SLuca Vizzarro if remote: 494*b935bdc3SLuca Vizzarro return RemoteDPDKTarballLocation.model_validate({"tarball": tarball}) 495*b935bdc3SLuca Vizzarro else: 496*b935bdc3SLuca Vizzarro return LocalDPDKTarballLocation.model_validate({"tarball": tarball}) 497*b935bdc3SLuca Vizzarro except ValidationError as e: 498*b935bdc3SLuca Vizzarro print( 499*b935bdc3SLuca Vizzarro "An error has occurred while validating the DPDK tarball supplied in the " 500*b935bdc3SLuca Vizzarro f"{'environment variable' if action else 'arguments'}:", 501*b935bdc3SLuca Vizzarro file=sys.stderr, 502f9957667STomáš Ďurovec ) 503*b935bdc3SLuca Vizzarro print(e, file=sys.stderr) 504*b935bdc3SLuca Vizzarro sys.exit(1) 505f9957667STomáš Ďurovec 506*b935bdc3SLuca Vizzarro return None 507f9957667STomáš Ďurovec 508f9957667STomáš Ďurovec 5097f86be25SLuca Vizzarrodef _process_test_suites( 5107f86be25SLuca Vizzarro parser: _DTSArgumentParser, args: list[list[str]] 5117f86be25SLuca Vizzarro) -> list[TestSuiteConfig]: 5124a4678c7SJuraj Linkeš """Process the given argument to a list of :class:`TestSuiteConfig` to execute. 5134a4678c7SJuraj Linkeš 5144a4678c7SJuraj Linkeš Args: 5154a4678c7SJuraj Linkeš args: The arguments to process. The args is a string from an environment variable 5164a4678c7SJuraj Linkeš or a list of from the user input containing tests suites with tests cases, 5174a4678c7SJuraj Linkeš each of which is a list of [test_suite, test_case, test_case, ...]. 5184a4678c7SJuraj Linkeš 5194a4678c7SJuraj Linkeš Returns: 5204a4678c7SJuraj Linkeš A list of test suite configurations to execute. 5214a4678c7SJuraj Linkeš """ 522*b935bdc3SLuca Vizzarro action = parser.find_action("test_suites", _is_from_env) 523*b935bdc3SLuca Vizzarro if action: 5247f86be25SLuca Vizzarro # Environment variable in the form of "SUITE1 CASE1 CASE2, SUITE2 CASE1, SUITE3, ..." 5257f86be25SLuca Vizzarro args = [suite_with_cases.split() for suite_with_cases in args[0][0].split(",")] 5264a4678c7SJuraj Linkeš 527*b935bdc3SLuca Vizzarro try: 528*b935bdc3SLuca Vizzarro return [ 529*b935bdc3SLuca Vizzarro TestSuiteConfig(test_suite=test_suite, test_cases=test_cases) 530*b935bdc3SLuca Vizzarro for [test_suite, *test_cases] in args 531*b935bdc3SLuca Vizzarro ] 532*b935bdc3SLuca Vizzarro except ValidationError as e: 533*b935bdc3SLuca Vizzarro print( 534*b935bdc3SLuca Vizzarro "An error has occurred while validating the test suites supplied in the " 535*b935bdc3SLuca Vizzarro f"{'environment variable' if action else 'arguments'}:", 536*b935bdc3SLuca Vizzarro file=sys.stderr, 537*b935bdc3SLuca Vizzarro ) 538*b935bdc3SLuca Vizzarro print(e, file=sys.stderr) 539*b935bdc3SLuca Vizzarro sys.exit(1) 5404a4678c7SJuraj Linkeš 5414a4678c7SJuraj Linkeš 542840b1e01SJuraj Linkešdef get_settings() -> Settings: 5436ef07151SJuraj Linkeš """Create new settings with inputs from the user. 5446ef07151SJuraj Linkeš 5456ef07151SJuraj Linkeš The inputs are taken from the command line and from environment variables. 5464a4678c7SJuraj Linkeš 5474a4678c7SJuraj Linkeš Returns: 5484a4678c7SJuraj Linkeš The new settings object. 5496ef07151SJuraj Linkeš """ 5507f86be25SLuca Vizzarro parser = _get_parser() 5517f86be25SLuca Vizzarro 5527f86be25SLuca Vizzarro args = parser.parse_args() 5537f86be25SLuca Vizzarro 554f9957667STomáš Ďurovec args.dpdk_location = _process_dpdk_location( 555*b935bdc3SLuca Vizzarro parser, args.dpdk_tree_path, args.dpdk_tarball_path, args.remote_source 556f9957667STomáš Ďurovec ) 5577f86be25SLuca Vizzarro args.test_suites = _process_test_suites(parser, args.test_suites) 5587f86be25SLuca Vizzarro 5597f86be25SLuca Vizzarro kwargs = {k: v for k, v in vars(args).items() if hasattr(SETTINGS, k)} 5607f86be25SLuca Vizzarro return Settings(**kwargs) 561