blob: dc35ce04b7f2bd95f405881acc9d79fac9544bf7 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
import logging
from pathlib import (
Path,
PurePath,
)
from pprint import pformat
from typing import List
from common import (
BAZEL,
DEVICE_LIBS_QUERY,
LLD_HOST,
BazelTestType,
CoverageParams,
run,
)
def handle_libs(device_libs_all: List[str]) -> List[str]:
"""Filter device libraries that are not compatible with the host.
Args:
device_libs_all: A list of device libraries.
Returns:
`device_libs_all` with incompatible libraries filtered out.
"""
device_libs_incompat = run(
BAZEL,
"cquery",
DEVICE_LIBS_QUERY,
"--output=starlark",
("--starlark:expr=target.label"
" if 'IncompatiblePlatformProvider' in providers(target)"
" else ''"),
)
logging.info(f"incompatible libraries: {pformat(device_libs_incompat)}")
return sorted(list(set(device_libs_all) - set(device_libs_incompat)))
def handle_objs(merged_library: Path, obj_files: List[str]):
"""Create a shared library from the given object files.
This function also filters the object files of mocks.
Args:
merged_library: Path where to save the merged library.
obj_files: A list of object files.
"""
# Note that we exclude mock_*.o since they contain duplicate definitions that we
# are not interested in.
logging.info(f"object files with coverage data: {pformat(obj_files)}")
run(
LLD_HOST,
"--shared",
"-o",
str(merged_library),
*[o for o in obj_files if not PurePath(o).name.startswith("mock_")],
)
def handle_test_targets(test_targets: List[str]) -> List[str]:
"""Add some base library tests to the given list of tests.
Args:
test_targets: A list of test targets.
Returns:
The given list of targets along with some base library tests.
"""
res = test_targets + [
"//sw/device/lib/base:hardened_memory_unittest",
"//sw/device/lib/base:math_unittest",
"//sw/device/lib/base:math_builtins_unittest",
"//sw/device/lib/base:memory_unittest",
]
logging.info(f"test targets: {pformat(res)}")
return res
def handle_test_log_dirs(test_log_dirs: List[Path]) -> List[Path]:
"""Get coverage profiles.
This function returns the paths of individual coverage profiles for the given list of
test log directories.
Args:
test_log_dirs: A list of test log directories.
Returns:
Paths of individual coverage profiles.
"""
return [d / "coverage.dat" for d in test_log_dirs]
PARAMS = CoverageParams(
bazel_test_type=BazelTestType.CC_TEST,
config="ot_coverage_off_target",
libs_fn=handle_libs,
objs_fn=handle_objs,
test_targets_fn=handle_test_targets,
test_log_dirs_fn=handle_test_log_dirs,
report_title="OpenTitan Unit Test Coverage",
)