diff options
author | Kevin Dagostino <kevindagostino@google.com> | 2022-12-05 06:45:43 +0000 |
---|---|---|
committer | Kevin Dagostino <kevindagostino@google.com> | 2022-12-12 19:27:28 +0000 |
commit | ed21a6c9816e695b3c8c4426d2eba4c061effd7b (patch) | |
tree | 04b08bcf6f43ebd68964824951dd19bc2ae49602 | |
parent | d9d14c64cfb745d6ffe57415cb655e488617f69c (diff) | |
download | bazel-ed21a6c9816e695b3c8c4426d2eba4c061effd7b.tar.gz |
Support running Tradefed tests with Bazel
Replace the placeholder shell script with a working version that invokes Tradefed. Generate result-reporter.xml config. Generate test config from template if one is not specified.
Test: b test //build/bazel/rules/tradefed/...
Change-Id: I7f479492d4d3f4457465cda7c39ef3b0e074550f
-rw-r--r-- | rules/tradefed/test/BUILD.bazel | 10 | ||||
-rw-r--r-- | rules/tradefed/tradefed.bzl | 157 | ||||
-rw-r--r-- | rules/tradefed/tradefed.sh.tpl | 63 | ||||
-rw-r--r-- | rules/tradefed/tradefed_test.bzl | 33 |
4 files changed, 181 insertions, 82 deletions
diff --git a/rules/tradefed/test/BUILD.bazel b/rules/tradefed/test/BUILD.bazel index 477735d5..a8460468 100644 --- a/rules/tradefed/test/BUILD.bazel +++ b/rules/tradefed/test/BUILD.bazel @@ -1,7 +1,5 @@ -filegroup( - name = "example_configs", - srcs = glob( - ["*.xml"], - ), - visibility = ["//build/bazel/rules/tradefed:__subpackages__"], +package(default_visibility = ["//build/bazel/rules/tradefed:__subpackages__"]) + +exports_files( + glob(["*.xml"]), ) diff --git a/rules/tradefed/tradefed.bzl b/rules/tradefed/tradefed.bzl index a2f40fce..c8c1e3df 100644 --- a/rules/tradefed/tradefed.bzl +++ b/rules/tradefed/tradefed.bzl @@ -14,93 +14,128 @@ See the License for the specific language governing permissions and limitations under the License. """ -# Types where generating a tradefed config is supported. -# These map to the template specified in _config_templates -_config_templates = { - "cc": "//build/make/core:native_test_config_template.xml", - "cc-host": "//build/make/core:native_host_test_config_template.xml", -} - TRADEFED_TEST_ATTRIBUTES = { "test": attr.label( providers = [[CcInfo]], doc = "Test target to run in tradefed.", ), + "host": attr.bool( + default = False, + doc = "Is a host (deviceless) test", + ), "_tradefed_test_sh_template": attr.label( default = ":tradefed.sh.tpl", allow_single_file = True, doc = "Template script to launch tradefed.", ), - "host": attr.bool( - default = False, - doc = "Is a host (deviceless) test", + "_tradefed_dependencies": attr.label_list( + default = [ + "//prebuilts/runtime:prebuilt-runtime-adb", + "//tools/tradefederation/prebuilts/filegroups/tradefed:bp2build_all_srcs", + "//tools/tradefederation/prebuilts/filegroups/suite:compatibility-host-util-prebuilt", + "//tools/tradefederation/prebuilts/filegroups/suite:compatibility-tradefed-prebuilt", + "//tools/asuite/atest:atest-tradefed", + "//tools/asuite/atest/bazel/reporter:bazel-result-reporter", + ], + doc = "Files needed on the PATH to run tradefed", ), - # Tradefed config specific attributes. - "tradefed_configs": attr.label_list( - allow_files = True, - doc = "Tradefed configs.", + # Test config and if test config generation attributes. + "test_config": attr.label( + allow_single_file = True, + doc = "Test/Tradefed config.", ), - "_config_templates": attr.label_list( - default = _config_templates.values(), - allow_files = True, - doc = "List of templates to generate a tradefed config based on a provider type.", + "template_test_config": attr.label( + allow_single_file = True, + doc = "Template to generate test config.", ), - "extra_configs": attr.string( - doc = "Extra configs to extend into generated tf config.", + "template_configs": attr.string_list( + doc = "Extra tradefed config options to extend into generated test config.", ), - "test_install_base": attr.string( + "template_install_base": attr.string( default = "/data/local/tmp", doc = "Directory to install tests onto the device for generated config", ), } -# Generate tradefed config from template. -def _create_tradefed_test_configs(ctx): - # Check for existing tradefed configs; and symlink - if len(ctx.files.tradefed_configs) > 0: - configs = [] - for f in ctx.files.tradefed_configs: - out = ctx.actions.declare_file(f.basename + ".tradefed.config") - ctx.actions.symlink( - output = out, - target_file = f, - ) - configs.append(out) - return configs - - # No existing configs -- generate from template. - out = ctx.actions.declare_file(ctx.attr.name + ".tradefed.config") +# Get test config if specified or generate test config from template. +def _get_or_generate_test_config(ctx): + # Validate input + c = ctx.file.test_config + c_template = ctx.file.template_test_config + if c and c_template: + fail("Both test_config and test_config_template were provided, please use only 1 of them") + if not c and not c_template: + fail("Either test_config or test_config_template should be provided") + + # Check for existing tradefed configs and if found add a symlink. + if c: + out = ctx.actions.declare_file(c.basename + ".test.config") + ctx.actions.symlink( + output = out, + target_file = c, + ) + return out + + # No existing config specified - generate from template. + out = ctx.actions.declare_file(ctx.attr.name + ".test.config") + + # Join extra configs together and add xml spacing indent. + extra_configs = "\n ".join(ctx.attr.template_configs) module_name = ctx.attr.test.label.name - # Choose template based on test target provider and host attribute. - key = "" - template_file = None - if CcInfo in ctx.attr.test: - key = "cc" - if ctx.attr.host: - key += "-host" - for t in ctx.attr._config_templates: - if str(t.label) == "@" + _config_templates[key]: - template_file = t.files.to_list()[0] - if not template_file: - fail("Unsupported target for tradefed config generation: " + str(ctx.attr.test)) - ctx.actions.expand_template( - template = template_file, + template = c_template, output = out, substitutions = { "{MODULE}": module_name, - "{EXTRA_CONFIGS}": ctx.attr.extra_configs, - "{TEST_INSTALL_BASE}": ctx.attr.test_install_base, + "{EXTRA_CONFIGS}": extra_configs, + "{TEST_INSTALL_BASE}": ctx.attr.template_install_base, }, ) - return [out] + return out + +# Generate tradefed result reporter config. +def _create_result_reporter_config(ctx): + result_reporters_config_file = ctx.actions.declare_file("result-reporters.xml") + config_lines = [ + "<?xml version=\"1.0\" encoding=\"utf-8\"?>", + "<configuration>", + ] + + result_reporters = [ + "com.android.tradefed.result.BazelExitCodeResultReporter", + "com.android.tradefed.result.BazelXmlResultReporter", + ] + for result_reporter in result_reporters: + config_lines.append(" <result_reporter class=\"%s\" />" % result_reporter) + config_lines.append("</configuration>") + + ctx.actions.write(result_reporters_config_file, "\n".join(config_lines)) + return result_reporters_config_file # Generate and run tradefed bash script. def _tradefed_test_impl(ctx): - # Generate tradefed configs. - configs = _create_tradefed_test_configs(ctx) + # Get or generate test config. + test_config = _get_or_generate_test_config(ctx) + + # Generate result reporter config file. + report_config = _create_result_reporter_config(ctx) + + # Gather runfiles. + runfiles = ctx.runfiles() + runfiles = runfiles.merge_all([ + ctx.attr.test.default_runfiles, + ctx.runfiles(files = ctx.files._tradefed_dependencies + [test_config, report_config]), + ]) + + # Gather directories of runfiles to put on the PATH. + dependency_paths = {} + for f in runfiles.files.to_list(): + dependency_paths[f.dirname] = True + for f in runfiles.symlinks.to_list(): + dependency_paths[f.dirname] = True + path_additions = ":".join(dependency_paths.keys()) # Generate script to run tradefed. script = ctx.actions.declare_file("tradefed_test_%s.sh" % ctx.label.name) @@ -108,14 +143,12 @@ def _tradefed_test_impl(ctx): template = ctx.file._tradefed_test_sh_template, output = script, is_executable = True, - substitutions = {}, + substitutions = { + "{MODULE}": ctx.attr.test.label.name, + "{PATH_ADDITIONS}": path_additions, + }, ) - # Gather runfiles. - runfiles = ctx.runfiles() - runfiles = runfiles.merge(ctx.attr.test.default_runfiles) - runfiles = runfiles.merge(ctx.runfiles(files = configs)) - return [DefaultInfo( executable = script, runfiles = runfiles, diff --git a/rules/tradefed/tradefed.sh.tpl b/rules/tradefed/tradefed.sh.tpl index a38163ea..13a2368e 100644 --- a/rules/tradefed/tradefed.sh.tpl +++ b/rules/tradefed/tradefed.sh.tpl @@ -1 +1,62 @@ -echo "Will be replace with tradefed call in future CL" +#!/bin/bash +set -e +set -x + +TEST_PATH="${TEST_SRCDIR}" +RUN_PATH="${TEST_SRCDIR}/${TEST_WORKSPACE}/build/bazel/rules/tradefed/" +PATH_ADDITIONS="{PATH_ADDITIONS}" + +# Add tradefed dependencies to PATH +for dep in ${PATH_ADDITIONS//:/ }; do + export PATH="${TEST_SRCDIR}/${TEST_WORKSPACE}/$dep:${PATH}" +done + +# Prepend the REMOTE_JAVA_HOME environment variable to the path to ensure +# that all Java invocations throughout the test execution flow use the same +# version. +if [ ! -z "${REMOTE_JAVA_HOME}" ]; then + export PATH="${REMOTE_JAVA_HOME}/bin:${PATH}" +fi + +exit_code_file="$(mktemp /tmp/tf-exec-XXXXXXXXXX)" + +atest_tradefed.sh template/atest_local_min \ + --template:map test=atest \ + --template:map reporters="${RUN_PATH}/result-reporters.xml" \ + --tests-dir "$TEST_PATH" \ + --logcat-on-failure \ + --no-enable-granular-attempts \ + --no-early-device-release \ + --skip-host-arch-check \ + --include-filter "{MODULE}" \ + --skip-loading-config-jar \ + --log-level-display VERBOSE \ + --log-level VERBOSE \ + "${ADDITIONAL_TRADEFED_OPTIONS[@]}" \ + --bazel-exit-code-result-reporter:file=${exit_code_file} \ + --bazel-xml-result-reporter:file=${XML_OUTPUT_FILE} \ + --proto-output-file="${TEST_UNDECLARED_OUTPUTS_DIR}/proto-results" \ + --log-file-path="${TEST_UNDECLARED_OUTPUTS_DIR}" \ + "$@" + +# Use the TF exit code if it terminates abnormally. +tf_exit=$? +if [ ${tf_exit} -ne 0 ] +then + echo "Tradefed command failed with exit code ${tf_exit}" + exit ${tf_exit} +fi + +# Set the exit code based on the exit code in the reporter-generated file. +exit_code=$(<${exit_code_file}) +if [ $? -ne 0 ] +then + echo "Could not read exit code file: ${exit_code_file}" + exit 36 +fi + +if [ ${exit_code} -ne 0 ] +then + echo "Test failed with exit code ${exit_code}" + exit ${exit_code} +fi diff --git a/rules/tradefed/tradefed_test.bzl b/rules/tradefed/tradefed_test.bzl index 2cbe4cf1..2316f9da 100644 --- a/rules/tradefed/tradefed_test.bzl +++ b/rules/tradefed/tradefed_test.bzl @@ -60,6 +60,7 @@ def tradefed_cc_outputs(): name = name, tags = ["manual"], test = target, + test_config = "//build/bazel/rules/tradefed/test:example_config.xml", target_compatible_with = ["//build/bazel/platforms/os:linux"], ) @@ -69,11 +70,12 @@ def tradefed_cc_outputs(): target_under_test = name, expected_outputs = [ "tradefed_test_" + name + ".sh", - name + ".tradefed.config", + "result-reporters.xml", + "example_config.xml.test.config", ], target_compatible_with = ["//build/bazel/platforms/os:linux"], ) - return name + return name + "_test" def tradefed_cc_host_outputs(): name = "cc_host" @@ -87,6 +89,7 @@ def tradefed_cc_host_outputs(): name = name, tags = ["manual"], test = target, + test_config = "//build/bazel/rules/tradefed/test:example_config.xml", target_compatible_with = ["//build/bazel/platforms/os:linux"], ) @@ -96,15 +99,16 @@ def tradefed_cc_host_outputs(): target_under_test = name, expected_outputs = [ "tradefed_test_" + name + ".sh", - name + ".tradefed.config", + "result-reporters.xml", + "example_config.xml.test.config", ], target_compatible_with = ["//build/bazel/platforms/os:linux"], ) - return name + return name + "_test" -def tradefed_cc_host_outputs_with_existing_tf_config(): - name = "cc_host_with_example_config" - target = "cc_host_target_with_example_config" +def tradefed_cc_host_outputs_generate_test_config(): + name = "cc_host_generate_config" + target = "cc_host_target_generate_config" cc_object( name = target, @@ -114,10 +118,12 @@ def tradefed_cc_host_outputs_with_existing_tf_config(): name = name, tags = ["manual"], test = target, - target_compatible_with = ["//build/bazel/platforms/os:linux"], - tradefed_configs = [ - "//build/bazel/rules/tradefed/test:example_configs", + template_test_config = "//build/make/core:native_host_test_config_template.xml", + template_configs = [ + "<option name=\"config-descriptor:metadata\" key=\"parameter\" value=\"not_multi_abi\" />", + "<option name=\"config-descriptor:metadata\" key=\"parameter\" value=\"secondary_user\" />", ], + target_compatible_with = ["//build/bazel/platforms/os:linux"], ) # check for expected output files (.config file and .sh script) @@ -126,11 +132,12 @@ def tradefed_cc_host_outputs_with_existing_tf_config(): target_under_test = name, expected_outputs = [ "tradefed_test_" + name + ".sh", - "example_config.xml.tradefed.config", + "result-reporters.xml", + "cc_host_generate_config.test.config", ], target_compatible_with = ["//build/bazel/platforms/os:linux"], ) - return name + return name + "_test" def tradefed_test_suite(name): native.test_suite( @@ -138,6 +145,6 @@ def tradefed_test_suite(name): tests = [ tradefed_cc_outputs(), tradefed_cc_host_outputs(), - tradefed_cc_host_outputs_with_existing_tf_config(), + tradefed_cc_host_outputs_generate_test_config(), ], ) |