blob: a1f52e19ab0f3ec78aa1875ec86dedd4dd87a5a3 [file]
# Copyright 2024 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Rules for declaring unit tests."""
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_cc//cc:cc_test.bzl", "cc_test")
load("//pw_build:compatibility.bzl", "incompatible_with_mcu")
load(
"//pw_compilation_testing:pw_cc_nc_test.bzl",
_check_and_update_nc_test_deps = "check_and_update_nc_test_deps",
_pw_cc_nc_test = "pw_cc_nc_test",
)
def pw_cc_test(name, has_nc_test = False, deps = None, **kwargs):
"""Wrapper for cc_test that provides additional features.
pw_cc_test expands to the following targets:
* $name: Runs all associated tests
* $name.cc_test: standard cc_test target with a dep on //pw_unit_test:test_main.
* $name.nc_test: negative compilation test (if has_nc_test = True).
* $name.lib: cc_library version of the cc_test.
pw_cc_test automatically adds necessary link-time dependencies to the cc_test and cc_library.
The .lib target that is created is a cc_library version of the cc_test.
These library targets can be used as dependencies of firmware images
bundling multiple tests. The library target has alwayslink = 1 to support
dynamic registration. This ensures the tests are baked into the image even
though there are no references to them, so that they can be found by
RUN_ALL_TESTS at runtime.
Args:
name: base name of the test target.
has_nc_test: set to True to enable PW_NC_TESTs.
deps: Dependencies forwarded to the cc_test and cc_library.
**kwargs: Other arguments forwarded to the cc_test and cc_library.
"""
deps = [] if deps == None else deps
deps.append(str(Label("//pw_build:default_link_extra_lib")))
deps.append(str(Label("//pw_unit_test:pw_unit_test_alias_for_migration_only")))
# If there are multiple test targets, group them into a test_suite.
if has_nc_test:
cc_test_name = name + ".cc_test"
native.test_suite(
name = name,
tests = [cc_test_name, name + ".nc_test"],
tags = kwargs.get("tags"),
)
else:
cc_test_name = name
# Use a test_suite to alias $name.cc_test to $name. This ensures $name.cc_test always
# exists, but avoids adding a new label to Bazel's test output, which an alias would.
native.test_suite(
name = name + ".cc_test",
tests = [name],
tags = kwargs.get("tags"),
)
# Check for incorrectly added NC test deps and add them if needed.
_check_and_update_nc_test_deps(has_nc_test, deps)
if has_nc_test:
if "srcs" not in kwargs:
fail("pw_cc_test requires a 'srcs' argument if has_nc_test = True")
_pw_cc_nc_test(
name = name + ".nc_test",
base = cc_test_name,
srcs = kwargs["srcs"],
tags = kwargs.get("tags"),
# TODO: https://pwbug.dev/452721904 - These produce shell scripts
# that emit the results, which are incompatible with device/MCU
# builds.
target_compatible_with = incompatible_with_mcu() + kwargs.get("target_compatible_with", []),
# TODO: https://pwbug.dev/446943440 - Handle more common attributes.
)
# Add the cc_test with the unit test main label flag dep.
test_main = kwargs.pop("test_main", str(Label("//pw_unit_test:main")))
cc_test(name = cc_test_name, deps = deps + [test_main], **kwargs)
# Update kwargs for the cc_library version of the cc_test. This must be last.
kwargs["alwayslink"] = 1
# pw_cc_test libraries may include testonly targets.
kwargs["testonly"] = True
# Remove any kwargs that cc_library would not recognize.
for arg in (
"additional_linker_inputs",
"args",
"env",
"env_inherit",
"flaky",
"local",
"malloc",
"shard_count",
"size",
"stamp",
"timeout",
):
kwargs.pop(arg, "")
cc_library(name = name + ".lib", deps = deps, **kwargs)