summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml11
-rw-r--r--docs/code_coverage.md30
-rw-r--r--docs/zephyr/zephyr_shim.md2
-rw-r--r--docs/zephyr/ztest.md2
-rwxr-xr-xzephyr/firmware_builder.py62
-rw-r--r--zephyr/test/drivers/README.md6
-rw-r--r--zephyr/zmake/README.md14
-rw-r--r--zephyr/zmake/zmake/__main__.py16
-rw-r--r--zephyr/zmake/zmake/zmake.py162
9 files changed, 171 insertions, 134 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index dbfdd52c5f..0f59495070 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -226,12 +226,11 @@ zephyr_coverage:
needs: ["seed_cache"]
script:
- zmake --zephyr-base "${ZEPHYR_BASE}"
- --modules-dir "${MODULES_DIR}" -l DEBUG coverage
- "${BUILD_DIR}/zcoverage"
+ --modules-dir "${MODULES_DIR}" -l DEBUG test
+ --coverage --host-tests-only
artifacts:
paths:
- - build/zcoverage/coverage_rpt/*
- - build/zcoverage/*.info
+ - build/zephyr/all_tests.info
expire_in: 1 week
coverage: '/lines\.*: \d+\.\d+%/'
@@ -239,7 +238,7 @@ merged_coverage:
stage: test
needs: ["ec_coverage", "zephyr_coverage"]
script:
- - lcov --rc lcov_branch_coverage=1 -o build/merged.info -a build/coverage/lcov.info -a build/zcoverage/lcov.info
+ - lcov --rc lcov_branch_coverage=1 -o build/merged.info -a build/coverage/lcov.info -a build/zephyr/all_tests.info
- lcov --rc lcov_branch_coverage=1 -o build/merged_no_zephyr.info -r build/merged.info
"${ZEPHYR_BASE}/**" "${MODULES_DIR}/**"
"${EC_DIR}/zephyr/drivers/**" "${EC_DIR}/zephyr/include/drivers/**"
@@ -258,7 +257,7 @@ testall:
needs: ["seed_cache"]
script:
- zmake --zephyr-base "${ZEPHYR_BASE}"
- --modules-dir "${MODULES_DIR}" -l DEBUG testall
+ --modules-dir "${MODULES_DIR}" -l DEBUG test --all
twister_coverage:
stage: test
diff --git a/docs/code_coverage.md b/docs/code_coverage.md
index 93637ac019..a15c61b358 100644
--- a/docs/code_coverage.md
+++ b/docs/code_coverage.md
@@ -38,20 +38,28 @@ appear to be caused in part by using relative paths instead of absolute paths.)
To build the Zephyr unit tests for code coverage run:
-`zmake coverage build/ztest-coverage`
+`zmake test --host-tests-only --coverage`
+`genhtml -q -o build/zephyr/coverage_rpt/ build/zephyr/all_tests.info`
-This target will compile, without linking, all zephyr projects with
-`CONFIG_COVERAGE` Kconfig option enabled, run the tests, and then process the
-profiling data into a code coverage report using the `lcov` and `genhtml`
-tools. This requires the `HAS_COVERAGE_SUPPORT` option, which can only be
-selected in `Kconfig.board`.
+The coverage report top-level page is
+`build/zephyr/coverage_rpt/index.html`.
+
+However you probably want to merge that with a single board's coverage report
+also, so that you can include code that is not part of any test as well.
+
+```
+zmake build --coverage herobrine
+zmake test --host-tests-only --coverage
+genhtml -q -s --branch-coverage -o build/zephyr/coverage_rpt/ \
+ build/zephyr/all_tests.info build/zephyr/herobrine/output/zephyr.info
+```
The coverage report top-level page is
-`build/ztest-coverage/coverage_rpt/index.html`.
+`build/zephyr/coverage_rpt/index.html`.
-For manual coverage report you can run:
-`zmake configure --test --coverage <TESTNAME>`
+For coverage report for a single test you can run:
+`zmake test --coverage <TESTNAME>`
Example:
-`zmake configure --test --coverage test-drivers`
-`genhtml -q -o build/ztest-coverage/coverage_rpt/ build/zephyr/test-drivers/output/zephyr.info`
+`zmake test --coverage test-drivers`
+`genhtml -q -o build/zephyr/test-drivers/output/coverage_rpt/ build/zephyr/test-drivers/output/zephyr.info`
diff --git a/docs/zephyr/zephyr_shim.md b/docs/zephyr/zephyr_shim.md
index fac0383aff..3c6b48f209 100644
--- a/docs/zephyr/zephyr_shim.md
+++ b/docs/zephyr/zephyr_shim.md
@@ -347,7 +347,7 @@ Follow these steps:
Unit tests, implemented using the Ztest framework, can be found in
`zephyr/test`.
-To run all unit tests, you use `zmake testall`.
+To build all projects and run all unit tests, you use `zmake test --all`.
## Alternatives Considered
diff --git a/docs/zephyr/ztest.md b/docs/zephyr/ztest.md
index 4a33d0a103..6bb121045d 100644
--- a/docs/zephyr/ztest.md
+++ b/docs/zephyr/ztest.md
@@ -178,7 +178,7 @@ uses.
Use `zmake` to build and run the test:
```
-(cr) $ zmake -l DEBUG configure --test -B build/ztest/base32 test-base32
+(cr) $ zmake -l DEBUG test test-base32
...
UART_0 connected to pseudotty: /dev/pts/1
*** Booting Zephyr OS build zephyr-v2.4.0-1-g63b2330a85cd ***
diff --git a/zephyr/firmware_builder.py b/zephyr/firmware_builder.py
index ae19b82c81..2b138357f3 100755
--- a/zephyr/firmware_builder.py
+++ b/zephyr/firmware_builder.py
@@ -31,10 +31,10 @@ def build(opts):
with open(opts.metrics, 'w') as f:
f.write(json_format.MessageToJson(metrics))
- # Nothing to do, as the test phase actually does the builds.
- # TODO(b/217788621): Do a build-only here once we can separate build
- # and test phases on zmake CLI.
- return 0
+ cmd = ['zmake', '-D', 'build', '-a']
+ if opts.code_coverage:
+ cmd.append('--coverage')
+ return subprocess.run(cmd, cwd=pathlib.Path(__file__).parent).returncode
def bundle(opts):
@@ -71,27 +71,7 @@ def bundle_coverage(opts):
bundle_dir = get_bundle_dir(opts)
zephyr_dir = pathlib.Path(__file__).parent
platform_ec = zephyr_dir.resolve().parent
- # Find the zephyr.info for every project and merge them
- all_lcov_files = [platform_ec / 'build' / 'zephyr-coverage' / 'lcov.info']
- for project in zmake.project.find_projects(zephyr_dir).values():
- if not project.config.is_test:
- build_dir = platform_ec / "build" / "zephyr" / project.config.project_name
- artifacts_dir = build_dir / 'output'
- all_lcov_files.append(artifacts_dir / 'zephyr.info')
- build_dir = platform_ec / "build"
- print("all_lcov_files = %s" % all_lcov_files)
- cmd = [
- "/usr/bin/lcov",
- "-o",
- build_dir / "lcov.info",
- "--rc",
- "lcov_branch_coverage=1",
- ]
- for lcov_file in all_lcov_files:
- cmd += ["-a", lcov_file]
- rv = subprocess.run(cmd, cwd=pathlib.Path(__file__).parent).returncode
- if rv != 0:
- return rv
+ build_dir = platform_ec / "build" / "zephyr"
tarball_name = 'coverage.tbz2'
tarball_path = bundle_dir / tarball_name
cmd = ['tar', 'cvfj', tarball_path, 'lcov.info']
@@ -112,12 +92,10 @@ def bundle_firmware(opts):
zephyr_dir = pathlib.Path(__file__).parent
platform_ec = zephyr_dir.resolve().parent
for project in zmake.project.find_projects(zephyr_dir).values():
+ if project.config.is_test:
+ continue
build_dir = platform_ec / "build" / "zephyr" / project.config.project_name
artifacts_dir = build_dir / 'output'
- # TODO(kmshelton): Remove once the build command does not rely
- # on a pre-defined list of targets.
- if not artifacts_dir.is_dir():
- continue
tarball_name = '{}.firmware.tbz2'.format(project.config.project_name)
tarball_path = bundle_dir.joinpath(tarball_name)
cmd = ['tar', 'cvfj', tarball_path, '.']
@@ -149,13 +127,29 @@ def test(opts):
config_files = zephyr_dir.rglob("**/BUILD.py")
subprocess.run(["black", "--diff", "--check", *config_files], check=True)
+ cmd = ['zmake', '-D', 'test', '-a', '--no-rebuild']
+ if opts.code_coverage:
+ cmd.append('--coverage')
+ rv = subprocess.run(cmd, check=True).returncode
+ if rv:
+ return rv
if opts.code_coverage:
platform_ec = zephyr_dir.parent
- build_dir = platform_ec / 'build/zephyr-coverage'
- return subprocess.run(
- ['zmake', '-D', 'coverage', build_dir], cwd=platform_ec).returncode
- else:
- return subprocess.run(['zmake', '-D', 'testall'], check=True).returncode
+ build_dir = platform_ec / "build" / "zephyr"
+ # Merge lcov files here because bundle failures are "infra" failures.
+ cmd = [
+ "/usr/bin/lcov",
+ "-o",
+ build_dir / "lcov.info",
+ "--rc",
+ "lcov_branch_coverage=1",
+ "-a", build_dir / 'all_tests.info',
+ "-a", build_dir / 'all_builds.info',
+ ]
+ rv = subprocess.run(cmd, cwd=pathlib.Path(__file__).parent).returncode
+ if rv != 0:
+ return rv
+ return 0
def main(args):
diff --git a/zephyr/test/drivers/README.md b/zephyr/test/drivers/README.md
index cdde4d4f6c..11c913baa8 100644
--- a/zephyr/test/drivers/README.md
+++ b/zephyr/test/drivers/README.md
@@ -5,13 +5,13 @@ so we can test interactions between different subsystems easily.
## Run all the test suites
```bash
-(chroot) zmake configure --test test-drivers
+(chroot) zmake test test-drivers
```
To see all the output of zmake (for example if the build fails)
```bash
-(chroot) zmake -l DEBUG -j 1 configure --test test-drivers
+(chroot) zmake -l DEBUG -j 1 test test-drivers
```
## Code coverage
@@ -19,7 +19,7 @@ To see all the output of zmake (for example if the build fails)
To calculate code coverage for this test only
```bash
-(chroot) zmake configure --coverage --test test-drivers
+(chroot) zmake test --coverage test-drivers
(chroot) genhtml --branch-coverage -q \
-o build/zephyr/test-drivers/output/coverage_rpt \
build/zephyr/test-drivers/output/zephyr.info
diff --git a/zephyr/zmake/README.md b/zephyr/zmake/README.md
index 97ff4a434f..fb7d4b8414 100644
--- a/zephyr/zmake/README.md
+++ b/zephyr/zmake/README.md
@@ -102,20 +102,28 @@ Chromium OS's meta-build tool for Zephyr
### zmake test
-**Usage:** `zmake test [-h] [-c] build_dir`
+**Usage:** `zmake test [-h] [--no-rebuild] [-t TOOLCHAIN] [--bringup] [--clobber] [--allow-warnings] [-B BUILD_DIR] [-c] (-a | --host-tests-only | project_name [project_name ...])`
#### Positional Arguments
| | |
|---|---|
-| `build_dir` | The build directory used during configuration |
+| `project_name` | Name(s) of the project(s) to build |
#### Optional Arguments
| | |
|---|---|
| `-h`, `--help` | show this help message and exit |
-| `-c`, `--coverage` | Run lcov after running test to generate coverage info file. |
+| `--no-rebuild` | Do not configure or build before running tests. |
+| `-t TOOLCHAIN`, `--toolchain TOOLCHAIN` | Name of toolchain to use |
+| `--bringup` | Enable bringup debugging features |
+| `--clobber` | Delete existing build directories, even if configuration is unchanged |
+| `--allow-warnings` | Do not treat warnings as errors |
+| `-B BUILD_DIR`, `--build-dir BUILD_DIR` | Root build directory, project files will be in ${build_dir}/${project_name} |
+| `-c`, `--coverage` | Enable CONFIG_COVERAGE Kconfig. |
+| `-a`, `--all` | Select all projects |
+| `--host-tests-only` | Select all test projects |
### zmake testall
diff --git a/zephyr/zmake/zmake/__main__.py b/zephyr/zmake/zmake/__main__.py
index 14f47bc462..c39a645a81 100644
--- a/zephyr/zmake/zmake/__main__.py
+++ b/zephyr/zmake/zmake/__main__.py
@@ -222,24 +222,18 @@ def get_argparser():
test = sub.add_parser(
"test",
- help="Execute tests from a build directory",
+ help="Configure, build and run tests on specified projects",
)
test.add_argument(
- "-c",
- "--coverage",
+ "--no-rebuild",
action="store_true",
- dest="coverage",
- help="Run lcov after running test to generate coverage info file.",
- )
- test.add_argument(
- "build_dir",
- type=pathlib.Path,
- help="The build directory used during configuration",
+ help="Do not configure or build before running tests.",
)
+ add_common_configure_args(test)
testall = sub.add_parser(
"testall",
- help="Execute all known builds and tests",
+ help="Alias for test --all",
)
testall.add_argument(
"--clobber",
diff --git a/zephyr/zmake/zmake/zmake.py b/zephyr/zmake/zmake/zmake.py
index f697075c59..585726f5af 100644
--- a/zephyr/zmake/zmake/zmake.py
+++ b/zephyr/zmake/zmake/zmake.py
@@ -11,6 +11,7 @@ import pathlib
import re
import shutil
import subprocess
+from typing import List
import zmake.build_config
import zmake.generate_readme
@@ -192,7 +193,7 @@ class Zmake:
def _resolve_projects(
self, project_names, all_projects=False, host_tests_only=False
- ):
+ ) -> List[zmake.project.Project]:
"""Finds all projects for the specified command line flags.
Returns a list of projects.
@@ -256,17 +257,19 @@ class Zmake:
rv = self.executor.wait()
if rv:
return rv
- if len(projects) > 1 and coverage and test_after_configure:
+ test_projects = [p for p in projects if p.config.is_test]
+ if len(test_projects) > 1 and coverage and test_after_configure:
rv = self._merge_lcov_files(
- projects=[p for p in projects if p.config.is_test],
+ projects=test_projects,
build_dir=build_dir,
output_file=build_dir / "all_tests.info",
)
if rv:
return rv
- if len(projects) > 1 and coverage and build_after_configure:
+ non_test_projects = [p for p in projects if not p.config.is_test]
+ if len(non_test_projects) > 1 and coverage and build_after_configure:
rv = self._merge_lcov_files(
- projects=[p for p in projects if not p.config.is_test],
+ projects=non_test_projects,
build_dir=build_dir,
output_file=build_dir / "all_builds.info",
)
@@ -300,6 +303,95 @@ class Zmake:
build_after_configure=True,
)
+ def test(
+ self,
+ project_names,
+ build_dir=None,
+ toolchain=None,
+ clobber=False,
+ bringup=False,
+ coverage=False,
+ allow_warnings=False,
+ all_projects=False,
+ host_tests_only=False,
+ no_rebuild=False,
+ ):
+ """Locate and build the specified projects."""
+ if not no_rebuild:
+ return self.configure(
+ project_names,
+ build_dir=build_dir,
+ toolchain=toolchain,
+ clobber=clobber,
+ bringup=bringup,
+ coverage=coverage,
+ allow_warnings=allow_warnings,
+ all_projects=all_projects,
+ host_tests_only=host_tests_only,
+ test_after_configure=True,
+ )
+ # Resolve build_dir if needed.
+ if not build_dir:
+ build_dir = self.module_paths["ec"] / "build" / "zephyr"
+
+ projects = self._resolve_projects(
+ project_names, all_projects=all_projects, host_tests_only=host_tests_only
+ )
+ test_projects = [p for p in projects if p.config.is_test]
+ for project in test_projects:
+ project_build_dir = pathlib.Path(build_dir) / project.config.project_name
+ gcov = "gcov.sh-not-found"
+ for build_name, _ in project.iter_builds():
+ target_build_dir = project_build_dir / "build-{}".format(build_name)
+ gcov = target_build_dir / "gcov.sh"
+ self.executor.append(
+ func=functools.partial(
+ self._run_test,
+ elf_file=project_build_dir / "output" / "zephyr.elf",
+ coverage=coverage,
+ gcov=gcov,
+ build_dir=project_build_dir,
+ lcov_file=project_build_dir / "output" / "zephyr.info",
+ timeout=project.config.test_timeout_secs,
+ )
+ )
+ if self._sequential:
+ rv = self.executor.wait()
+ if rv:
+ return rv
+ rv = self.executor.wait()
+ if rv:
+ return rv
+ if len(test_projects) > 1 and coverage:
+ rv = self._merge_lcov_files(
+ projects=test_projects,
+ build_dir=build_dir,
+ output_file=build_dir / "all_tests.info",
+ )
+ if rv:
+ return rv
+ return 0
+
+ def testall(
+ self,
+ build_dir=None,
+ toolchain=None,
+ clobber=False,
+ bringup=False,
+ coverage=False,
+ allow_warnings=False,
+ ):
+ return self.test(
+ [],
+ build_dir=build_dir,
+ toolchain=toolchain,
+ clobber=clobber,
+ bringup=bringup,
+ coverage=coverage,
+ allow_warnings=allow_warnings,
+ all_projects=True,
+ )
+
def _configure(
self,
project,
@@ -499,7 +591,7 @@ class Zmake:
def _build(
self,
build_dir,
- project,
+ project: zmake.project.Project,
output_files_out=None,
fail_on_warnings=False,
coverage=False,
@@ -693,64 +785,6 @@ class Zmake:
with self.jobserver.get_job():
_run()
- def test(self, build_dir, coverage=False):
- """Test a build directory."""
- output_files = []
- build_dir = build_dir.resolve()
- found_projects = zmake.project.find_projects(build_dir / "project")
- project = found_projects[(build_dir / "project_name.txt").read_text()]
- self._build(
- build_dir, project=project, output_files_out=output_files, coverage=coverage
- )
-
- # If the project built but isn't a test, just bail.
- if not project.config.is_test:
- return 0
-
- gcov = "gcov.sh-not-found"
- if coverage:
- for build_name, _ in project.iter_builds():
- gcov = build_dir / "build-{}".format(build_name) / "gcov.sh"
-
- for output_file in output_files:
- self.executor.append(
- func=functools.partial(
- self._run_test,
- elf_file=output_file,
- coverage=coverage,
- gcov=gcov,
- build_dir=build_dir,
- lcov_file=build_dir / "output" / "zephyr.info",
- timeout=project.config.test_timeout_secs,
- )
- )
-
- return 0
-
- def testall(self, build_dir=None, clobber=False):
- """Test all the valid test targets"""
- for project in zmake.project.find_projects(
- self.module_paths["ec"] / "zephyr"
- ).values():
- is_test = project.config.is_test
- if build_dir:
- project_build_dir = build_dir / project.config.project_name
- else:
- project_build_dir = None
- # Configure and run the test.
- self.executor.append(
- func=functools.partial(
- self._configure,
- project=project,
- build_dir=project_build_dir,
- build_after_configure=True,
- test_after_configure=is_test,
- clobber=clobber,
- )
- )
-
- return self.executor.wait()
-
def _run_lcov(self, build_dir, lcov_file, initial=False, gcov=""):
gcov = os.path.abspath(gcov)
if initial: