• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2022 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15TRADEFED_TEST_ATTRIBUTES = {
16    "test": attr.label(
17        providers = [[CcInfo]],
18        doc = "Test target to run in tradefed.",
19    ),
20    "test_identifier": attr.string(),
21    "host_driven": attr.bool(
22        default = True,
23        doc = "Is a host driven test",
24    ),
25    "_tradefed_test_sh_template": attr.label(
26        default = ":tradefed.sh.tpl",
27        allow_single_file = True,
28        doc = "Template script to launch tradefed.",
29    ),
30    "_tradefed_dependencies": attr.label_list(
31        default = [
32            "//prebuilts/runtime:prebuilt-runtime-adb",
33            "//tools/tradefederation/prebuilts/filegroups/tradefed:bp2build_all_srcs",
34            "//tools/tradefederation/prebuilts/filegroups/suite:compatibility-host-util-prebuilt",
35            "//tools/tradefederation/prebuilts/filegroups/suite:compatibility-tradefed-prebuilt",
36            "//tools/asuite/atest:atest-tradefed",
37            "//tools/asuite/atest/bazel/reporter:bazel-result-reporter",
38        ],
39        doc = "Files needed on the PATH to run tradefed",
40        cfg = "exec",
41    ),
42
43    # Test config and if test config generation attributes.
44    "test_config": attr.label(
45        allow_single_file = True,
46        doc = "Test/Tradefed config.",
47    ),
48    "template_test_config": attr.label(
49        allow_single_file = True,
50        doc = "Template to generate test config.",
51    ),
52    "template_configs": attr.string_list(
53        doc = "Extra tradefed config options to extend into generated test config.",
54    ),
55    "template_install_base": attr.string(
56        default = "/data/local/tmp",
57        doc = "Directory to install tests onto the device for generated config",
58    ),
59}
60
61# Get test config if specified or generate test config from template.
62def _get_or_generate_test_config(ctx):
63    # Validate input
64    c = ctx.file.test_config
65    c_template = ctx.file.template_test_config
66    if c and c_template:
67        fail("Both test_config and test_config_template were provided, please use only 1 of them")
68    if not c and not c_template:
69        fail("Either test_config or test_config_template should be provided")
70
71    # Check for existing tradefed config - and add a symlink with test_identifier.
72    out = ctx.actions.declare_file(ctx.attr.test_identifier + ".config")
73    if c:
74        ctx.actions.symlink(
75            output = out,
76            target_file = c,
77        )
78        return out
79
80    # No test config found, generate config from template.
81    # Join extra configs together and add xml spacing indent.
82    extra_configs = "\n    ".join(ctx.attr.template_configs)
83    ctx.actions.expand_template(
84        template = c_template,
85        output = out,
86        substitutions = {
87            "{MODULE}": ctx.attr.test_identifier,
88            "{EXTRA_CONFIGS}": extra_configs,
89            "{TEST_INSTALL_BASE}": ctx.attr.template_install_base,
90        },
91    )
92    return out
93
94# Generate tradefed result reporter config.
95def _create_result_reporter_config(ctx):
96    result_reporters_config_file = ctx.actions.declare_file("result-reporters.xml")
97    config_lines = [
98        "<?xml version=\"1.0\" encoding=\"utf-8\"?>",
99        "<configuration>",
100    ]
101
102    result_reporters = [
103        "com.android.tradefed.result.BazelExitCodeResultReporter",
104        "com.android.tradefed.result.BazelXmlResultReporter",
105    ]
106    for result_reporter in result_reporters:
107        config_lines.append("    <result_reporter class=\"%s\" />" % result_reporter)
108    config_lines.append("</configuration>")
109
110    ctx.actions.write(result_reporters_config_file, "\n".join(config_lines))
111    return result_reporters_config_file
112
113# Generate and run tradefed bash script.
114def _tradefed_test_impl(ctx):
115    # Get or generate test config.
116    test_config = _get_or_generate_test_config(ctx)
117
118    # Generate result reporter config file.
119    report_config = _create_result_reporter_config(ctx)
120
121    # Symlink file names if `__test_binary` was appended in a previous rule.
122    targets = []
123    for f in ctx.attr.test.files.to_list():
124        if "__test_binary" not in f.basename:
125            targets.append(f)
126        else:
127            file_name = f.basename.replace("__test_binary", "")
128            out = ctx.actions.declare_file(file_name)
129            ctx.actions.symlink(
130                output = out,
131                target_file = f,
132            )
133            targets.append(out)
134
135    # Symlink tradefed dependencies.
136    for f in ctx.files._tradefed_dependencies:
137        out = ctx.actions.declare_file(f.basename)
138        ctx.actions.symlink(
139            output = out,
140            target_file = f,
141        )
142        targets.append(out)
143
144    # Gather runfiles.
145    runfiles = ctx.runfiles()
146    runfiles = runfiles.merge_all([
147        ctx.attr.test.default_runfiles,
148        ctx.runfiles(files = targets + [test_config, report_config]),
149    ])
150
151    # Generate script to run tradefed.
152    script = ctx.actions.declare_file("tradefed_test_%s.sh" % ctx.label.name)
153    ctx.actions.expand_template(
154        template = ctx.file._tradefed_test_sh_template,
155        output = script,
156        is_executable = True,
157        substitutions = {
158            "{MODULE}": ctx.attr.test_identifier,
159        },
160    )
161
162    return [DefaultInfo(
163        executable = script,
164        runfiles = runfiles,
165    )]
166
167# Generate and run tradefed bash script for deviceless (host) tests.
168_tradefed_test = rule(
169    doc = "A rule used to run tests using Tradefed",
170    attrs = TRADEFED_TEST_ATTRIBUTES,
171    test = True,
172    implementation = _tradefed_test_impl,
173)
174
175def tradefed_host_driven_test(**kwargs):
176    _tradefed_test(
177        **kwargs
178    )
179
180def tradefed_device_test(**kwargs):
181    _tradefed_test(
182        host_driven = False,
183        **kwargs
184    )
185