diff options
author | Tristan Honscheid <honscheid@google.com> | 2022-07-19 14:13:16 -0600 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-07-22 15:13:17 +0000 |
commit | 1041d49b493d4036ae1a554ea5bc68bc151372fd (patch) | |
tree | 059af8e39cd2503f04aa3d4580248981feb8d48f | |
parent | 83b8d53fa25fef09acd768572d8c2d9b58388f97 (diff) | |
download | chrome-ec-1041d49b493d4036ae1a554ea5bc68bc151372fd.tar.gz |
zephyr: Add wrapper script for calling twister
Add a wrapper script that helps invoke twister with the correct
configuration and defaults for running EC tests. Developers can simply
run `./twister` from `src/platform/ec` to run all Twister-compatible EC
tests, or specify specific tests to run by adding `-T path/to/testroot`
arguments. Other CLI args are passed straight through to Twister.
This CL also adds a testcase.yaml file to the `math` test, allowing it
to be run through Twister:
```
cd $CROS_WORKON_SRCROOT/src/platform/ec
./twister (or)
./twister -T zephyr/test/math
```
Twister's output directories, `twister-out` and `twister-out.N` have
been added to the `.gitignore`.
The `firmware_builder.py` CQ script now also calls Twister and can merge
in coverage reports.
BRANCH=None
BUG=None
TEST=./twister
Signed-off-by: Tristan Honscheid <honscheid@google.com>
Change-Id: If6ff10ffb76655912c96a66aec28d12dcebd1764
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3773766
Reviewed-by: Yuval Peress <peress@google.com>
-rw-r--r-- | .gitignore | 3 | ||||
l--------- | twister | 1 | ||||
-rwxr-xr-x | util/twister_launcher.py | 132 | ||||
-rwxr-xr-x | zephyr/firmware_builder.py | 15 |
4 files changed, 150 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore index 49c5321a0c..75a29bf672 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ zephyr/zmake/.coverage # Clangd language server .cache/clangd/index/* compile_commands.json + +# Twister test output directories +twister-out* diff --git a/twister b/twister new file mode 120000 index 0000000000..7b6dd74c5c --- /dev/null +++ b/twister @@ -0,0 +1 @@ +util/twister_launcher.py
\ No newline at end of file diff --git a/util/twister_launcher.py b/util/twister_launcher.py new file mode 100755 index 0000000000..783d2a7ad9 --- /dev/null +++ b/util/twister_launcher.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 + +# Copyright 2022 The ChromiumOS Authors. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +This script is a wrapper for invoking Twister, the Zephyr test runner, using +default parameters for the ChromiumOS EC project. For an overview of CLI +parameters that may be used, please consult the Twister documentation. +""" + +import argparse +import os +import subprocess +from pathlib import Path + + +def find_checkout() -> Path: + """Find the location of the source checkout or raise an error.""" + # cros_checkout = os.environ.get("CROS_WORKON_SRCROOT") + # if cros_checkout is not None: + # return Path(cros_checkout) + + # Attempt to locate checkout location relatively if being run outside of chroot. + try: + cros_checkout = Path(__file__).resolve().parents[4] + assert (cros_checkout / "src").exists() + return cros_checkout + except (IndexError, AssertionError) as err: + raise RuntimeError( + "Cannot locate the checkout source root. Try entering the chroot or " + "making sure your directory structure matches it." + ) from err + + +def find_modules(mod_dir: Path) -> list: + """Find Zephyr modules in the given directory `dir`.""" + + modules = [] + for child in mod_dir.iterdir(): + if child.is_dir() and (child / "zephyr" / "module.yml").exists(): + modules.append(child) + return modules + + +def main(): + """Run Twister using defaults for the EC project.""" + + # Determine where the source tree is checked out. + cros_checkout = find_checkout() + + # Use ZEPHYR_BASE environment var, or compute from checkout path if not + # specified. + zephyr_base = Path( + os.environ.get( + "ZEPHYR_BASE", + cros_checkout / "src" / "third_party" / "zephyr" / "main", + ) + ) + + ec_base = cros_checkout / "src" / "platform" / "ec" + + # Module paths, including third party modules and the EC application. + zephyr_modules = find_modules(cros_checkout / "src" / "third_party" / "zephyr") + zephyr_modules.append(ec_base) + + # Prepare environment variables for export to Twister and inherit the + # parent environment. + twister_env = dict(os.environ) + twister_env.update( + { + "ZEPHYR_BASE": str(zephyr_base), + "TOOLCHAIN_ROOT": str(zephyr_base), + "ZEPHYR_TOOLCHAIN_VARIANT": "host", + } + ) + + # Twister CLI args + twister_cli = [ + str(zephyr_base / "scripts" / "twister"), # Executable path + "--ninja", + f"-x=DTS_ROOT={str( ec_base / 'zephyr')}", + f"-x=SYSCALL_INCLUDE_DIRS={str(ec_base / 'zephyr' / 'include' / 'drivers')}", + f"-x=ZEPHYR_MODULES={';'.join([str(p) for p in zephyr_modules])}", + ] + + # `-T` flags (used for specifying test directories to build and run) + # require special handling. When run without `-T` flags, Twister will + # search for tests in `zephyr_base`. This is undesirable and we want + # Twister to look in the EC tree by default, instead. Use argparse to + # intercept `-T` flags and pass in a new default if none are found. If + # user does pass their own `-T` flags, pass them through instead. Do the + # same with verbosity. Other arguments get passed straight through, + # including -h/--help so that Twister's own help text gets displayed. + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("-T", "--testsuite-root", action="append") + parser.add_argument("-v", "--verbose", action="count", default=0) + intercepted_args, other_args = parser.parse_known_args() + + for _ in range(intercepted_args.verbose): + # Pass verbosity setting through to twister + twister_cli.append("-v") + + if intercepted_args.testsuite_root: + # Pass user-provided -T args when present. + for arg in intercepted_args.testsuite_root: + twister_cli.extend(["-T", arg]) + else: + # Use EC base dir when no -T args specified. This will cause all + # Twister-compatible EC tests to run. + twister_cli.extend(["-T", str(ec_base)]) + + # Append additional user-supplied args + twister_cli.extend(other_args) + + # Print exact CLI args and environment variables depending on verbosity. + if intercepted_args.verbose > 0: + print("Calling:", twister_cli) + if intercepted_args.verbose > 1: + print("With environment:", twister_env) + + # Invoke Twister and wait for it to exit. + with subprocess.Popen( + twister_cli, + env=twister_env, + ) as proc: + proc.wait() + + +if __name__ == "__main__": + main() diff --git a/zephyr/firmware_builder.py b/zephyr/firmware_builder.py index fb1bbac6c0..c6cf0b0afc 100755 --- a/zephyr/firmware_builder.py +++ b/zephyr/firmware_builder.py @@ -185,8 +185,19 @@ def test(opts): ret = subprocess.run(cmd, check=True).returncode if ret: return ret + + # Twister-based tests + platform_ec = zephyr_dir.parent + cmd = [platform_ec / "twister", "--outdir", platform_ec / "twister-out"] + if opts.code_coverage: + # Tell Twister to collect coverage data. We must specify an explicit platform + # type in this case, as well. + cmd.extend(["--coverage", "-p", "native_posix"]) + ret = subprocess.run(cmd, check=True).returncode + if ret: + return ret + if opts.code_coverage: - platform_ec = zephyr_dir.parent build_dir = platform_ec / "build" / "zephyr" # Merge lcov files here because bundle failures are "infra" failures. cmd = [ @@ -199,6 +210,8 @@ def test(opts): build_dir / "all_tests.info", "-a", build_dir / "all_builds.info", + "-a", + platform_ec / "twister-out" / "coverage.info", ] output = subprocess.run( cmd, |