blob: 13497150455487112468fc66fd141459288381ab [file] [log] [blame]
#! /usr/bin/env python3
#
# Copyright 2020 The Android Open Source Project
#
# 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
#
# http://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.
# Regenerate some ART test related files.
# This script handles only a subset of ART run-tests at the moment; additional
# cases will be added later.
import argparse
import collections
import json
import logging
import os
import re
import sys
import textwrap
import xml.dom.minidom
ME = os.path.basename(sys.argv[0])
# Common advisory placed at the top of all generated files.
ADVISORY = f"Generated by `{ME}`. Do not edit manually."
# Default indentation unit.
INDENT = " "
# Indentation unit for XML files.
XML_INDENT = " "
def reindent(str, indent = ""):
"""Reindent literal string while removing common leading spaces."""
return textwrap.indent(textwrap.dedent(str), indent)
# The prefix used in the Soong module name of all ART run-tests.
ART_RUN_TEST_MODULE_NAME_PREFIX = "art-run-test-"
# Known failing ART run-tests.
# TODO(rpl): Investigate and address the causes of failures.
known_failing_tests = [
"004-SignalTest",
"004-UnsafeTest",
"030-bad-finalizer",
"034-call-null",
"038-inner-null",
"044-proxy",
"051-thread",
"054-uncaught",
"086-null-super",
"087-gc-after-link",
"096-array-copy-concurrent-gc",
"115-native-bridge",
"116-nodex2oat",
"1336-short-finalizer-timeout",
"1337-gc-coverage",
"1339-dead-reference-safe",
"134-nodex2oat-nofallback",
"136-daemon-jni-shutdown",
"139-register-natives",
"148-multithread-gc-annotations",
"149-suspend-all-stress",
"150-loadlibrary",
"154-gc-loop",
"158-app-image-class-table",
"169-threadgroup-jni",
"172-app-image-twice",
"177-visibly-initialized-deadlock",
"178-app-image-native-method",
"179-nonvirtual-jni",
"1900-track-alloc",
"1901-get-bytecodes",
"1902-suspend",
"1903-suspend-self",
"1904-double-suspend",
"1905-suspend-native",
"1906-suspend-list-me-first",
"1907-suspend-list-self-twice",
"1908-suspend-native-resume-self",
"1909-per-agent-tls",
"1910-transform-with-default",
"1911-get-local-var-table",
"1912-get-set-local-primitive",
"1913-get-set-local-objects",
"1914-get-local-instance",
"1915-get-set-local-current-thread",
"1916-get-set-current-frame",
"1917-get-stack-frame",
"1919-vminit-thread-start-timing",
"1920-suspend-native-monitor",
"1921-suspend-native-recursive-monitor",
"1922-owned-monitors-info",
"1923-frame-pop",
"1924-frame-pop-toggle",
"1925-self-frame-pop",
"1926-missed-frame-pop",
"1927-exception-event",
"1928-exception-event-exception",
"1930-monitor-info",
"1931-monitor-events",
"1932-monitor-events-misc",
"1933-monitor-current-contended",
"1934-jvmti-signal-thread",
"1935-get-set-current-frame-jit",
"1936-thread-end-events",
"1937-transform-soft-fail",
"1938-transform-abstract-single-impl",
"1939-proxy-frames",
"1941-dispose-stress",
"1942-suspend-raw-monitor-exit",
"1943-suspend-raw-monitor-wait",
"1945-proxy-method-arguments",
"1947-breakpoint-redefine-deopt",
"1949-short-dex-file",
"1951-monitor-enter-no-suspend",
"1953-pop-frame",
"1954-pop-frame-jit",
"1955-pop-frame-jit-called",
"1956-pop-frame-jit-calling",
"1957-error-ext",
"1958-transform-try-jit",
"1959-redefine-object-instrument",
"1960-obsolete-jit-multithread-native",
"1961-obsolete-jit-multithread",
"1962-multi-thread-events",
"1963-add-to-dex-classloader-in-memory",
"1967-get-set-local-bad-slot",
"1968-force-early-return",
"1969-force-early-return-void",
"1970-force-early-return-long",
"1971-multi-force-early-return",
"1972-jni-id-swap-indices",
"1973-jni-id-swap-pointer",
"1974-resize-array",
"1975-hello-structural-transformation",
"1976-hello-structural-static-methods",
"1977-hello-structural-obsolescence",
"1978-regular-obsolete-then-structural-obsolescence",
"1979-threaded-structural-transformation",
"1980-obsolete-object-cleared",
"1982-no-virtuals-structural-redefinition",
"1984-structural-redefine-field-trace",
"1985-structural-redefine-stack-scope",
"1986-structural-redefine-multi-thread-stack-scope",
"1987-structural-redefine-recursive-stack-scope",
"1988-multi-structural-redefine",
"1989-transform-bad-monitor",
"1990-structural-bad-verify",
"1991-hello-structural-retransform",
"1992-retransform-no-such-field",
"1993-fallback-non-structural",
"1994-final-virtual-structural",
"1995-final-virtual-structural-multithread",
"1996-final-override-virtual-structural",
"1997-structural-shadow-method",
"1998-structural-shadow-field",
"1999-virtual-structural",
"2003-double-virtual-structural",
"2004-double-virtual-structural-abstract",
"2005-pause-all-redefine-multithreaded",
"2008-redefine-then-old-reflect-field",
"2011-stack-walk-concurrent-instrument",
"203-multi-checkpoint",
"2031-zygote-compiled-frame-deopt",
"2033-shutdown-mechanics",
"2036-jni-filechannel",
"2037-thread-name-inherit",
"305-other-fault-handler",
"449-checker-bce",
"454-get-vreg",
"461-get-reference-vreg",
"466-get-live-vreg",
"497-inlining-and-class-loader",
"530-regression-lse",
"555-UnsafeGetLong-regression",
"566-polymorphic-inlining",
"595-profile-saving",
"597-deopt-busy-loop",
"597-deopt-invoke-stub",
"597-deopt-new-string",
"602-deoptimizeable",
"604-hot-static-interface",
"616-cha-abstract",
"616-cha-interface",
"616-cha-miranda",
"616-cha-native",
"616-cha-regression-proxy-method",
"616-cha",
"623-checker-loop-regressions",
"626-set-resolved-string",
"629-vdex-speed",
"638-checker-inline-cache-intrinsic",
"642-fp-callees",
"647-jni-get-field-id",
"652-deopt-intrinsic",
"655-jit-clinit",
"656-loop-deopt",
"660-clinit",
"661-oat-writer-layout",
"664-aget-verifier",
"667-jit-jni-stub",
"674-hotness-compiled",
"679-locks",
"680-checker-deopt-dex-pc-0",
"685-deoptimizeable",
"687-deopt",
"689-zygote-jit-deopt",
"693-vdex-inmem-loader-evict",
"707-checker-invalid-profile",
"708-jit-cache-churn",
"717-integer-value-of",
"720-thread-priority",
"728-imt-conflict-zygote", # Custom `run` script + dependency on `libarttest`.
"813-fp-args", # Dependency on `libarttest`.
"900-hello-plugin",
"901-hello-ti-agent",
"902-hello-transformation",
"903-hello-tagging",
"904-object-allocation",
"905-object-free",
"906-iterate-heap",
"907-get-loaded-classes",
"908-gc-start-finish",
"910-methods",
"911-get-stack-trace",
"913-heaps",
"914-hello-obsolescence",
"915-obsolete-2",
"916-obsolete-jit",
"917-fields-transformation",
"918-fields",
"919-obsolete-fields",
"920-objects",
"921-hello-failure",
"922-properties",
"923-monitors",
"924-threads",
"925-threadgroups",
"926-multi-obsolescence",
"927-timers",
"928-jni-table",
"930-hello-retransform",
"931-agent-thread",
"932-transform-saves",
"933-misc-events",
"937-hello-retransform-package",
"939-hello-transformation-bcp",
"940-recursive-obsolete",
"941-recursive-obsolete-jit",
"942-private-recursive",
"943-private-recursive-jit",
"944-transform-classloaders",
"945-obsolete-native",
"946-obsolete-throw",
"947-reflect-method",
"949-in-memory-transform",
"950-redefine-intrinsic",
"951-threaded-obsolete",
"982-ok-no-retransform",
"983-source-transform-verify",
"984-obsolete-invoke",
"985-re-obsolete",
"986-native-method-bind",
"987-agent-bind",
"988-method-trace",
"989-method-trace-throw",
"990-field-trace",
"991-field-trace-2",
"992-source-data",
"993-breakpoints",
"994-breakpoint-line",
"995-breakpoints-throw",
"996-breakpoint-obsolete",
"997-single-step",
]
# More known failing tests, related to Checker.
# TODO(rpl): Investigate and address the causes of failures.
known_failing_tests.extend([
# Fails (on flame-userdebug) with:
#
# java.lang.RuntimeException: Error running Checker
# error: Statement could not be matched starting from line 564575
# RemTest.java:289: lsr x{{\d+}}, x{{\d+}}, #32
# ISA_FEATURES = {'a53': True, 'crc': True, 'lse': False, 'fp16': False, 'dotprod': False, 'sve': False}
#
"411-checker-hdiv-hrem-const",
# Fails (on aosp_cf_x86_phone-userdebug) with:
#
# Error while running Checker: java.lang.RuntimeException: Error running Checker command:
# error: Statement could not be matched starting from line 317325
# Main.java:296: InvokeStaticOrDirect
# ISA_FEATURES = {'ssse3': True, 'sse4': False}
# NewInstance = l6
#
"476-checker-ctor-fence-redun-elim",
# Fails (on aosp_cf_x86_phone-userdebug) with:
#
# Error while running Checker: java.lang.RuntimeException: Error running Checker command:
# error: Statement could not be matched starting from line 264874
# Main.java:77: InvokeStaticOrDirect [{{([ij]\d+,)?}}<<ClinitCheck>>]
# ClinitCheck = l4
# ISA_FEATURES = {'ssse3': True, 'sse4': False}
# LoadClass = l3
#
"478-checker-clinit-check-pruning",
# Fails (on aosp_cf_x86_phone-userdebug) with:
#
# Error while running Checker: java.lang.RuntimeException: Error running Checker command:
# error: Statement could not be matched starting from line 124181
# Main.java:178: <<Arg:z\d+>> StaticFieldGet liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>]
# ISA_FEATURES = {'ssse3': True, 'sse4': False}
#
"482-checker-loop-back-edge-use",
# Fails (on aosp_cf_x86_phone-userdebug) with:
#
# Error while running Checker: java.lang.RuntimeException: Error running Checker command:
# error: Statement could not be matched starting from line 7333
# Main.java:66: <<t1:i\d+>> Add [<<Arg>>,<<Const1>>] {{.*->e(bp|si|di)}}
# Arg = i0
# Const1 = i3
# ISA_FEATURES = {'ssse3': True, 'sse4': False}
#
"526-checker-caller-callee-regs",
# Fails (on aosp_cf_x86_phone-userdebug) with:
#
# Error while running Checker: java.lang.RuntimeException: Error running Checker command:
# error: NOT statement matched line 379347
# Main.java:538: NewInstance
# ISA_FEATURES = {'ssse3': True, 'sse4': False}
#
"530-checker-lse",
# Fails (on aosp_cf_x86_phone-userdebug) with:
#
# Error while running Checker: java.lang.RuntimeException: Error running Checker command:
# error: NOT statement matched line 238857
# Main.java:650: Shl
# ISA_FEATURES = {'ssse3': True, 'sse4': False}
#
"551-checker-shifter-operand",
# Fails (on aosp_cf_x86_phone-userdebug) with:
#
# Error while running Checker: java.lang.RuntimeException: Error running Checker command:
# error: Statement could not be matched starting from line 158575
# Main.java:97: X86ComputeBaseMethodAddress
# ISA_FEATURES = {'ssse3': True, 'sse4': False}
#
"552-checker-sharpening",
# Fails (on flame-userdebug) with:
#
# java.lang.RuntimeException: Error running Checker
# error: Statement could not be matched starting from line 11964
# Main.java:59: <<ConstM42:i\d+>> IntConstant -42
# ISA_FEATURES = {'a53': True, 'crc': True, 'lse': False, 'fp16': False, 'dotprod': False, 'sve': False}
#
#
"562-checker-no-intermediate",
# Fails (on aosp_cf_x86_phone-userdebug) with:
#
# Error while running Checker: java.lang.RuntimeException: Error running Checker command:
# error: Statement could not be matched starting from line 149082
# Main.java:312: <<LoadClass:l\d+>> LoadClass class_name:Main
# ISA_FEATURES = {'ssse3': True, 'sse4': False}
# Int42 = i8
# Int43 = i10
#
"639-checker-code-sinking",
])
known_failing_tests = frozenset(known_failing_tests)
# Percentage of ART run-tests (among the ones expected to succeed) to include in
# the `presubmit` test group in `TEST_MAPPING` file -- the rest will be included
# in `postsubmit` test group.
# This value has to be a number between 0 and 100.
presubmit_tests_percentage = 75
# Percentage of ART run-tests (among the ones expected to succeed) to include in
# the `mainline-presubmit` test group in `TEST_MAPPING` file.
# This value has to be a number between 0 and 100.
mainline_presubmit_tests_percentage = 10
# Is `run_test` a Checker test (i.e. a test containing Checker
# assertions)?
def is_checker_test(run_test):
return re.match("^[0-9]+-checker-", run_test)
# Is `run_test` expected to succeed?
def is_expected_succeeding(run_test):
return run_test not in known_failing_tests
class Generator:
def __init__(self, top_dir):
"""Generator of ART test files for an Android source tree anchored at `top_dir`."""
# Path to the Android top source tree.
self.top_dir = top_dir
# Path to the ART directory
self.art_dir = os.path.join(top_dir, "art")
# Path to the ART tests directory.
self.art_test_dir = os.path.join(self.art_dir, "test")
# Path to the MTS configuration directory.
self.mts_config_dir = os.path.join(
top_dir, "test", "mts", "tools", "mts-tradefed", "res", "config")
def enumerate_run_tests(self):
return sorted([run_test
for run_test in os.listdir(self.art_test_dir)
if re.match("^[0-9]{3,}-", run_test)])
# Is building `run_test` supported?
# TODO(b/147814778): Add build support for more tests.
def is_buildable(self, run_test):
run_test_path = os.path.join(self.art_test_dir, run_test)
# Ignore tests with non-default build rules.
if os.path.isfile(os.path.join(run_test_path, "build")):
return False
# Ignore tests with no `src` directory.
if not os.path.isdir(os.path.join(run_test_path, "src")):
return False
# Ignore tests with sources outside the `src` directory.
for subdir in ["jasmin",
"jasmin-multidex",
"smali",
"smali-ex",
"smali-multidex",
"src-art",
"src-dex2oat-unresolved",
"src-ex",
"src-ex2",
"src-multidex",
"src2"]:
if os.path.isdir(os.path.join(run_test_path, subdir)):
return False
# Ignore test with a copy of `sun.misc.Unsafe`.
if os.path.isfile(os.path.join(run_test_path, "src", "sun", "misc", "Unsafe.java")):
return False
# Ignore tests with Hidden API specs.
if os.path.isfile(os.path.join(run_test_path, "hiddenapi-flags.csv")):
return False
# All other tests are considered buildable.
return True
def regen_bp_files(self, run_tests, buildable_tests):
for run_test in run_tests:
# Remove any previously generated file.
bp_file = os.path.join(self.art_test_dir, run_test, "Android.bp")
if os.path.exists(bp_file):
os.remove(bp_file)
for run_test in buildable_tests:
self.regen_bp_file(run_test)
def regen_bp_file(self, run_test):
"""Regenerate Blueprint file for an ART run-test."""
bp_file = os.path.join(self.art_test_dir, run_test, "Android.bp")
run_test_module_name = ART_RUN_TEST_MODULE_NAME_PREFIX + run_test
if is_expected_succeeding(run_test):
test_config_template = "art-run-test-target-template"
else:
test_config_template = "art-run-test-target-no-test-suite-tag-template"
if is_checker_test(run_test):
include_src = """\
// Include the Java source files in the test's artifacts, to make Checker assertions
// available to the TradeFed test runner.
include_srcs: true,"""
else:
include_src = ""
with open(bp_file, "w") as f:
f.write(textwrap.dedent(f"""\
// {ADVISORY}
// Build rules for ART run-test `{run_test}`.
// Test's Dex code.
java_test {{
name: "{run_test_module_name}",
defaults: ["art-run-test-defaults"],
test_config_template: ":{test_config_template}",
srcs: ["src/**/*.java"],
data: [
":{run_test_module_name}-expected-stdout",
":{run_test_module_name}-expected-stderr",
],{include_src}
}}
// Test's expected standard output.
genrule {{
name: "{run_test_module_name}-expected-stdout",
out: ["{run_test_module_name}-expected-stdout.txt"],
srcs: ["expected-stdout.txt"],
cmd: "cp -f $(in) $(out)",
}}
// Test's expected standard error.
genrule {{
name: "{run_test_module_name}-expected-stderr",
out: ["{run_test_module_name}-expected-stderr.txt"],
srcs: ["expected-stderr.txt"],
cmd: "cp -f $(in) $(out)",
}}
"""))
def regen_test_mapping_file(self, art_run_tests, num_presubmit_run_tests,
num_mainline_presubmit_run_tests):
"""Regenerate ART's `TEST_MAPPING`."""
run_test_module_names = [ART_RUN_TEST_MODULE_NAME_PREFIX + t for t in art_run_tests]
# Mainline presubmits.
mainline_presubmit_run_tests = [t + "[com.google.android.art.apex]"
for t
in run_test_module_names[0:num_mainline_presubmit_run_tests]]
mainline_presubmit_tests_dict = [{"name": t} for t in mainline_presubmit_run_tests]
# Presubmits.
other_presubmit_tests = [
"CtsJdwpTestCases",
"BootImageProfileTest",
"ArtServiceTests",
]
art_gtests = [
"ArtGtestsTarget",
]
presubmit_run_tests = run_test_module_names[0:num_presubmit_run_tests]
presubmit_tests = other_presubmit_tests + art_gtests + presubmit_run_tests
presubmit_tests_dict = [{"name": t} for t in presubmit_tests]
# Postsubmits.
postsubmit_run_tests = run_test_module_names[num_presubmit_run_tests:]
postsubmit_tests_dict = [{"name": t} for t in postsubmit_run_tests]
# Use an `OrderedDict` container to preserve the order in which items are inserted.
test_mapping_dict = collections.OrderedDict([
("mainline-presubmit", mainline_presubmit_tests_dict),
("presubmit", presubmit_tests_dict),
("postsubmit", postsubmit_tests_dict),
])
test_mapping_contents = json.dumps(test_mapping_dict, indent = INDENT)
test_mapping_file = os.path.join(self.art_dir, "TEST_MAPPING")
with open(test_mapping_file, "w") as f:
f.write(f"// {ADVISORY}\n")
f.write(test_mapping_contents)
f.write("\n")
def regen_art_mts_files(self, art_run_tests):
"""Regenerate ART MTS definition files."""
run_test_module_names = [ART_RUN_TEST_MODULE_NAME_PREFIX + t for t in art_run_tests]
# Regenerate `mts_art_tests_list_user_file.xml`.
root = xml.dom.minidom.Document()
configuration = root.createElement("configuration")
advisory_header = root.createComment(f" {ADVISORY} ")
root.appendChild(advisory_header)
copyright_header = root.createComment(reindent("""\
Copyright (C) 2020 The Android Open Source Project
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
http://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.
""", " "))
root.appendChild(copyright_header)
root.appendChild(configuration)
configuration.setAttribute("description", "List of ART MTS tests that do not need root access.")
# ART run-tests.
art_run_test_header = root.createComment(" ART run-tests. ")
configuration.appendChild(art_run_test_header)
art_run_test_todo = root.createComment(
" TODO(rpl): Find a way to express this list in a more concise fashion. ")
configuration.appendChild(art_run_test_todo)
for run_test_module_name in run_test_module_names:
option = root.createElement("option")
option.setAttribute("name", "compatibility:include-filter")
option.setAttribute("value", run_test_module_name)
configuration.appendChild(option)
# `MainlineTestModuleController` configuration for ART run-tests.
art_run_test_module_controller_header = root.createComment(
" Enable MainlineTestModuleController. ")
configuration.appendChild(art_run_test_module_controller_header)
art_run_test_module_controller_todo = root.createComment(
" TODO(rpl): Find a way to express this list in a more concise fashion. ")
configuration.appendChild(art_run_test_module_controller_todo)
for run_test_module_name in run_test_module_names:
option = root.createElement("option")
option.setAttribute("name", "compatibility:module-arg")
option.setAttribute("value", f"{run_test_module_name}:enable:true")
configuration.appendChild(option)
xml_str = root.toprettyxml(indent = XML_INDENT, encoding = "utf-8")
mts_art_tests_list_user_file = os.path.join(self.mts_config_dir, "mts-art-tests-list-user.xml")
with open(mts_art_tests_list_user_file, "wb") as f:
f.write(xml_str)
def regen_test_files(self, regen_art_mts):
"""Regenerate ART test files.
Args:
regen_art_mts: If true, also regenerate the ART MTS definition.
"""
run_tests = self.enumerate_run_tests()
# Create a list of the tests that can currently be built, and for
# which a Blueprint file is to be generated.
buildable_tests = list(filter(self.is_buildable, run_tests))
# Create a list of the tests that can be built and are expected to
# succeed. These tests are to be added to ART's `TEST_MAPPING`
# file and also tagged as part of TradeFed's `art-target-run-test`
# test suite via the `test-suite-tag` option in their
# configuration file.
expected_succeeding_tests = list(filter(is_expected_succeeding, buildable_tests))
# Regenerate Blueprint files.
# ---------------------------
self.regen_bp_files(run_tests, buildable_tests)
buildable_tests_percentage = int(len(buildable_tests) * 100 / len(run_tests))
print(f"Generated Blueprint files for {len(buildable_tests)} ART run-tests out of"
f" {len(run_tests)} ({buildable_tests_percentage}%).")
# Regenerate `TEST_MAPPING` file.
# -------------------------------
# Note: We only include ART run-tests expected to succeed for now.
# Note: We only include a (growing) fraction of the supported ART
# run-tests (see `presubmit_tests_percentage`) into the
# `presubmit` test group (the other ART run-tests are added to the
# `postsubmit` test group), as we initially had issues with
# Android presubmits when the whole set of supported ART run-tests
# was included in one go (b/169310621). This progressive rollout
# allows us to better monitor future potential presubmit failures.
#
# Likewise for tests in the `mainline-presubmit` group.
num_presubmit_run_tests = int(len(expected_succeeding_tests) * presubmit_tests_percentage / 100)
num_mainline_presubmit_run_tests = int(
len(expected_succeeding_tests) * mainline_presubmit_tests_percentage / 100)
self.regen_test_mapping_file(
expected_succeeding_tests, num_presubmit_run_tests, num_mainline_presubmit_run_tests)
expected_succeeding_tests_percentage = int(
len(expected_succeeding_tests) * 100 / len(run_tests))
num_postsubmit_tests = len(expected_succeeding_tests) - num_presubmit_run_tests
postsubmit_tests_percentage = 100 - presubmit_tests_percentage
print(f"Generated TEST_MAPPING entries for {len(expected_succeeding_tests)} ART run-tests out"
f" of {len(run_tests)} ({expected_succeeding_tests_percentage}%):")
for (num_tests, tests_percentage, test_group_name) in [
(num_mainline_presubmit_run_tests, mainline_presubmit_tests_percentage,
"mainline-presubmit"),
(num_presubmit_run_tests, presubmit_tests_percentage, "presubmit"),
(num_postsubmit_tests, postsubmit_tests_percentage, "postsubmit"),
]:
print(f" {num_tests} tests ({tests_percentage}%) in `{test_group_name}` test group.")
# Regenerate ART MTS definition (optional).
# -----------------------------------------
if regen_art_mts:
self.regen_art_mts_files(expected_succeeding_tests)
print(f"Generated ART MTS entries for {len(expected_succeeding_tests)} ART run-tests out"
f" of {len(run_tests)} ({expected_succeeding_tests_percentage}%).")
def main():
if "ANDROID_BUILD_TOP" not in os.environ:
logging.error("ANDROID_BUILD_TOP environment variable is empty; did you forget to run `lunch`?")
sys.exit(1)
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent("Regenerate some ART test related files."),
epilog=textwrap.dedent("""\
Regenerate ART run-tests Blueprint files, ART's `TEST_MAPPING` file, and
optionally the ART MTS (Mainline Test Suite) definition.
"""))
parser.add_argument("-m", "--regen-art-mts", help="Regenerate the ART MTS definition as well",
action="store_true")
args = parser.parse_args()
generator = Generator(os.path.join(os.environ["ANDROID_BUILD_TOP"]))
generator.regen_test_files(args.regen_art_mts)
if __name__ == "__main__":
main()