Introduce a Testing Runtime APEX (test) module including ART gtests.

Define a new flavor of the Runtime APEX, having the same contents
as the Debug Runtime APEX plus ART gtests that have dependencies
on Runtime APEX internal libraries.

Previously, when these ART gtests were built and installed in
the data partition, they would depend on "legacy" ART internal
libraries being installed in the system partition (not the ones
from the Runtime APEX). As we plan to remove these ART libraries
from the system partition, we needed a way to be able to build
and install device ART gtests without triggering the installation
of these legacy ART internal libraries.

This Testing Runtime APEX is meant to be used for ART testing only,
and should never be included in any product.

This change adds build rules for the Testing Runtime APEX (and
corresponding unit tests), but does not replace the Debug Runtime APEX
for device testing yet (this will be implemented in a follow-up
change).

Also rename `art_apex_test` module type as `art_apex_test_host`.

Test: m com.android.runtime.testing
Test: art/build/apex/runtests.sh
Test: art/build/apex/art_apex_test.py
Bug: 129534335
Change-Id: I8d70bdcf7c6253dd5bc8786a702f130d444c3cb6
diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py
index 3bcf7c6..86acfa6 100755
--- a/build/apex/art_apex_test.py
+++ b/build/apex/art_apex_test.py
@@ -26,6 +26,14 @@
 
 logging.basicConfig(format='%(message)s')
 
+# Architectures supported by APEX packages.
+archs = ["arm", "arm64", "x86", "x86_64"]
+# Directory containing ART tests within a Runtime APEX (if the package includes
+# any). ART test executables are installed in `bin/art/<arch>`. Segregating
+# tests by architecture is useful on devices supporting more than one
+# architecture, as it permits testing all of them using a single Runtime APEX
+# package.
+art_test_dir = 'bin/test'
 
 class FSObject:
   def __init__(self, name, is_dir, is_exec, is_symlink, size):
@@ -270,6 +278,28 @@
       self.fail('%s is not a symlink', path)
     self._expected_file_globs.add(path)
 
+  def check_art_test_executable(self, filename):
+    # This is a simplistic implementation, as we declare victory as soon as the
+    # test binary is found for one of the supported (not built) architectures.
+    # Ideally we would propagate the built architectures from the build system
+    # to this script and require test binaries for all of them to be present.
+    # Note that this behavior is not specific to this method: there are other
+    # places in this script where we rely on this simplified strategy.
+    #
+    # TODO: Implement the suggestion above (here and in other places in this
+    # script).
+    test_found = False
+    for arch in archs:
+      test_path = '%s/%s/%s' % (art_test_dir, arch, filename)
+      test_is_file, _ = self.is_file(test_path)
+      if test_is_file:
+        test_found = True
+        self._expected_file_globs.add(test_path)
+        if not self._provider.get(test_path).is_exec:
+          self.fail('%s is not executable', test_path)
+    if not test_found:
+      self.fail('ART test binary missing: %s', filename)
+
   def check_single_library(self, filename):
     lib_path = 'lib/%s' % filename
     lib64_path = 'lib64/%s' % filename
@@ -288,6 +318,10 @@
   def ignore_path(self, path_glob):
     self._expected_file_globs.add(path_glob)
 
+  def check_optional_art_test_executable(self, filename):
+    for arch in archs:
+      self.ignore_path('%s/%s/%s' % (art_test_dir, arch, filename))
+
   def check_no_superfluous_files(self, dir_path):
     paths = []
     for name in sorted(self._provider.read_dir(dir_path).keys()):
@@ -616,6 +650,267 @@
     self._checker.check_prefer64_library('libprocinfo')
 
 
+class TestingTargetChecker:
+  def __init__(self, checker):
+    self._checker = checker
+
+  def __str__(self):
+    return 'Testing (Target) Checker'
+
+  def run(self):
+    # Check cmdline tests.
+    self._checker.check_optional_art_test_executable('cmdline_parser_test')
+
+    # Check compiler tests.
+    self._checker.check_art_test_executable('atomic_dex_ref_map_test')
+    self._checker.check_art_test_executable('bounds_check_elimination_test')
+    self._checker.check_art_test_executable('codegen_test')
+    self._checker.check_art_test_executable('compiled_method_storage_test')
+    self._checker.check_art_test_executable('data_type_test')
+    self._checker.check_art_test_executable('dedupe_set_test')
+    self._checker.check_art_test_executable('dominator_test')
+    self._checker.check_art_test_executable('dwarf_test')
+    self._checker.check_art_test_executable('exception_test')
+    self._checker.check_art_test_executable('find_loops_test')
+    self._checker.check_art_test_executable('graph_checker_test')
+    self._checker.check_art_test_executable('graph_test')
+    self._checker.check_art_test_executable('gvn_test')
+    self._checker.check_art_test_executable('induction_var_analysis_test')
+    self._checker.check_art_test_executable('induction_var_range_test')
+    self._checker.check_art_test_executable('jni_cfi_test')
+    self._checker.check_art_test_executable('jni_compiler_test')
+    self._checker.check_art_test_executable('licm_test')
+    self._checker.check_art_test_executable('linker_patch_test')
+    self._checker.check_art_test_executable('live_interval_test')
+    self._checker.check_art_test_executable('load_store_analysis_test')
+    self._checker.check_art_test_executable('loop_optimization_test')
+    self._checker.check_art_test_executable('nodes_test')
+    self._checker.check_art_test_executable('nodes_vector_test')
+    self._checker.check_art_test_executable('optimizing_cfi_test')
+    self._checker.check_art_test_executable('output_stream_test')
+    self._checker.check_art_test_executable('parallel_move_test')
+    self._checker.check_art_test_executable('pretty_printer_test')
+    self._checker.check_art_test_executable('reference_type_propagation_test')
+    self._checker.check_art_test_executable('scheduler_test')
+    self._checker.check_art_test_executable('select_generator_test')
+    self._checker.check_art_test_executable('side_effects_test')
+    self._checker.check_art_test_executable('src_map_elem_test')
+    self._checker.check_art_test_executable('ssa_liveness_analysis_test')
+    self._checker.check_art_test_executable('ssa_test')
+    self._checker.check_art_test_executable('stack_map_test')
+    self._checker.check_art_test_executable('superblock_cloner_test')
+    self._checker.check_art_test_executable('suspend_check_test')
+    self._checker.check_art_test_executable('swap_space_test')
+    # These tests depend on a specific code generator and are conditionally included.
+    self._checker.check_optional_art_test_executable('constant_folding_test')
+    self._checker.check_optional_art_test_executable('dead_code_elimination_test')
+    self._checker.check_optional_art_test_executable('linearize_test')
+    self._checker.check_optional_art_test_executable('live_ranges_test')
+    self._checker.check_optional_art_test_executable('liveness_test')
+    self._checker.check_optional_art_test_executable('managed_register_arm64_test')
+    self._checker.check_optional_art_test_executable('managed_register_arm_test')
+    self._checker.check_optional_art_test_executable('managed_register_mips64_test')
+    self._checker.check_optional_art_test_executable('managed_register_x86_64_test')
+    self._checker.check_optional_art_test_executable('managed_register_x86_test')
+    self._checker.check_optional_art_test_executable('register_allocator_test')
+
+    # Check dex2oat tests.
+    self._checker.check_art_test_executable('compiler_driver_test')
+    self._checker.check_art_test_executable('dex2oat_image_test')
+    self._checker.check_art_test_executable('dex2oat_test')
+    self._checker.check_art_test_executable('dex_to_dex_decompiler_test')
+    self._checker.check_art_test_executable('elf_writer_test')
+    self._checker.check_art_test_executable('image_test')
+    self._checker.check_art_test_executable('image_write_read_test')
+    self._checker.check_art_test_executable('index_bss_mapping_encoder_test')
+    self._checker.check_art_test_executable('multi_oat_relative_patcher_test')
+    self._checker.check_art_test_executable('oat_writer_test')
+    self._checker.check_art_test_executable('verifier_deps_test')
+    # These tests depend on a specific code generator and are conditionally included.
+    self._checker.check_optional_art_test_executable('relative_patcher_arm64_test')
+    self._checker.check_optional_art_test_executable('relative_patcher_mips32r6_test')
+    self._checker.check_optional_art_test_executable('relative_patcher_mips64_test')
+    self._checker.check_optional_art_test_executable('relative_patcher_mips_test')
+    self._checker.check_optional_art_test_executable('relative_patcher_thumb2_test')
+    self._checker.check_optional_art_test_executable('relative_patcher_x86_64_test')
+    self._checker.check_optional_art_test_executable('relative_patcher_x86_test')
+
+    # Check dexanalyze tests.
+    self._checker.check_optional_art_test_executable('dexanalyze_test')
+
+    # Check dexdiag tests.
+    self._checker.check_optional_art_test_executable('dexdiag_test')
+
+    # Check dexdump tests.
+    self._checker.check_art_test_executable('dexdump_test')
+
+    # Check dexlayout tests.
+    self._checker.check_optional_art_test_executable('dexlayout_test')
+
+    # Check dexlist tests.
+    self._checker.check_art_test_executable('dexlist_test')
+
+    # Check dexoptanalyzer tests.
+    self._checker.check_art_test_executable('dexoptanalyzer_test')
+
+    # Check imgdiag tests.
+    self._checker.check_art_test_executable('imgdiag_test')
+
+    # Check libartbase tests.
+    self._checker.check_art_test_executable('arena_allocator_test')
+    self._checker.check_art_test_executable('bit_field_test')
+    self._checker.check_art_test_executable('bit_memory_region_test')
+    self._checker.check_art_test_executable('bit_string_test')
+    self._checker.check_art_test_executable('bit_struct_test')
+    self._checker.check_art_test_executable('bit_table_test')
+    self._checker.check_art_test_executable('bit_utils_test')
+    self._checker.check_art_test_executable('bit_vector_test')
+    self._checker.check_art_test_executable('fd_file_test')
+    self._checker.check_art_test_executable('file_utils_test')
+    self._checker.check_art_test_executable('hash_set_test')
+    self._checker.check_art_test_executable('hex_dump_test')
+    self._checker.check_art_test_executable('histogram_test')
+    self._checker.check_art_test_executable('indenter_test')
+    self._checker.check_art_test_executable('instruction_set_test')
+    self._checker.check_art_test_executable('intrusive_forward_list_test')
+    self._checker.check_art_test_executable('leb128_test')
+    self._checker.check_art_test_executable('logging_test')
+    self._checker.check_art_test_executable('mem_map_test')
+    self._checker.check_art_test_executable('membarrier_test')
+    self._checker.check_art_test_executable('memfd_test')
+    self._checker.check_art_test_executable('memory_region_test')
+    self._checker.check_art_test_executable('memory_type_table_test')
+    self._checker.check_art_test_executable('safe_copy_test')
+    self._checker.check_art_test_executable('scoped_flock_test')
+    self._checker.check_art_test_executable('time_utils_test')
+    self._checker.check_art_test_executable('transform_array_ref_test')
+    self._checker.check_art_test_executable('transform_iterator_test')
+    self._checker.check_art_test_executable('utils_test')
+    self._checker.check_art_test_executable('variant_map_test')
+    self._checker.check_art_test_executable('zip_archive_test')
+
+    # Check libartpalette tests.
+    self._checker.check_art_test_executable('palette_test')
+
+    # Check libdexfile tests.
+    self._checker.check_art_test_executable('art_dex_file_loader_test')
+    self._checker.check_art_test_executable('art_libdexfile_support_tests')
+    self._checker.check_art_test_executable('class_accessor_test')
+    self._checker.check_art_test_executable('code_item_accessors_test')
+    self._checker.check_art_test_executable('compact_dex_file_test')
+    self._checker.check_art_test_executable('compact_offset_table_test')
+    self._checker.check_art_test_executable('descriptors_names_test')
+    self._checker.check_art_test_executable('dex_file_loader_test')
+    self._checker.check_art_test_executable('dex_file_verifier_test')
+    self._checker.check_art_test_executable('dex_instruction_test')
+    self._checker.check_art_test_executable('primitive_test')
+    self._checker.check_art_test_executable('string_reference_test')
+    self._checker.check_art_test_executable('test_dex_file_builder_test')
+    self._checker.check_art_test_executable('type_lookup_table_test')
+    self._checker.check_art_test_executable('utf_test')
+
+    # Check libprofile tests.
+    self._checker.check_optional_art_test_executable('profile_boot_info_test')
+    self._checker.check_optional_art_test_executable('profile_compilation_info_test')
+
+    # Check oatdump tests.
+    self._checker.check_art_test_executable('oatdump_app_test')
+    self._checker.check_art_test_executable('oatdump_image_test')
+    self._checker.check_art_test_executable('oatdump_test')
+
+    # Check profman tests.
+    self._checker.check_art_test_executable('profile_assistant_test')
+
+    # Check runtime compiler tests.
+    self._checker.check_art_test_executable('module_exclusion_test')
+    self._checker.check_art_test_executable('reflection_test')
+
+    # Check runtime tests.
+    self._checker.check_art_test_executable('arch_test')
+    self._checker.check_art_test_executable('barrier_test')
+    self._checker.check_art_test_executable('card_table_test')
+    self._checker.check_art_test_executable('cha_test')
+    self._checker.check_art_test_executable('class_linker_test')
+    self._checker.check_art_test_executable('class_loader_context_test')
+    self._checker.check_art_test_executable('class_table_test')
+    self._checker.check_art_test_executable('compiler_filter_test')
+    self._checker.check_art_test_executable('dex_cache_test')
+    self._checker.check_art_test_executable('dlmalloc_space_random_test')
+    self._checker.check_art_test_executable('dlmalloc_space_static_test')
+    self._checker.check_art_test_executable('entrypoints_order_test')
+    self._checker.check_art_test_executable('exec_utils_test')
+    self._checker.check_art_test_executable('gtest_test')
+    self._checker.check_art_test_executable('handle_scope_test')
+    self._checker.check_art_test_executable('heap_test')
+    self._checker.check_art_test_executable('heap_verification_test')
+    self._checker.check_art_test_executable('hidden_api_test')
+    self._checker.check_art_test_executable('image_space_test')
+    self._checker.check_art_test_executable('immune_spaces_test')
+    self._checker.check_art_test_executable('imtable_test')
+    self._checker.check_art_test_executable('indirect_reference_table_test')
+    self._checker.check_art_test_executable('instruction_set_features_arm64_test')
+    self._checker.check_art_test_executable('instruction_set_features_arm_test')
+    self._checker.check_art_test_executable('instruction_set_features_mips64_test')
+    self._checker.check_art_test_executable('instruction_set_features_mips_test')
+    self._checker.check_art_test_executable('instruction_set_features_test')
+    self._checker.check_art_test_executable('instruction_set_features_x86_64_test')
+    self._checker.check_art_test_executable('instruction_set_features_x86_test')
+    self._checker.check_art_test_executable('instrumentation_test')
+    self._checker.check_art_test_executable('intern_table_test')
+    self._checker.check_art_test_executable('java_vm_ext_test')
+    self._checker.check_art_test_executable('jdwp_options_test')
+    self._checker.check_art_test_executable('jit_memory_region_test')
+    self._checker.check_art_test_executable('jni_internal_test')
+    self._checker.check_art_test_executable('large_object_space_test')
+    self._checker.check_art_test_executable('math_entrypoints_test')
+    self._checker.check_art_test_executable('memcmp16_test')
+    self._checker.check_art_test_executable('method_handles_test')
+    self._checker.check_art_test_executable('method_type_test')
+    self._checker.check_art_test_executable('method_verifier_test')
+    self._checker.check_art_test_executable('mod_union_table_test')
+    self._checker.check_art_test_executable('monitor_pool_test')
+    self._checker.check_art_test_executable('monitor_test')
+    self._checker.check_art_test_executable('mutex_test')
+    self._checker.check_art_test_executable('oat_file_assistant_test')
+    self._checker.check_art_test_executable('oat_file_test')
+    self._checker.check_art_test_executable('object_test')
+    self._checker.check_art_test_executable('parsed_options_test')
+    self._checker.check_art_test_executable('prebuilt_tools_test')
+    self._checker.check_art_test_executable('profiling_info_test')
+    self._checker.check_art_test_executable('proxy_test')
+    self._checker.check_art_test_executable('quick_trampoline_entrypoints_test')
+    self._checker.check_art_test_executable('reference_queue_test')
+    self._checker.check_art_test_executable('reference_table_test')
+    self._checker.check_art_test_executable('reg_type_test')
+    self._checker.check_art_test_executable('rosalloc_space_random_test')
+    self._checker.check_art_test_executable('rosalloc_space_static_test')
+    self._checker.check_art_test_executable('runtime_callbacks_test')
+    self._checker.check_art_test_executable('runtime_test')
+    self._checker.check_art_test_executable('safe_math_test')
+    self._checker.check_art_test_executable('space_bitmap_test')
+    self._checker.check_art_test_executable('space_create_test')
+    self._checker.check_art_test_executable('stub_test')
+    self._checker.check_art_test_executable('subtype_check_info_test')
+    self._checker.check_art_test_executable('subtype_check_test')
+    self._checker.check_art_test_executable('system_weak_test')
+    self._checker.check_art_test_executable('task_processor_test')
+    self._checker.check_art_test_executable('thread_pool_test')
+    self._checker.check_art_test_executable('timing_logger_test')
+    self._checker.check_art_test_executable('transaction_test')
+    self._checker.check_art_test_executable('two_runtimes_test')
+    self._checker.check_art_test_executable('unstarted_runtime_test')
+    self._checker.check_art_test_executable('var_handle_test')
+    self._checker.check_art_test_executable('vdex_file_test')
+
+    # Check sigchainlib tests.
+    self._checker.check_art_test_executable('sigchain_test')
+
+    # Check ART test (internal) libraries.
+    self._checker.check_native_library('libart-gtest')
+    self._checker.check_native_library('libartd-disassembler')
+    self._checker.check_native_library('libartd-simulator-container')
+
+
 class NoSuperfluousBinariesChecker:
   def __init__(self, checker):
     self._checker = checker
@@ -642,6 +937,18 @@
     self._checker.check_no_superfluous_files('lib64/bionic')
 
 
+class NoSuperfluousArtTestsChecker:
+  def __init__(self, checker):
+    self._checker = checker
+
+  def __str__(self):
+    return 'No superfluous ART tests checker'
+
+  def run(self):
+    for arch in archs:
+      self._checker.check_no_superfluous_files('%s/%s' % (art_test_dir, arch))
+
+
 class List:
   def __init__(self, provider, print_size):
     self._provider = provider
@@ -731,15 +1038,24 @@
   if test_args.tree and test_args.debug:
     logging.error("Both of --tree and --debug set")
     return 1
+  if test_args.tree and test_args.testing:
+    logging.error("Both of --tree and --testing set")
+    return 1
   if test_args.list and test_args.debug:
     logging.error("Both of --list and --debug set")
     return 1
+  if test_args.list and test_args.testing:
+    logging.error("Both of --list and --testing set")
+    return 1
   if test_args.list and test_args.tree:
     logging.error("Both of --list and --tree set")
     return 1
   if test_args.size and not (test_args.list or test_args.tree):
     logging.error("--size set but neither --list nor --tree set")
     return 1
+  if test_args.host and test_args.testing:
+    logging.error("Both of --host and --testing set")
+    return 1
   if not test_args.tmpdir:
     logging.error("Need a tmpdir.")
     return 1
@@ -800,13 +1116,16 @@
     checkers.append(ReleaseHostChecker(base_checker))
   else:
     checkers.append(ReleaseTargetChecker(base_checker))
-  if test_args.debug:
+  if test_args.debug or test_args.testing:
     checkers.append(DebugChecker(base_checker))
-  if test_args.debug and not test_args.host:
-    checkers.append(DebugTargetChecker(base_checker))
+    if not test_args.host:
+      checkers.append(DebugTargetChecker(base_checker))
+  if test_args.testing:
+    checkers.append(TestingTargetChecker(base_checker))
 
   # These checkers must be last.
   checkers.append(NoSuperfluousBinariesChecker(base_checker))
+  checkers.append(NoSuperfluousArtTestsChecker(base_checker))
   if not test_args.host:
     # We only care about superfluous libraries on target, where their absence
     # can be vital to ensure they get picked up from the right package.
@@ -851,8 +1170,9 @@
 
   # TODO: Add host support
   configs = [
-    {'name': 'com.android.runtime.release', 'debug': False, 'host': False},
-    {'name': 'com.android.runtime.debug', 'debug': True, 'host': False},
+    {'name': 'com.android.runtime.release', 'debug': False, 'testing': False, 'host': False},
+    {'name': 'com.android.runtime.debug',   'debug': True,  'testing': False, 'host': False},
+    {'name': 'com.android.runtime.testing', 'debug': False, 'testing': True,  'host': False},
   ]
 
   for config in configs:
@@ -864,6 +1184,7 @@
       logging.error("Cannot find APEX %s. Please build it first.", test_args.apex)
       continue
     test_args.debug = config['debug']
+    test_args.testing = config['testing']
     test_args.host = config['host']
     failed = art_apex_test_main(test_args) != 0
 
@@ -881,6 +1202,7 @@
   parser.add_argument('--flattened', help='Check as flattened (target) apex', action='store_true')
 
   parser.add_argument('--debug', help='Check as debug apex', action='store_true')
+  parser.add_argument('--testing', help='Check as testing apex', action='store_true')
 
   parser.add_argument('--list', help='List all files', action='store_true')
   parser.add_argument('--tree', help='Print directory tree', action='store_true')