xref: /aosp_15_r20/external/skia/tools/testrunners/common/android/android_test.bzl (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1"""This module defines the android_test macro."""
2
3load("//bazel:skia_rules.bzl", "skia_cc_binary")
4load("//tools/testrunners/common:binary_wrapper_script_with_cmdline_flags.bzl", "binary_wrapper_script_with_cmdline_flags")
5load("//tools/testrunners/common/android:adb_test.bzl", "adb_test")
6
7def android_test(
8        name,
9        srcs,
10        deps = [],
11        extra_args = [],
12        benchmark = False,
13        requires_resources_dir = False,
14        save_output_files = False):
15    """Defines an Android test.
16
17    Note: This macro is not intended to be used directly in BUILD files. Instead, please use macros
18    android_unit_test, android_gm_test, android_benchmark_test, etc.
19
20    This macro compiles one or more C++ tests into a single Android binary and produces a script
21    that runs the test on an attached Android device via `adb`. This macro is compatible with unit,
22    GM and benchmark tests.
23
24    The test target produced by this macro can be executed on a machine attached to an Android
25    device. This can be either via USB, or by port-forwarding a remote ADB server (TCP port 5037)
26    running on a machine attached to the target device, such as a Skolo Raspberry Pi.
27
28    High-level overview of how this rule works:
29
30    - It produces a <name>.tar.gz archive containing the Android binary, a minimal launcher script
31      that invokes the binary on the device under test with any necessary command-line arguments,
32      and any static resources needed by the C++ tests, such as fonts and images under //resources.
33    - It produces a <name> test runner script that extracts the tarball into the device via `adb`,
34      sets up the device, runs the test, cleans up and pipes through the test's exit code.
35    - Optionally, the <name> test runner script can be configured to download from the device any
36      files produced by the C++ tests (such as PNG and JSON files produced by GM tests). These
37      files will be available as undeclared test outputs (see documentation for the
38      TEST_UNDECLARED_OUTPUTS_DIR environment variable at
39      https://bazel.build/reference/test-encyclopedia#initial-conditions).
40
41    For CI jobs, rather than invoking "bazel test" on a Raspberry Pi attached to the Android device
42    under test, we compile and run the test in two separate tasks:
43
44    - A build task running on a GCE machine compiles the test on RBE with Bazel and stores the
45      <name>.tar.gz and <name> output files to CAS.
46    - A test task running on a Skolo Raspberry Pi downloads <name>.tar.gz and <name> from CAS and
47      executes <name> *outside of Bazel*.
48
49    The reason why we don't want to run Bazel on a Raspberry Pi is due to its constrained
50    resources.
51
52    Note: Although not currently supported, we could use a similar approach for Apple devices in
53    in the future.
54
55    Args:
56        name: The name of the test.
57        srcs: A list of C++ source files.
58        deps: Any dependencies needed by the srcs.
59        extra_args: Additional command-line arguments to pass to the test, for example, any
60            device-specific --skip flags to skip incompatible or buggy test cases.
61        benchmark: Set up the device for benchmark tests. This might affect e.g. CPU and GPU
62            settings specific to the Android device under test.
63        requires_resources_dir: If set, the contents of the //resources directory will be included
64            in the tarball that is pushed to the device via `adb push`, and the test binary will be
65            invoked with flag --resourcePath set to the path to said directory.
66        save_output_files: If true, save any files produced by this test (e.g. PNG and JSON files
67            in the case of GM tests) as undeclared outputs (see documentation for the
68            TEST_UNDECLARED_OUTPUTS_DIR environment variable at
69            https://bazel.build/reference/test-encyclopedia#initial-conditions).
70    """
71
72    test_binary = "%s_binary" % name
73
74    skia_cc_binary(
75        name = test_binary,
76        srcs = srcs,
77        deps = deps,
78        testonly = True,  # Needed to gain access to test-only files.
79    )
80
81    test_runner = "%s_runner" % name
82
83    binary_wrapper_script_with_cmdline_flags(
84        name = test_runner,
85        binary = test_binary,
86        extra_args = extra_args,
87        requires_resources_dir = requires_resources_dir,
88        testonly = True,  # Needed to gain access to test-only files.
89    )
90
91    archive = "%s_archive" % name
92    archive_srcs = [test_runner, test_binary] + (
93        ["//resources"] if requires_resources_dir else []
94    )
95
96    # Create an archive containing the test and its resources, with a structure that emulates
97    # the environment expected by the test when executed via "bazel test". This archive can be
98    # pushed to an Android device via "adb push", and once extracted, the test binary can be
99    # executed on the device via "adb shell" as long as the working directory is set to the
100    # directory where the archive is extracted.
101    #
102    # See https://bazel.build/reference/test-encyclopedia#initial-conditions.
103    native.genrule(
104        name = archive,
105        srcs = archive_srcs,
106        outs = ["%s.tar.gz" % name],
107        cmd = """
108            $(location //tools/testrunners/common/make_tarball) \
109                --execpaths "{execpaths}" \
110                --rootpaths "{rootpaths}" \
111                --output-file $@
112        """.format(
113            execpaths = " ".join(["$(execpaths %s)" % src for src in archive_srcs]),
114            rootpaths = " ".join(["$(rootpaths %s)" % src for src in archive_srcs]),
115        ),
116        testonly = True,  # Needed to gain access to test-only files.
117        # Tools are always built for the exec platform
118        # (https://bazel.build/reference/be/general#genrule.tools), e.g. Linux on x86_64 when
119        # running on a gLinux workstation or on a Linux GCE machine.
120        tools = ["//tools/testrunners/common/make_tarball"],
121    )
122
123    adb_test(
124        name = name,
125        archive = archive,
126        test_runner = test_runner,
127        benchmark = benchmark,
128        save_output_files = save_output_files,
129        tags = ["no-remote"],  # Incompatible with RBE because it requires an Android device.
130        target_compatible_with = ["@platforms//os:android"],
131    )
132