blob: 3706672043bc729bfde1408d19cffb9daaba77ee [file] [log] [blame]
"""This module defines the android_test macro."""
load("//bazel:skia_rules.bzl", "skia_cc_binary")
load("//tools/testrunners/common:binary_wrapper_script_with_cmdline_flags.bzl", "binary_wrapper_script_with_cmdline_flags")
load("//tools/testrunners/common/android:adb_test.bzl", "adb_test")
def android_test(
name,
srcs,
deps = [],
extra_args = [],
benchmark = False,
requires_resources_dir = False,
save_output_files = False):
"""Defines an Android test.
Note: This macro is not intended to be used directly in BUILD files. Instead, please use macros
android_unit_test, android_gm_test, android_benchmark_test, etc.
This macro compiles one or more C++ tests into a single Android binary and produces a script
that runs the test on an attached Android device via `adb`. This macro is compatible with unit,
GM and benchmark tests.
The test target produced by this macro can be executed on a machine attached to an Android
device. This can be either via USB, or by port-forwarding a remote ADB server (TCP port 5037)
running on a machine attached to the target device, such as a Skolo Raspberry Pi.
High-level overview of how this rule works:
- It produces a <name>.tar.gz archive containing the Android binary, a minimal launcher script
that invokes the binary on the device under test with any necessary command-line arguments,
and any static resources needed by the C++ tests, such as fonts and images under //resources.
- It produces a <name> test runner script that extracts the tarball into the device via `adb`,
sets up the device, runs the test, cleans up and pipes through the test's exit code.
- Optionally, the <name> test runner script can be configured to download from the device any
files produced by the C++ tests (such as PNG and JSON files produced by GM tests). These
files will be available as undeclared test outputs (see documentation for the
TEST_UNDECLARED_OUTPUTS_DIR environment variable at
https://bazel.build/reference/test-encyclopedia#initial-conditions).
For CI jobs, rather than invoking "bazel test" on a Raspberry Pi attached to the Android device
under test, we compile and run the test in two separate tasks:
- A build task running on a GCE machine compiles the test on RBE with Bazel and stores the
<name>.tar.gz and <name> output files to CAS.
- A test task running on a Skolo Raspberry Pi downloads <name>.tar.gz and <name> from CAS and
executes <name> *outside of Bazel*.
The reason why we don't want to run Bazel on a Raspberry Pi is due to its constrained
resources.
Note: Although not currently supported, we could use a similar approach for Apple devices in
in the future.
Args:
name: The name of the test.
srcs: A list of C++ source files.
deps: Any dependencies needed by the srcs.
extra_args: Additional command-line arguments to pass to the test, for example, any
device-specific --skip flags to skip incompatible or buggy test cases.
benchmark: Set up the device for benchmark tests. This might affect e.g. CPU and GPU
settings specific to the Android device under test.
requires_resources_dir: If set, the contents of the //resources directory will be included
in the tarball that is pushed to the device via `adb push`, and the test binary will be
invoked with flag --resourcePath set to the path to said directory.
save_output_files: If true, save any files produced by this test (e.g. PNG and JSON files
in the case of GM tests) as undeclared outputs (see documentation for the
TEST_UNDECLARED_OUTPUTS_DIR environment variable at
https://bazel.build/reference/test-encyclopedia#initial-conditions).
"""
test_binary = "%s_binary" % name
skia_cc_binary(
name = test_binary,
srcs = srcs,
deps = deps,
testonly = True, # Needed to gain access to test-only files.
)
test_runner = "%s_runner" % name
binary_wrapper_script_with_cmdline_flags(
name = test_runner,
binary = test_binary,
extra_args = extra_args,
requires_resources_dir = requires_resources_dir,
testonly = True, # Needed to gain access to test-only files.
)
archive = "%s_archive" % name
archive_srcs = [test_runner, test_binary] + (
["//resources"] if requires_resources_dir else []
)
# Create an archive containing the test and its resources, with a structure that emulates
# the environment expected by the test when executed via "bazel test". This archive can be
# pushed to an Android device via "adb push", and once extracted, the test binary can be
# executed on the device via "adb shell" as long as the working directory is set to the
# directory where the archive is extracted.
#
# See https://bazel.build/reference/test-encyclopedia#initial-conditions.
native.genrule(
name = archive,
srcs = archive_srcs,
outs = ["%s.tar.gz" % name],
cmd = """
$(location //tools/testrunners/common/make_tarball) \
--execpaths "{execpaths}" \
--rootpaths "{rootpaths}" \
--output-file $@
""".format(
execpaths = " ".join(["$(execpaths %s)" % src for src in archive_srcs]),
rootpaths = " ".join(["$(rootpaths %s)" % src for src in archive_srcs]),
),
testonly = True, # Needed to gain access to test-only files.
# Tools are always built for the exec platform
# (https://bazel.build/reference/be/general#genrule.tools), e.g. Linux on x86_64 when
# running on a gLinux workstation or on a Linux GCE machine.
tools = ["//tools/testrunners/common/make_tarball"],
)
adb_test(
name = name,
archive = archive,
test_runner = test_runner,
benchmark = benchmark,
save_output_files = save_output_files,
tags = ["no-remote"], # Incompatible with RBE because it requires an Android device.
target_compatible_with = ["@platforms//os:android"],
)