xref: /dpdk/dts/framework/settings.py (revision 4a4678c76def68a9e81a6acd340eb9a567de964c)
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
5995fb337SOwen Hilyard
66ef07151SJuraj Linkeš"""Environment variables and command line arguments parsing.
76ef07151SJuraj Linkeš
86ef07151SJuraj LinkešThis is a simple module utilizing the built-in argparse module to parse command line arguments,
96ef07151SJuraj Linkešaugment them with values from environment variables and make them available across the framework.
106ef07151SJuraj Linkeš
116ef07151SJuraj LinkešThe command line value takes precedence, followed by the environment variable value,
126ef07151SJuraj Linkešfollowed by the default value defined in this module.
136ef07151SJuraj Linkeš
146ef07151SJuraj LinkešThe command line arguments along with the supported environment variables are:
156ef07151SJuraj Linkeš
166ef07151SJuraj Linkeš.. option:: --config-file
176ef07151SJuraj Linkeš.. envvar:: DTS_CFG_FILE
186ef07151SJuraj Linkeš
196ef07151SJuraj Linkeš    The path to the YAML test run configuration file.
206ef07151SJuraj Linkeš
216ef07151SJuraj Linkeš.. option:: --output-dir, --output
226ef07151SJuraj Linkeš.. envvar:: DTS_OUTPUT_DIR
236ef07151SJuraj Linkeš
246ef07151SJuraj Linkeš    The directory where DTS logs and results are saved.
256ef07151SJuraj Linkeš
266ef07151SJuraj Linkeš.. option:: --compile-timeout
276ef07151SJuraj Linkeš.. envvar:: DTS_COMPILE_TIMEOUT
286ef07151SJuraj Linkeš
296ef07151SJuraj Linkeš    The timeout for compiling DPDK.
306ef07151SJuraj Linkeš
316ef07151SJuraj Linkeš.. option:: -t, --timeout
326ef07151SJuraj Linkeš.. envvar:: DTS_TIMEOUT
336ef07151SJuraj Linkeš
346ef07151SJuraj Linkeš    The timeout for all DTS operation except for compiling DPDK.
356ef07151SJuraj Linkeš
366ef07151SJuraj Linkeš.. option:: -v, --verbose
376ef07151SJuraj Linkeš.. envvar:: DTS_VERBOSE
386ef07151SJuraj Linkeš
396ef07151SJuraj Linkeš    Set to any value to enable logging everything to the console.
406ef07151SJuraj Linkeš
416ef07151SJuraj Linkeš.. option:: -s, --skip-setup
426ef07151SJuraj Linkeš.. envvar:: DTS_SKIP_SETUP
436ef07151SJuraj Linkeš
446ef07151SJuraj Linkeš    Set to any value to skip building DPDK.
456ef07151SJuraj Linkeš
466ef07151SJuraj Linkeš.. option:: --tarball, --snapshot, --git-ref
476ef07151SJuraj Linkeš.. envvar:: DTS_DPDK_TARBALL
486ef07151SJuraj Linkeš
496ef07151SJuraj Linkeš    The path to a DPDK tarball, git commit ID, tag ID or tree ID to test.
506ef07151SJuraj Linkeš
51*4a4678c7SJuraj Linkeš.. option:: --test-suite
52*4a4678c7SJuraj Linkeš.. envvar:: DTS_TEST_SUITES
536ef07151SJuraj Linkeš
54*4a4678c7SJuraj Linkeš        A test suite with test cases which may be specified multiple times.
55*4a4678c7SJuraj Linkeš        In the environment variable, the suites are joined with a comma.
566ef07151SJuraj Linkeš
576ef07151SJuraj Linkeš.. option:: --re-run, --re_run
586ef07151SJuraj Linkeš.. envvar:: DTS_RERUN
596ef07151SJuraj Linkeš
606ef07151SJuraj Linkeš    Re-run each test case this many times in case of a failure.
616ef07151SJuraj Linkeš
626ef07151SJuraj LinkešThe module provides one key module-level variable:
636ef07151SJuraj Linkeš
646ef07151SJuraj LinkešAttributes:
656ef07151SJuraj Linkeš    SETTINGS: The module level variable storing framework-wide DTS settings.
666ef07151SJuraj Linkeš
676ef07151SJuraj LinkešTypical usage example::
686ef07151SJuraj Linkeš
696ef07151SJuraj Linkeš  from framework.settings import SETTINGS
706ef07151SJuraj Linkeš  foo = SETTINGS.foo
716ef07151SJuraj Linkeš"""
726ef07151SJuraj Linkeš
73995fb337SOwen Hilyardimport argparse
74995fb337SOwen Hilyardimport os
75840b1e01SJuraj Linkešfrom dataclasses import dataclass, field
76680d8a24SJuraj Linkešfrom pathlib import Path
77*4a4678c7SJuraj Linkešfrom typing import Any
78995fb337SOwen Hilyard
79*4a4678c7SJuraj Linkešfrom .config import TestSuiteConfig
80c9d31a7eSJuraj Linkešfrom .utils import DPDKGitTarball
81680d8a24SJuraj Linkeš
82995fb337SOwen Hilyard
83840b1e01SJuraj Linkeš@dataclass(slots=True)
84840b1e01SJuraj Linkešclass Settings:
856ef07151SJuraj Linkeš    """Default framework-wide user settings.
866ef07151SJuraj Linkeš
876ef07151SJuraj Linkeš    The defaults may be modified at the start of the run.
886ef07151SJuraj Linkeš    """
896ef07151SJuraj Linkeš
906ef07151SJuraj Linkeš    #:
91840b1e01SJuraj Linkeš    config_file_path: Path = Path(__file__).parent.parent.joinpath("conf.yaml")
926ef07151SJuraj Linkeš    #:
93840b1e01SJuraj Linkeš    output_dir: str = "output"
946ef07151SJuraj Linkeš    #:
95840b1e01SJuraj Linkeš    timeout: float = 15
966ef07151SJuraj Linkeš    #:
97840b1e01SJuraj Linkeš    verbose: bool = False
986ef07151SJuraj Linkeš    #:
99840b1e01SJuraj Linkeš    skip_setup: bool = False
1006ef07151SJuraj Linkeš    #:
101840b1e01SJuraj Linkeš    dpdk_tarball_path: Path | str = "dpdk.tar.xz"
1026ef07151SJuraj Linkeš    #:
103840b1e01SJuraj Linkeš    compile_timeout: float = 1200
1046ef07151SJuraj Linkeš    #:
105*4a4678c7SJuraj Linkeš    test_suites: list[TestSuiteConfig] = field(default_factory=list)
1066ef07151SJuraj Linkeš    #:
107840b1e01SJuraj Linkeš    re_run: int = 0
108840b1e01SJuraj Linkeš
109840b1e01SJuraj Linkeš
110840b1e01SJuraj LinkešSETTINGS: Settings = Settings()
111995fb337SOwen Hilyard
112995fb337SOwen Hilyard
113995fb337SOwen Hilyarddef _get_parser() -> argparse.ArgumentParser:
114*4a4678c7SJuraj Linkeš    """Create the argument parser for DTS.
115*4a4678c7SJuraj Linkeš
116*4a4678c7SJuraj Linkeš    Command line options take precedence over environment variables, which in turn take precedence
117*4a4678c7SJuraj Linkeš    over default values.
118*4a4678c7SJuraj Linkeš
119*4a4678c7SJuraj Linkeš    Returns:
120*4a4678c7SJuraj Linkeš        argparse.ArgumentParser: The configured argument parser with defined options.
121*4a4678c7SJuraj Linkeš    """
122*4a4678c7SJuraj Linkeš
123*4a4678c7SJuraj Linkeš    def env_arg(env_var: str, default: Any) -> Any:
124*4a4678c7SJuraj Linkeš        """A helper function augmenting the argparse with environment variables.
125*4a4678c7SJuraj Linkeš
126*4a4678c7SJuraj Linkeš        If the supplied environment variable is defined, then the default value
127*4a4678c7SJuraj Linkeš        of the argument is modified. This satisfies the priority order of
128*4a4678c7SJuraj Linkeš        command line argument > environment variable > default value.
129*4a4678c7SJuraj Linkeš
130*4a4678c7SJuraj Linkeš        Args:
131*4a4678c7SJuraj Linkeš            env_var: Environment variable name.
132*4a4678c7SJuraj Linkeš            default: Default value.
133*4a4678c7SJuraj Linkeš
134*4a4678c7SJuraj Linkeš        Returns:
135*4a4678c7SJuraj Linkeš            Environment variable or default value.
136*4a4678c7SJuraj Linkeš        """
137*4a4678c7SJuraj Linkeš        return os.environ.get(env_var) or default
138*4a4678c7SJuraj Linkeš
13978534506SJuraj Linkeš    parser = argparse.ArgumentParser(
140517b4b26SJuraj Linkeš        description="Run DPDK test suites. All options may be specified with the environment "
141517b4b26SJuraj Linkeš        "variables provided in brackets. Command line arguments have higher priority.",
14278534506SJuraj Linkeš        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
14378534506SJuraj Linkeš    )
144995fb337SOwen Hilyard
145995fb337SOwen Hilyard    parser.add_argument(
146995fb337SOwen Hilyard        "--config-file",
147*4a4678c7SJuraj Linkeš        default=env_arg("DTS_CFG_FILE", SETTINGS.config_file_path),
148840b1e01SJuraj Linkeš        type=Path,
149*4a4678c7SJuraj Linkeš        help="[DTS_CFG_FILE] The configuration file that describes the test cases, "
150*4a4678c7SJuraj Linkeš        "SUTs and targets.",
151995fb337SOwen Hilyard    )
152995fb337SOwen Hilyard
153179d7059SJuraj Linkeš    parser.add_argument(
154179d7059SJuraj Linkeš        "--output-dir",
155179d7059SJuraj Linkeš        "--output",
156*4a4678c7SJuraj Linkeš        default=env_arg("DTS_OUTPUT_DIR", SETTINGS.output_dir),
15755442c14SLuca Vizzarro        help="[DTS_OUTPUT_DIR] Output directory where DTS logs and results are saved.",
158179d7059SJuraj Linkeš    )
159179d7059SJuraj Linkeš
160179d7059SJuraj Linkeš    parser.add_argument(
16134dfd265SJuraj Linkeš        "-t",
16234dfd265SJuraj Linkeš        "--timeout",
163*4a4678c7SJuraj Linkeš        default=env_arg("DTS_TIMEOUT", SETTINGS.timeout),
164680d8a24SJuraj Linkeš        type=float,
165517b4b26SJuraj Linkeš        help="[DTS_TIMEOUT] The default timeout for all DTS operations except for compiling DPDK.",
16634dfd265SJuraj Linkeš    )
16734dfd265SJuraj Linkeš
16834dfd265SJuraj Linkeš    parser.add_argument(
169179d7059SJuraj Linkeš        "-v",
170179d7059SJuraj Linkeš        "--verbose",
171*4a4678c7SJuraj Linkeš        action="store_true",
172*4a4678c7SJuraj Linkeš        default=env_arg("DTS_VERBOSE", SETTINGS.verbose),
173840b1e01SJuraj Linkeš        help="[DTS_VERBOSE] Specify to enable verbose output, logging all messages "
174179d7059SJuraj Linkeš        "to the console.",
175179d7059SJuraj Linkeš    )
176179d7059SJuraj Linkeš
177680d8a24SJuraj Linkeš    parser.add_argument(
178680d8a24SJuraj Linkeš        "-s",
179680d8a24SJuraj Linkeš        "--skip-setup",
180*4a4678c7SJuraj Linkeš        action="store_true",
181*4a4678c7SJuraj Linkeš        default=env_arg("DTS_SKIP_SETUP", SETTINGS.skip_setup),
182840b1e01SJuraj Linkeš        help="[DTS_SKIP_SETUP] Specify to skip all setup steps on SUT and TG nodes.",
183680d8a24SJuraj Linkeš    )
184680d8a24SJuraj Linkeš
185680d8a24SJuraj Linkeš    parser.add_argument(
186680d8a24SJuraj Linkeš        "--tarball",
187680d8a24SJuraj Linkeš        "--snapshot",
188c9d31a7eSJuraj Linkeš        "--git-ref",
189*4a4678c7SJuraj Linkeš        default=env_arg("DTS_DPDK_TARBALL", SETTINGS.dpdk_tarball_path),
190680d8a24SJuraj Linkeš        type=Path,
191c9d31a7eSJuraj Linkeš        help="[DTS_DPDK_TARBALL] Path to DPDK source code tarball or a git commit ID, "
192c9d31a7eSJuraj Linkeš        "tag ID or tree ID to test. To test local changes, first commit them, "
193c9d31a7eSJuraj Linkeš        "then use the commit ID with this option.",
194680d8a24SJuraj Linkeš    )
195680d8a24SJuraj Linkeš
196680d8a24SJuraj Linkeš    parser.add_argument(
197680d8a24SJuraj Linkeš        "--compile-timeout",
198*4a4678c7SJuraj Linkeš        default=env_arg("DTS_COMPILE_TIMEOUT", SETTINGS.compile_timeout),
199680d8a24SJuraj Linkeš        type=float,
200680d8a24SJuraj Linkeš        help="[DTS_COMPILE_TIMEOUT] The timeout for compiling DPDK.",
201680d8a24SJuraj Linkeš    )
202680d8a24SJuraj Linkeš
2036fc05ca7SJuraj Linkeš    parser.add_argument(
204*4a4678c7SJuraj Linkeš        "--test-suite",
205*4a4678c7SJuraj Linkeš        action="append",
206*4a4678c7SJuraj Linkeš        nargs="+",
207*4a4678c7SJuraj Linkeš        metavar=("TEST_SUITE", "TEST_CASES"),
208*4a4678c7SJuraj Linkeš        default=env_arg("DTS_TEST_SUITES", SETTINGS.test_suites),
209*4a4678c7SJuraj Linkeš        help="[DTS_TEST_SUITES] A list containing a test suite with test cases. "
210*4a4678c7SJuraj Linkeš        "The first parameter is the test suite name, and the rest are test case names, "
211*4a4678c7SJuraj Linkeš        "which are optional. May be specified multiple times. To specify multiple test suites in "
212*4a4678c7SJuraj Linkeš        "the environment variable, join the lists with a comma. "
213*4a4678c7SJuraj Linkeš        "Examples: "
214*4a4678c7SJuraj Linkeš        "--test-suite suite case case --test-suite suite case ... | "
215*4a4678c7SJuraj Linkeš        "DTS_TEST_SUITES='suite case case, suite case, ...' | "
216*4a4678c7SJuraj Linkeš        "--test-suite suite --test-suite suite case ... | "
217*4a4678c7SJuraj Linkeš        "DTS_TEST_SUITES='suite, suite case, ...'",
2186fc05ca7SJuraj Linkeš    )
2196fc05ca7SJuraj Linkeš
2206fc05ca7SJuraj Linkeš    parser.add_argument(
2216fc05ca7SJuraj Linkeš        "--re-run",
2226fc05ca7SJuraj Linkeš        "--re_run",
223*4a4678c7SJuraj Linkeš        default=env_arg("DTS_RERUN", SETTINGS.re_run),
2246fc05ca7SJuraj Linkeš        type=int,
2256ef07151SJuraj Linkeš        help="[DTS_RERUN] Re-run each test case the specified number of times "
226*4a4678c7SJuraj Linkeš        "if a test failure occurs.",
2276fc05ca7SJuraj Linkeš    )
2286fc05ca7SJuraj Linkeš
229995fb337SOwen Hilyard    return parser
230995fb337SOwen Hilyard
231995fb337SOwen Hilyard
232*4a4678c7SJuraj Linkešdef _process_test_suites(args: str | list[list[str]]) -> list[TestSuiteConfig]:
233*4a4678c7SJuraj Linkeš    """Process the given argument to a list of :class:`TestSuiteConfig` to execute.
234*4a4678c7SJuraj Linkeš
235*4a4678c7SJuraj Linkeš    Args:
236*4a4678c7SJuraj Linkeš        args: The arguments to process. The args is a string from an environment variable
237*4a4678c7SJuraj Linkeš              or a list of from the user input containing tests suites with tests cases,
238*4a4678c7SJuraj Linkeš              each of which is a list of [test_suite, test_case, test_case, ...].
239*4a4678c7SJuraj Linkeš
240*4a4678c7SJuraj Linkeš    Returns:
241*4a4678c7SJuraj Linkeš        A list of test suite configurations to execute.
242*4a4678c7SJuraj Linkeš    """
243*4a4678c7SJuraj Linkeš    if isinstance(args, str):
244*4a4678c7SJuraj Linkeš        # Environment variable in the form of "suite case case, suite case, suite, ..."
245*4a4678c7SJuraj Linkeš        args = [suite_with_cases.split() for suite_with_cases in args.split(",")]
246*4a4678c7SJuraj Linkeš
247*4a4678c7SJuraj Linkeš    test_suites_to_run = []
248*4a4678c7SJuraj Linkeš    for suite_with_cases in args:
249*4a4678c7SJuraj Linkeš        test_suites_to_run.append(
250*4a4678c7SJuraj Linkeš            TestSuiteConfig(test_suite=suite_with_cases[0], test_cases=suite_with_cases[1:])
251*4a4678c7SJuraj Linkeš        )
252*4a4678c7SJuraj Linkeš
253*4a4678c7SJuraj Linkeš    return test_suites_to_run
254*4a4678c7SJuraj Linkeš
255*4a4678c7SJuraj Linkeš
256840b1e01SJuraj Linkešdef get_settings() -> Settings:
2576ef07151SJuraj Linkeš    """Create new settings with inputs from the user.
2586ef07151SJuraj Linkeš
2596ef07151SJuraj Linkeš    The inputs are taken from the command line and from environment variables.
260*4a4678c7SJuraj Linkeš
261*4a4678c7SJuraj Linkeš    Returns:
262*4a4678c7SJuraj Linkeš        The new settings object.
2636ef07151SJuraj Linkeš    """
264995fb337SOwen Hilyard    parsed_args = _get_parser().parse_args()
265840b1e01SJuraj Linkeš    return Settings(
266995fb337SOwen Hilyard        config_file_path=parsed_args.config_file,
267179d7059SJuraj Linkeš        output_dir=parsed_args.output_dir,
268680d8a24SJuraj Linkeš        timeout=parsed_args.timeout,
269840b1e01SJuraj Linkeš        verbose=parsed_args.verbose,
270840b1e01SJuraj Linkeš        skip_setup=parsed_args.skip_setup,
271840b1e01SJuraj Linkeš        dpdk_tarball_path=Path(
272840b1e01SJuraj Linkeš            Path(DPDKGitTarball(parsed_args.tarball, parsed_args.output_dir))
273c9d31a7eSJuraj Linkeš            if not os.path.exists(parsed_args.tarball)
274840b1e01SJuraj Linkeš            else Path(parsed_args.tarball)
275840b1e01SJuraj Linkeš        ),
276680d8a24SJuraj Linkeš        compile_timeout=parsed_args.compile_timeout,
277*4a4678c7SJuraj Linkeš        test_suites=_process_test_suites(parsed_args.test_suite),
2786fc05ca7SJuraj Linkeš        re_run=parsed_args.re_run,
279995fb337SOwen Hilyard    )
280