blob: 5ead8dab49eafb6a62fe73c571eef67c555a49df [file] [log] [blame]
Vladimir Markoc716cb82021-04-23 10:11:44 +00001#!/usr/bin/env python3
Roland Levillain29e740f2019-08-20 15:31:37 +01002# -*- coding: utf-8 -*-
Andreas Gampe2c846cd2019-01-29 22:06:46 +00003
4# Copyright (C) 2019 The Android Open Source Project
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19import argparse
Martin Stjernholm84a32cd2019-03-29 16:39:46 +000020import fnmatch
Andreas Gampe2c846cd2019-01-29 22:06:46 +000021import logging
22import os
Martin Stjernholm84a32cd2019-03-29 16:39:46 +000023import os.path
Martin Stjernholm571a6be2021-05-25 01:16:53 +010024import shutil
Andreas Gampe2c846cd2019-01-29 22:06:46 +000025import subprocess
26import sys
27import zipfile
28
29logging.basicConfig(format='%(message)s')
30
Orion Hodsonaf3ed622019-10-03 16:30:54 +010031# Flavors of ART APEX package.
32FLAVOR_RELEASE = 'release'
33FLAVOR_DEBUG = 'debug'
34FLAVOR_TESTING = 'testing'
35FLAVOR_AUTO = 'auto'
36FLAVORS_ALL = [FLAVOR_RELEASE, FLAVOR_DEBUG, FLAVOR_TESTING, FLAVOR_AUTO]
37
38# Bitness options for APEX package
39BITNESS_32 = '32'
40BITNESS_64 = '64'
41BITNESS_MULTILIB = 'multilib'
42BITNESS_AUTO = 'auto'
43BITNESS_ALL = [BITNESS_32, BITNESS_64, BITNESS_MULTILIB, BITNESS_AUTO]
44
Roland Levillain61f07162019-06-26 12:44:04 +010045# Architectures supported by APEX packages.
Victor Hsieh52f7f632021-09-24 11:50:55 -070046ARCHS_32 = ["arm", "x86"]
47ARCHS_64 = ["arm64", "x86_64"]
48
49# Multilib options
50MULTILIB_32 = '32'
51MULTILIB_64 = '64'
52MULTILIB_BOTH = 'both'
53MULTILIB_FIRST = 'first'
Orion Hodsonaf3ed622019-10-03 16:30:54 +010054
Martin Stjernholme58624f2019-09-20 15:53:40 +010055# Directory containing ART tests within an ART APEX (if the package includes
Roland Levillain61f07162019-06-26 12:44:04 +010056# any). ART test executables are installed in `bin/art/<arch>`. Segregating
57# tests by architecture is useful on devices supporting more than one
Martin Stjernholme58624f2019-09-20 15:53:40 +010058# architecture, as it permits testing all of them using a single ART APEX
Roland Levillain61f07162019-06-26 12:44:04 +010059# package.
Orion Hodsonaf3ed622019-10-03 16:30:54 +010060ART_TEST_DIR = 'bin/art'
Luca Stefani4e91ee92019-03-06 15:08:16 +010061
Ulya Trafimovich7b0df592020-01-03 13:29:00 +000062
63# Test if a given variable is set to a string "true".
64def isEnvTrue(var):
65 return var in os.environ and os.environ[var] == 'true'
66
67
Martin Stjernholm571a6be2021-05-25 01:16:53 +010068def extract_apex(apex_path, deapexer_path, debugfs_path, tmpdir):
69 _, apex_name = os.path.split(apex_path)
70 extract_path = os.path.join(tmpdir, apex_name)
71 if os.path.exists(extract_path):
72 shutil.rmtree(extract_path)
73 subprocess.check_call([deapexer_path, '--debugfs', debugfs_path,
74 'extract', apex_path, extract_path],
75 stdout=subprocess.DEVNULL)
76 return extract_path
77
78
Andreas Gampe2c846cd2019-01-29 22:06:46 +000079class FSObject:
Roland Levillain88e55692019-07-25 15:57:06 +010080 def __init__(self, name, is_dir, is_exec, is_symlink, size):
Andreas Gampe2c846cd2019-01-29 22:06:46 +000081 self.name = name
82 self.is_dir = is_dir
83 self.is_exec = is_exec
84 self.is_symlink = is_symlink
Roland Levillain88e55692019-07-25 15:57:06 +010085 self.size = size
Luca Stefani4e91ee92019-03-06 15:08:16 +010086
Andreas Gampe2c846cd2019-01-29 22:06:46 +000087 def __str__(self):
Roland Levillain88e55692019-07-25 15:57:06 +010088 return '%s(dir=%r,exec=%r,symlink=%r,size=%d)' \
89 % (self.name, self.is_dir, self.is_exec, self.is_symlink, self.size)
Andreas Gampe2c846cd2019-01-29 22:06:46 +000090
Luca Stefani4e91ee92019-03-06 15:08:16 +010091
Andreas Gampe2c846cd2019-01-29 22:06:46 +000092class TargetApexProvider:
Roland Levillaindd20d002019-07-19 16:09:47 +010093 def __init__(self, apex):
94 self._folder_cache = {}
95 self._apex = apex
96
97 def get(self, path):
98 apex_dir, name = os.path.split(path)
99 if not apex_dir:
100 apex_dir = '.'
101 apex_map = self.read_dir(apex_dir)
102 return apex_map[name] if name in apex_map else None
103
104 def read_dir(self, apex_dir):
105 if apex_dir in self._folder_cache:
106 return self._folder_cache[apex_dir]
107 apex_map = {}
108 dirname = os.path.join(self._apex, apex_dir)
109 if os.path.exists(dirname):
110 for basename in os.listdir(dirname):
111 filepath = os.path.join(dirname, basename)
112 is_dir = os.path.isdir(filepath)
113 is_exec = os.access(filepath, os.X_OK)
114 is_symlink = os.path.islink(filepath)
Roland Levillain3cd802e2020-02-20 15:31:20 +0000115 if is_symlink:
116 # Report the length of the symlink's target's path as file size, like `ls`.
117 size = len(os.readlink(filepath))
118 else:
119 size = os.path.getsize(filepath)
Roland Levillain88e55692019-07-25 15:57:06 +0100120 apex_map[basename] = FSObject(basename, is_dir, is_exec, is_symlink, size)
Roland Levillaindd20d002019-07-19 16:09:47 +0100121 self._folder_cache[apex_dir] = apex_map
122 return apex_map
123
124
Andreas Gampe09123952019-01-30 13:17:02 -0800125class HostApexProvider:
126 def __init__(self, apex, tmpdir):
127 self._tmpdir = tmpdir
Roland Levillain77251f92019-08-09 15:00:04 +0100128 self._folder_cache = {}
Andreas Gampe09123952019-01-30 13:17:02 -0800129 self._payload = os.path.join(self._tmpdir, 'apex_payload.zip')
130 # Extract payload to tmpdir.
Luca Stefani4e91ee92019-03-06 15:08:16 +0100131 apex_zip = zipfile.ZipFile(apex)
132 apex_zip.extract('apex_payload.zip', tmpdir)
Andreas Gampe09123952019-01-30 13:17:02 -0800133
134 def __del__(self):
135 # Delete temps.
136 if os.path.exists(self._payload):
137 os.remove(self._payload)
138
139 def get(self, path):
Luca Stefani4e91ee92019-03-06 15:08:16 +0100140 apex_dir, name = os.path.split(path)
141 if not apex_dir:
142 apex_dir = ''
143 apex_map = self.read_dir(apex_dir)
144 return apex_map[name] if name in apex_map else None
Andreas Gampe09123952019-01-30 13:17:02 -0800145
Luca Stefani4e91ee92019-03-06 15:08:16 +0100146 def read_dir(self, apex_dir):
Roland Levillain77251f92019-08-09 15:00:04 +0100147 if apex_dir in self._folder_cache:
148 return self._folder_cache[apex_dir]
149 if not self._folder_cache:
Andreas Gampe09123952019-01-30 13:17:02 -0800150 self.parse_zip()
Roland Levillain77251f92019-08-09 15:00:04 +0100151 if apex_dir in self._folder_cache:
152 return self._folder_cache[apex_dir]
Andreas Gampe09123952019-01-30 13:17:02 -0800153 return {}
154
155 def parse_zip(self):
Luca Stefani4e91ee92019-03-06 15:08:16 +0100156 apex_zip = zipfile.ZipFile(self._payload)
157 infos = apex_zip.infolist()
Andreas Gampe09123952019-01-30 13:17:02 -0800158 for zipinfo in infos:
159 path = zipinfo.filename
160
161 # Assume no empty file is stored.
162 assert path
163
164 def get_octal(val, index):
Luca Stefani4e91ee92019-03-06 15:08:16 +0100165 return (val >> (index * 3)) & 0x7
166
Andreas Gampe09123952019-01-30 13:17:02 -0800167 def bits_is_exec(val):
168 # TODO: Enforce group/other, too?
169 return get_octal(val, 2) & 1 == 1
170
171 is_zipinfo = True
172 while path:
Luca Stefani4e91ee92019-03-06 15:08:16 +0100173 apex_dir, base = os.path.split(path)
Andreas Gampe09123952019-01-30 13:17:02 -0800174 # TODO: If directories are stored, base will be empty.
175
Roland Levillain77251f92019-08-09 15:00:04 +0100176 if apex_dir not in self._folder_cache:
177 self._folder_cache[apex_dir] = {}
178 dir_map = self._folder_cache[apex_dir]
Luca Stefani4e91ee92019-03-06 15:08:16 +0100179 if base not in dir_map:
Andreas Gampe09123952019-01-30 13:17:02 -0800180 if is_zipinfo:
181 bits = (zipinfo.external_attr >> 16) & 0xFFFF
182 is_dir = get_octal(bits, 4) == 4
183 is_symlink = get_octal(bits, 4) == 2
184 is_exec = bits_is_exec(bits)
Roland Levillain88e55692019-07-25 15:57:06 +0100185 size = zipinfo.file_size
Andreas Gampe09123952019-01-30 13:17:02 -0800186 else:
187 is_exec = False # Seems we can't get this easily?
188 is_symlink = False
189 is_dir = True
Roland Levillain88e55692019-07-25 15:57:06 +0100190 # Use a negative value as an indicator of undefined/unknown size.
191 size = -1
192 dir_map[base] = FSObject(base, is_dir, is_exec, is_symlink, size)
Andreas Gampe09123952019-01-30 13:17:02 -0800193 is_zipinfo = False
Luca Stefani4e91ee92019-03-06 15:08:16 +0100194 path = apex_dir
195
Andreas Gampe09123952019-01-30 13:17:02 -0800196
Andreas Gampeeb555b82019-01-30 14:47:49 -0800197# DO NOT USE DIRECTLY! This is an "abstract" base class.
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000198class Checker:
199 def __init__(self, provider):
200 self._provider = provider
201 self._errors = 0
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000202 self._expected_file_globs = set()
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000203
Luca Stefani4e91ee92019-03-06 15:08:16 +0100204 def fail(self, msg, *fail_args):
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000205 self._errors += 1
Martin Stjernholm2babede2019-03-18 21:04:49 +0000206 logging.error(msg, *fail_args)
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000207
208 def error_count(self):
209 return self._errors
Luca Stefani4e91ee92019-03-06 15:08:16 +0100210
Andreas Gampe9dc4b052019-01-30 13:47:25 -0800211 def reset_errors(self):
212 self._errors = 0
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000213
Martin Stjernholm2babede2019-03-18 21:04:49 +0000214 def is_file(self, path):
215 fs_object = self._provider.get(path)
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000216 if fs_object is None:
Luca Stefani4e91ee92019-03-06 15:08:16 +0100217 return False, 'Could not find %s'
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000218 if fs_object.is_dir:
Luca Stefani4e91ee92019-03-06 15:08:16 +0100219 return False, '%s is a directory'
Roland Levillaina79a6eb2022-05-20 00:05:07 +0100220 if fs_object.is_symlink:
221 return False, '%s is a symlink'
Luca Stefani4e91ee92019-03-06 15:08:16 +0100222 return True, ''
Andreas Gampea0242cf2019-01-29 13:01:23 -0800223
Ulyana Trafimovich7a20cbd2019-11-08 11:27:31 +0000224 def is_dir(self, path):
225 fs_object = self._provider.get(path)
226 if fs_object is None:
227 return False, 'Could not find %s'
228 if not fs_object.is_dir:
229 return False, '%s is not a directory'
230 return True, ''
231
Martin Stjernholm2babede2019-03-18 21:04:49 +0000232 def check_file(self, path):
233 ok, msg = self.is_file(path)
234 if not ok:
235 self.fail(msg, path)
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000236 self._expected_file_globs.add(path)
Martin Stjernholm2babede2019-03-18 21:04:49 +0000237 return ok
Luca Stefani4e91ee92019-03-06 15:08:16 +0100238
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000239 def check_executable(self, filename):
Martin Stjernholm2babede2019-03-18 21:04:49 +0000240 path = 'bin/%s' % filename
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000241 if not self.check_file(path):
Luca Stefani4e91ee92019-03-06 15:08:16 +0100242 return
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000243 if not self._provider.get(path).is_exec:
244 self.fail('%s is not executable', path)
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000245
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000246 def check_executable_symlink(self, filename):
Martin Stjernholm2babede2019-03-18 21:04:49 +0000247 path = 'bin/%s' % filename
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000248 fs_object = self._provider.get(path)
249 if fs_object is None:
250 self.fail('Could not find %s', path)
Luca Stefani4e91ee92019-03-06 15:08:16 +0100251 return
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000252 if fs_object.is_dir:
253 self.fail('%s is a directory', path)
Luca Stefani4e91ee92019-03-06 15:08:16 +0100254 return
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000255 if not fs_object.is_symlink:
256 self.fail('%s is not a symlink', path)
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000257 self._expected_file_globs.add(path)
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000258
Victor Hsieh52f7f632021-09-24 11:50:55 -0700259 def arch_dirs_for_path(self, path, multilib=None):
Ulyana Trafimovich7a20cbd2019-11-08 11:27:31 +0000260 # Look for target-specific subdirectories for the given directory path.
261 # This is needed because the list of build targets is not propagated
262 # to this script.
Ulyana Trafimovich0f7c7922019-11-07 16:12:09 +0000263 #
Roland Levillain48136182019-11-15 13:39:03 +0000264 # TODO(b/123602136): Pass build target information to this script and fix
265 # all places where this function in used (or similar workarounds).
Ulyana Trafimovich7a20cbd2019-11-08 11:27:31 +0000266 dirs = []
Victor Hsieh52f7f632021-09-24 11:50:55 -0700267 for arch in self.possible_archs(multilib):
Ulyana Trafimovich7a20cbd2019-11-08 11:27:31 +0000268 dir = '%s/%s' % (path, arch)
269 found, _ = self.is_dir(dir)
270 if found:
271 dirs.append(dir)
272 return dirs
273
Victor Hsieh52f7f632021-09-24 11:50:55 -0700274 def check_art_test_executable(self, filename, multilib=None):
275 dirs = self.arch_dirs_for_path(ART_TEST_DIR, multilib)
Ulyana Trafimovich7a20cbd2019-11-08 11:27:31 +0000276 if not dirs:
Roland Levillain61f07162019-06-26 12:44:04 +0100277 self.fail('ART test binary missing: %s', filename)
Ulyana Trafimovich7a20cbd2019-11-08 11:27:31 +0000278 for dir in dirs:
279 test_path = '%s/%s' % (dir, filename)
280 self._expected_file_globs.add(test_path)
281 if not self._provider.get(test_path).is_exec:
282 self.fail('%s is not executable', test_path)
Roland Levillain61f07162019-06-26 12:44:04 +0100283
David Srbecky4a88a5a2020-05-05 16:21:57 +0100284 def check_art_test_data(self, filename):
285 dirs = self.arch_dirs_for_path(ART_TEST_DIR)
286 if not dirs:
287 self.fail('ART test data missing: %s', filename)
288 for dir in dirs:
289 if not self.check_file('%s/%s' % (dir, filename)):
290 return
291
Martin Stjernholm2babede2019-03-18 21:04:49 +0000292 def check_single_library(self, filename):
293 lib_path = 'lib/%s' % filename
294 lib64_path = 'lib64/%s' % filename
295 lib_is_file, _ = self.is_file(lib_path)
296 if lib_is_file:
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000297 self._expected_file_globs.add(lib_path)
Martin Stjernholm2babede2019-03-18 21:04:49 +0000298 lib64_is_file, _ = self.is_file(lib64_path)
299 if lib64_is_file:
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000300 self._expected_file_globs.add(lib64_path)
Martin Stjernholm2babede2019-03-18 21:04:49 +0000301 if not lib_is_file and not lib64_is_file:
302 self.fail('Library missing: %s', filename)
Andreas Gampea0242cf2019-01-29 13:01:23 -0800303
Ulyana Trafimovich7a20cbd2019-11-08 11:27:31 +0000304 def check_dexpreopt(self, basename):
305 dirs = self.arch_dirs_for_path('javalib')
Ulyana Trafimovich7a20cbd2019-11-08 11:27:31 +0000306 for dir in dirs:
Tim Joinesbe50bc32020-03-18 18:00:41 +0000307 for ext in ['art', 'oat', 'vdex']:
Ulyana Trafimovich7a20cbd2019-11-08 11:27:31 +0000308 self.check_file('%s/%s.%s' % (dir, basename, ext))
309
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000310 def check_java_library(self, basename):
311 return self.check_file('javalib/%s.jar' % basename)
Andreas Gampe09123952019-01-30 13:17:02 -0800312
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000313 def ignore_path(self, path_glob):
314 self._expected_file_globs.add(path_glob)
Martin Stjernholm2babede2019-03-18 21:04:49 +0000315
Roland Levillain61f07162019-06-26 12:44:04 +0100316 def check_optional_art_test_executable(self, filename):
Victor Hsieh52f7f632021-09-24 11:50:55 -0700317 for arch in self.possible_archs():
Orion Hodsonaf3ed622019-10-03 16:30:54 +0100318 self.ignore_path('%s/%s/%s' % (ART_TEST_DIR, arch, filename))
Roland Levillain61f07162019-06-26 12:44:04 +0100319
Martin Stjernholm2babede2019-03-18 21:04:49 +0000320 def check_no_superfluous_files(self, dir_path):
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000321 paths = []
Martin Stjernholm2babede2019-03-18 21:04:49 +0000322 for name in sorted(self._provider.read_dir(dir_path).keys()):
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000323 if name not in ('.', '..'):
324 paths.append(os.path.join(dir_path, name))
325 expected_paths = set()
326 dir_prefix = dir_path + '/'
327 for path_glob in self._expected_file_globs:
328 expected_paths |= set(fnmatch.filter(paths, path_glob))
329 # If there are globs in subdirectories of dir_path we want to match their
330 # path segments at this directory level.
331 if path_glob.startswith(dir_prefix):
332 subpath = path_glob[len(dir_prefix):]
333 subpath_first_segment, _, _ = subpath.partition('/')
334 expected_paths |= set(fnmatch.filter(paths, dir_prefix + subpath_first_segment))
335 for unexpected_path in set(paths) - expected_paths:
336 self.fail('Unexpected file \'%s\'', unexpected_path)
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000337
Andreas Gampeeb555b82019-01-30 14:47:49 -0800338 # Just here for docs purposes, even if it isn't good Python style.
339
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000340 def check_symlinked_multilib_executable(self, filename):
341 """Check bin/filename32, and/or bin/filename64, with symlink bin/filename."""
Andreas Gampeeb555b82019-01-30 14:47:49 -0800342 raise NotImplementedError
343
Nicolas Geoffrayd68580e2020-04-15 16:52:32 +0100344 def check_symlinked_first_executable(self, filename):
345 """Check bin/filename32, and/or bin/filename64, with symlink bin/filename."""
346 raise NotImplementedError
347
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000348 def check_native_library(self, basename):
349 """Check lib/basename.so, and/or lib64/basename.so."""
Martin Stjernholm2babede2019-03-18 21:04:49 +0000350 raise NotImplementedError
351
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000352 def check_optional_native_library(self, basename_glob):
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000353 """Allow lib/basename.so and/or lib64/basename.so to exist."""
Martin Stjernholmb81fe232019-03-25 17:38:04 +0000354 raise NotImplementedError
355
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000356 def check_prefer64_library(self, basename):
357 """Check lib64/basename.so, or lib/basename.so on 32 bit only."""
Andreas Gampeeb555b82019-01-30 14:47:49 -0800358 raise NotImplementedError
359
Victor Hsieh52f7f632021-09-24 11:50:55 -0700360 def possible_archs(self, multilib=None):
361 """Returns names of possible archs."""
362 raise NotImplementedError
Andreas Gampeeb555b82019-01-30 14:47:49 -0800363
364class Arch32Checker(Checker):
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000365 def check_symlinked_multilib_executable(self, filename):
366 self.check_executable('%s32' % filename)
367 self.check_executable_symlink(filename)
Andreas Gampeeb555b82019-01-30 14:47:49 -0800368
Nicolas Geoffrayd68580e2020-04-15 16:52:32 +0100369 def check_symlinked_first_executable(self, filename):
370 self.check_executable('%s32' % filename)
371 self.check_executable_symlink(filename)
372
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000373 def check_native_library(self, basename):
Andreas Gampeeb555b82019-01-30 14:47:49 -0800374 # TODO: Use $TARGET_ARCH (e.g. check whether it is "arm" or "arm64") to improve
375 # the precision of this test?
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000376 self.check_file('lib/%s.so' % basename)
Andreas Gampeeb555b82019-01-30 14:47:49 -0800377
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000378 def check_optional_native_library(self, basename_glob):
379 self.ignore_path('lib/%s.so' % basename_glob)
Martin Stjernholmb81fe232019-03-25 17:38:04 +0000380
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000381 def check_prefer64_library(self, basename):
382 self.check_native_library(basename)
Andreas Gampeeb555b82019-01-30 14:47:49 -0800383
Victor Hsieh52f7f632021-09-24 11:50:55 -0700384 def possible_archs(self, multilib=None):
385 return ARCHS_32
Andreas Gampeeb555b82019-01-30 14:47:49 -0800386
387class Arch64Checker(Checker):
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000388 def check_symlinked_multilib_executable(self, filename):
389 self.check_executable('%s64' % filename)
390 self.check_executable_symlink(filename)
Andreas Gampeeb555b82019-01-30 14:47:49 -0800391
Nicolas Geoffrayd68580e2020-04-15 16:52:32 +0100392 def check_symlinked_first_executable(self, filename):
393 self.check_executable('%s64' % filename)
394 self.check_executable_symlink(filename)
395
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000396 def check_native_library(self, basename):
Andreas Gampeeb555b82019-01-30 14:47:49 -0800397 # TODO: Use $TARGET_ARCH (e.g. check whether it is "arm" or "arm64") to improve
398 # the precision of this test?
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000399 self.check_file('lib64/%s.so' % basename)
Andreas Gampeeb555b82019-01-30 14:47:49 -0800400
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000401 def check_optional_native_library(self, basename_glob):
402 self.ignore_path('lib64/%s.so' % basename_glob)
Martin Stjernholmb81fe232019-03-25 17:38:04 +0000403
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000404 def check_prefer64_library(self, basename):
405 self.check_native_library(basename)
Andreas Gampeeb555b82019-01-30 14:47:49 -0800406
Victor Hsieh52f7f632021-09-24 11:50:55 -0700407 def possible_archs(self, multilib=None):
408 return ARCHS_64
409
Andreas Gampeeb555b82019-01-30 14:47:49 -0800410
411class MultilibChecker(Checker):
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000412 def check_symlinked_multilib_executable(self, filename):
413 self.check_executable('%s32' % filename)
414 self.check_executable('%s64' % filename)
415 self.check_executable_symlink(filename)
Andreas Gampeeb555b82019-01-30 14:47:49 -0800416
Nicolas Geoffrayd68580e2020-04-15 16:52:32 +0100417 def check_symlinked_first_executable(self, filename):
418 self.check_executable('%s64' % filename)
419 self.check_executable_symlink(filename)
420
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000421 def check_native_library(self, basename):
Andreas Gampeeb555b82019-01-30 14:47:49 -0800422 # TODO: Use $TARGET_ARCH (e.g. check whether it is "arm" or "arm64") to improve
423 # the precision of this test?
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000424 self.check_file('lib/%s.so' % basename)
425 self.check_file('lib64/%s.so' % basename)
Andreas Gampeeb555b82019-01-30 14:47:49 -0800426
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000427 def check_optional_native_library(self, basename_glob):
428 self.ignore_path('lib/%s.so' % basename_glob)
429 self.ignore_path('lib64/%s.so' % basename_glob)
Martin Stjernholmb81fe232019-03-25 17:38:04 +0000430
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000431 def check_prefer64_library(self, basename):
432 self.check_file('lib64/%s.so' % basename)
Andreas Gampeeb555b82019-01-30 14:47:49 -0800433
Victor Hsieh52f7f632021-09-24 11:50:55 -0700434 def possible_archs(self, multilib=None):
435 if multilib is None or multilib == MULTILIB_BOTH:
436 return ARCHS_32 + ARCHS_64
437 if multilib == MULTILIB_FIRST or multilib == MULTILIB_64:
438 return ARCHS_64
439 elif multilib == MULTILIB_32:
440 return ARCHS_32
441 self.fail('Unrecognized multilib option "%s"', multilib)
442
Andreas Gampeeb555b82019-01-30 14:47:49 -0800443
Andreas Gampe9dc4b052019-01-30 13:47:25 -0800444class ReleaseChecker:
445 def __init__(self, checker):
446 self._checker = checker
Luca Stefani4e91ee92019-03-06 15:08:16 +0100447
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000448 def __str__(self):
449 return 'Release Checker'
450
451 def run(self):
Roland Levillaindf66de02019-11-11 23:22:15 +0000452 # Check the Protocol Buffers APEX manifest.
453 self._checker.check_file('apex_manifest.pb')
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000454
Martin Stjernholm77f17662019-04-03 17:08:21 +0100455 # Check binaries for ART.
Martin Stjernholm77f17662019-04-03 17:08:21 +0100456 self._checker.check_executable('dexdump')
457 self._checker.check_executable('dexlist')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000458 self._checker.check_executable('dexoptanalyzer')
459 self._checker.check_executable('profman')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000460 self._checker.check_symlinked_multilib_executable('dalvikvm')
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000461
Martin Stjernholm023c2182019-03-28 15:52:32 +0000462 # Check exported libraries for ART.
Martin Stjernholmd3e9ff32021-03-16 00:44:25 +0000463 self._checker.check_native_library('libdexfile')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000464 self._checker.check_native_library('libnativebridge')
465 self._checker.check_native_library('libnativehelper')
466 self._checker.check_native_library('libnativeloader')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000467
468 # Check internal libraries for ART.
469 self._checker.check_native_library('libadbconnection')
470 self._checker.check_native_library('libart')
471 self._checker.check_native_library('libart-compiler')
472 self._checker.check_native_library('libart-dexlayout')
Roland Levillain5b768892020-02-19 15:49:02 +0000473 self._checker.check_native_library('libart-disassembler')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000474 self._checker.check_native_library('libartbase')
475 self._checker.check_native_library('libartpalette')
Chris Wailesbefdad42021-01-12 16:37:57 -0800476 self._checker.check_native_library('libartservice')
477 self._checker.check_native_library('libarttools')
Roland Levillain3934fe82020-08-20 20:16:42 +0100478 self._checker.check_native_library('libdt_fd_forward')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000479 self._checker.check_native_library('libopenjdkjvm')
480 self._checker.check_native_library('libopenjdkjvmti')
481 self._checker.check_native_library('libprofile')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000482 self._checker.check_native_library('libsigchain')
483
Roland Levillain2af026d2021-06-14 12:25:04 +0100484 # Check Java libraries for Managed Core Library.
Martin Stjernholm023c2182019-03-28 15:52:32 +0000485 self._checker.check_java_library('apache-xml')
486 self._checker.check_java_library('bouncycastle')
487 self._checker.check_java_library('core-libart')
488 self._checker.check_java_library('core-oj')
489 self._checker.check_java_library('okhttp')
Ulya Trafimovich7b0df592020-01-03 13:29:00 +0000490 if isEnvTrue('EMMA_INSTRUMENT_FRAMEWORK'):
491 # In coverage builds jacoco is added to the list of ART apex jars.
492 self._checker.check_java_library('jacocoagent')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000493
494 # Check internal native libraries for Managed Core Library.
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000495 self._checker.check_native_library('libjavacore')
496 self._checker.check_native_library('libopenjdk')
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000497
Martin Stjernholm2babede2019-03-18 21:04:49 +0000498 # Check internal native library dependencies.
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000499 #
Martin Stjernholm2babede2019-03-18 21:04:49 +0000500 # Any internal dependency not listed here will cause a failure in
501 # NoSuperfluousLibrariesChecker. Internal dependencies are generally just
502 # implementation details, but in the release package we want to track them
503 # because a) they add to the package size and the RAM usage (in particular
504 # if the library is also present in /system or another APEX and hence might
505 # get loaded twice through linker namespace separation), and b) we need to
506 # catch invalid dependencies on /system or other APEXes that should go
507 # through an exported library with stubs (b/128708192 tracks implementing a
508 # better approach for that).
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000509 self._checker.check_native_library('libbacktrace')
510 self._checker.check_native_library('libbase')
511 self._checker.check_native_library('libc++')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000512 self._checker.check_native_library('libdt_socket')
513 self._checker.check_native_library('libjdwp')
Martin Stjernholm2eb1f832020-09-17 00:25:52 +0100514 self._checker.check_native_library('liblz4')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000515 self._checker.check_native_library('liblzma')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000516 self._checker.check_native_library('libnpt')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000517 self._checker.check_native_library('libunwindstack')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000518 self._checker.check_native_library('libziparchive')
Martin Stjernholm2babede2019-03-18 21:04:49 +0000519
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000520 # Allow extra dependencies that appear in ASAN builds.
521 self._checker.check_optional_native_library('libclang_rt.asan*')
522 self._checker.check_optional_native_library('libclang_rt.hwasan*')
523 self._checker.check_optional_native_library('libclang_rt.ubsan*')
524
Ulya Trafimovich7b0df592020-01-03 13:29:00 +0000525 # Check dexpreopt files for libcore bootclasspath jars.
526 self._checker.check_dexpreopt('boot')
527 self._checker.check_dexpreopt('boot-apache-xml')
528 self._checker.check_dexpreopt('boot-bouncycastle')
Ulya Trafimovich7b0df592020-01-03 13:29:00 +0000529 self._checker.check_dexpreopt('boot-core-libart')
530 self._checker.check_dexpreopt('boot-okhttp')
531 if isEnvTrue('EMMA_INSTRUMENT_FRAMEWORK'):
532 # In coverage builds the ART boot image includes jacoco.
533 self._checker.check_dexpreopt('boot-jacocoagent')
Luca Stefani4e91ee92019-03-06 15:08:16 +0100534
Andreas Gampe9dc4b052019-01-30 13:47:25 -0800535class ReleaseTargetChecker:
536 def __init__(self, checker):
537 self._checker = checker
Luca Stefani4e91ee92019-03-06 15:08:16 +0100538
Andreas Gampe09123952019-01-30 13:17:02 -0800539 def __str__(self):
540 return 'Release (Target) Checker'
541
542 def run(self):
Roland Levillaindf66de02019-11-11 23:22:15 +0000543 # We don't check for the presence of the JSON APEX manifest (file
544 # `apex_manifest.json`, only present in target APEXes), as it is only
545 # included for compatibility reasons with Android Q and will likely be
546 # removed in Android R.
547
Martin Stjernholm023c2182019-03-28 15:52:32 +0000548 # Check binaries for ART.
Roland Levillain2af026d2021-06-14 12:25:04 +0100549 self._checker.check_executable('artd')
Orion Hodson4c3ade62021-02-10 14:07:10 +0000550 self._checker.check_executable('oatdump')
551 self._checker.check_executable("odrefresh")
Martin Stjernholm6c61af82021-12-14 01:10:06 +0000552 self._checker.check_symlinked_multilib_executable('dex2oat')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000553
554 # Check internal libraries for ART.
Florian Mayer07710c52019-09-16 15:53:38 +0000555 self._checker.check_native_library('libperfetto_hprof')
Martin Stjernholm05949c62021-10-28 02:31:53 +0100556 self._checker.check_prefer64_library('artd-aidl-ndk')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000557
Roland Levillain2af026d2021-06-14 12:25:04 +0100558 # Check internal Java libraries
559 self._checker.check_java_library("service-art")
560
Martin Stjernholm023c2182019-03-28 15:52:32 +0000561 # Check exported native libraries for Managed Core Library.
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000562 self._checker.check_native_library('libandroidio')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000563
564 # Check internal native library dependencies.
565 self._checker.check_native_library('libcrypto')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000566 self._checker.check_native_library('libexpat')
Martin Stjernholm2babede2019-03-18 21:04:49 +0000567
Luca Stefani4e91ee92019-03-06 15:08:16 +0100568
Andreas Gampe9dc4b052019-01-30 13:47:25 -0800569class ReleaseHostChecker:
570 def __init__(self, checker):
Luca Stefani4e91ee92019-03-06 15:08:16 +0100571 self._checker = checker
572
Andreas Gampe09123952019-01-30 13:17:02 -0800573 def __str__(self):
574 return 'Release (Host) Checker'
575
576 def run(self):
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000577 # Check binaries for ART.
578 self._checker.check_executable('hprof-conv')
Nicolas Geoffrayd68580e2020-04-15 16:52:32 +0100579 self._checker.check_symlinked_first_executable('dex2oatd')
580 self._checker.check_symlinked_first_executable('dex2oat')
Martin Stjernholm84a32cd2019-03-29 16:39:46 +0000581
Martin Stjernholm023c2182019-03-28 15:52:32 +0000582 # Check exported native libraries for Managed Core Library.
Victor Chang8b247622020-09-22 21:48:15 +0100583 self._checker.check_native_library('libicu')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000584 self._checker.check_native_library('libandroidio')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000585
586 # Check internal libraries for Managed Core Library.
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000587 self._checker.check_native_library('libexpat-host')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000588 self._checker.check_native_library('libz-host')
Andreas Gampe09123952019-01-30 13:17:02 -0800589
Luca Stefani4e91ee92019-03-06 15:08:16 +0100590
Andreas Gampe9dc4b052019-01-30 13:47:25 -0800591class DebugChecker:
592 def __init__(self, checker):
593 self._checker = checker
Luca Stefani4e91ee92019-03-06 15:08:16 +0100594
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000595 def __str__(self):
596 return 'Debug Checker'
597
598 def run(self):
Martin Stjernholm023c2182019-03-28 15:52:32 +0000599 # Check binaries for ART.
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000600 self._checker.check_executable('dexdiag')
Roland Levillain6dd62122019-06-18 19:10:21 +0100601 self._checker.check_executable('dexanalyze')
602 self._checker.check_executable('dexlayout')
603 self._checker.check_symlinked_multilib_executable('imgdiag')
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000604
Martin Stjernholm023c2182019-03-28 15:52:32 +0000605 # Check debug binaries for ART.
Roland Levillain6dd62122019-06-18 19:10:21 +0100606 self._checker.check_executable('dexlayoutd')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000607 self._checker.check_executable('dexoptanalyzerd')
Roland Levillain6dd62122019-06-18 19:10:21 +0100608 self._checker.check_symlinked_multilib_executable('imgdiagd')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000609 self._checker.check_executable('profmand')
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000610
Martin Stjernholmd3e9ff32021-03-16 00:44:25 +0000611 # Check exported libraries for ART.
612 self._checker.check_native_library('libdexfiled')
613
Martin Stjernholm023c2182019-03-28 15:52:32 +0000614 # Check internal libraries for ART.
615 self._checker.check_native_library('libadbconnectiond')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000616 self._checker.check_native_library('libartbased')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000617 self._checker.check_native_library('libartd')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000618 self._checker.check_native_library('libartd-compiler')
619 self._checker.check_native_library('libartd-dexlayout')
Roland Levillain4d6f24d2019-10-02 16:47:36 +0100620 self._checker.check_native_library('libartd-disassembler')
Jiakai Zhangba974862022-05-25 20:39:12 +0100621 self._checker.check_native_library('libartserviced')
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000622 self._checker.check_native_library('libopenjdkjvmd')
623 self._checker.check_native_library('libopenjdkjvmtid')
624 self._checker.check_native_library('libprofiled')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000625
626 # Check internal libraries for Managed Core Library.
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000627 self._checker.check_native_library('libopenjdkd')
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000628
Luca Stefani4e91ee92019-03-06 15:08:16 +0100629
Andreas Gampe9dc4b052019-01-30 13:47:25 -0800630class DebugTargetChecker:
631 def __init__(self, checker):
632 self._checker = checker
Luca Stefani4e91ee92019-03-06 15:08:16 +0100633
Andreas Gampea0242cf2019-01-29 13:01:23 -0800634 def __str__(self):
635 return 'Debug (Target) Checker'
636
637 def run(self):
Martin Stjernholm023c2182019-03-28 15:52:32 +0000638 # Check ART debug binaries.
Martin Stjernholmc17ace22019-03-18 21:47:31 +0000639 self._checker.check_executable('oatdumpd')
Martin Stjernholm6c61af82021-12-14 01:10:06 +0000640 self._checker.check_symlinked_multilib_executable('dex2oatd')
Martin Stjernholm023c2182019-03-28 15:52:32 +0000641
642 # Check ART internal libraries.
Florian Mayer07710c52019-09-16 15:53:38 +0000643 self._checker.check_native_library('libperfetto_hprofd')
Andreas Gampea0242cf2019-01-29 13:01:23 -0800644
Martin Stjernholm2babede2019-03-18 21:04:49 +0000645 # Check internal native library dependencies.
646 #
647 # Like in the release package, we check that we don't get other dependencies
648 # besides those listed here. In this case the concern is not bloat, but
649 # rather that we don't get behavioural differences between user (release)
650 # and userdebug/eng builds, which could happen if the debug package has
651 # duplicate library instances where releases don't. In other words, it's
652 # uncontroversial to add debug-only dependencies, as long as they don't make
653 # assumptions on having a single global state (ideally they should have
654 # double_loadable:true, cf. go/double_loadable). Also, like in the release
655 # package we need to look out for dependencies that should go through
656 # exported library stubs (until b/128708192 is fixed).
Martin Stjernholm77f17662019-04-03 17:08:21 +0100657 self._checker.check_prefer64_library('libmeminfo')
658 self._checker.check_prefer64_library('libprocinfo')
Martin Stjernholm2babede2019-03-18 21:04:49 +0000659
660
Roland Levillain61f07162019-06-26 12:44:04 +0100661class TestingTargetChecker:
662 def __init__(self, checker):
663 self._checker = checker
664
665 def __str__(self):
666 return 'Testing (Target) Checker'
667
668 def run(self):
David Srbecky883c1342020-05-11 23:30:29 +0000669 # Check ART test binaries.
670 self._checker.check_art_test_executable('art_cmdline_tests')
671 self._checker.check_art_test_executable('art_compiler_tests')
672 self._checker.check_art_test_executable('art_dex2oat_tests')
673 self._checker.check_art_test_executable('art_dexanalyze_tests')
674 self._checker.check_art_test_executable('art_dexdiag_tests')
675 self._checker.check_art_test_executable('art_dexdump_tests')
676 self._checker.check_art_test_executable('art_dexlayout_tests')
677 self._checker.check_art_test_executable('art_dexlist_tests')
678 self._checker.check_art_test_executable('art_dexoptanalyzer_tests')
679 self._checker.check_art_test_executable('art_imgdiag_tests')
680 self._checker.check_art_test_executable('art_libartbase_tests')
681 self._checker.check_art_test_executable('art_libartpalette_tests')
Chris Wailesbfd622a2021-01-13 16:13:41 -0800682 self._checker.check_art_test_executable('art_libartservice_tests')
683 self._checker.check_art_test_executable('art_libarttools_tests')
Roland Levillain61f07162019-06-26 12:44:04 +0100684 self._checker.check_art_test_executable('art_libdexfile_support_tests')
David Srbecky883c1342020-05-11 23:30:29 +0000685 self._checker.check_art_test_executable('art_libdexfile_tests')
686 self._checker.check_art_test_executable('art_libprofile_tests')
687 self._checker.check_art_test_executable('art_oatdump_tests')
Victor Hsieh7b798142022-01-18 15:13:14 -0800688 self._checker.check_art_test_executable('art_odrefresh_tests')
David Srbecky883c1342020-05-11 23:30:29 +0000689 self._checker.check_art_test_executable('art_profman_tests')
690 self._checker.check_art_test_executable('art_runtime_compiler_tests')
691 self._checker.check_art_test_executable('art_runtime_tests')
692 self._checker.check_art_test_executable('art_sigchain_tests')
Roland Levillain61f07162019-06-26 12:44:04 +0100693
694 # Check ART test (internal) libraries.
Roland Levillain55ffe7f2021-06-14 15:18:54 +0100695 self._checker.check_native_library('libartd-gtest')
Ulya Trafimovich5439f052020-07-29 10:03:46 +0100696 self._checker.check_native_library('libartd-simulator-container')
Jiakai Zhangd539f862022-02-08 14:56:05 +0000697 self._checker.check_native_library('libartbased-testing')
Roland Levillain61f07162019-06-26 12:44:04 +0100698
Andreas Gampe816a5522019-09-11 11:29:49 -0700699 # Check ART test tools.
700 self._checker.check_executable('signal_dumper')
701
David Srbecky4a88a5a2020-05-05 16:21:57 +0100702 # Check ART jar files which are needed for gtests.
703 self._checker.check_art_test_data('art-gtest-jars-AbstractMethod.jar')
704 self._checker.check_art_test_data('art-gtest-jars-MyClassNatives.jar')
705 self._checker.check_art_test_data('art-gtest-jars-Main.jar')
706 self._checker.check_art_test_data('art-gtest-jars-ProtoCompare.jar')
707 self._checker.check_art_test_data('art-gtest-jars-Transaction.jar')
David Srbeckyedda3ca2020-07-08 00:41:08 +0100708 self._checker.check_art_test_data('art-gtest-jars-VerifierDepsMulti.dex')
David Srbecky4a88a5a2020-05-05 16:21:57 +0100709 self._checker.check_art_test_data('art-gtest-jars-Nested.jar')
710 self._checker.check_art_test_data('art-gtest-jars-MyClass.jar')
711 self._checker.check_art_test_data('art-gtest-jars-ManyMethods.jar')
712 self._checker.check_art_test_data('art-gtest-jars-GetMethodSignature.jar')
713 self._checker.check_art_test_data('art-gtest-jars-Lookup.jar')
714 self._checker.check_art_test_data('art-gtest-jars-Instrumentation.jar')
715 self._checker.check_art_test_data('art-gtest-jars-MainUncompressedAligned.jar')
716 self._checker.check_art_test_data('art-gtest-jars-ForClassLoaderD.jar')
717 self._checker.check_art_test_data('art-gtest-jars-ForClassLoaderC.jar')
718 self._checker.check_art_test_data('art-gtest-jars-ErroneousA.jar')
David Srbecky4a88a5a2020-05-05 16:21:57 +0100719 self._checker.check_art_test_data('art-gtest-jars-HiddenApiSignatures.jar')
720 self._checker.check_art_test_data('art-gtest-jars-ForClassLoaderB.jar')
David Srbeckyedda3ca2020-07-08 00:41:08 +0100721 self._checker.check_art_test_data('art-gtest-jars-LinkageTest.dex')
David Srbecky4a88a5a2020-05-05 16:21:57 +0100722 self._checker.check_art_test_data('art-gtest-jars-MethodTypes.jar')
723 self._checker.check_art_test_data('art-gtest-jars-ErroneousInit.jar')
David Srbeckyedda3ca2020-07-08 00:41:08 +0100724 self._checker.check_art_test_data('art-gtest-jars-VerifierDeps.dex')
David Srbecky4a88a5a2020-05-05 16:21:57 +0100725 self._checker.check_art_test_data('art-gtest-jars-StringLiterals.jar')
726 self._checker.check_art_test_data('art-gtest-jars-XandY.jar')
727 self._checker.check_art_test_data('art-gtest-jars-ExceptionHandle.jar')
728 self._checker.check_art_test_data('art-gtest-jars-ImageLayoutB.jar')
729 self._checker.check_art_test_data('art-gtest-jars-Interfaces.jar')
730 self._checker.check_art_test_data('art-gtest-jars-IMTB.jar')
731 self._checker.check_art_test_data('art-gtest-jars-Extension2.jar')
732 self._checker.check_art_test_data('art-gtest-jars-Extension1.jar')
733 self._checker.check_art_test_data('art-gtest-jars-MainEmptyUncompressedAligned.jar')
734 self._checker.check_art_test_data('art-gtest-jars-ErroneousB.jar')
735 self._checker.check_art_test_data('art-gtest-jars-MultiDexModifiedSecondary.jar')
736 self._checker.check_art_test_data('art-gtest-jars-NonStaticLeafMethods.jar')
737 self._checker.check_art_test_data('art-gtest-jars-DefaultMethods.jar')
738 self._checker.check_art_test_data('art-gtest-jars-MultiDexUncompressedAligned.jar')
739 self._checker.check_art_test_data('art-gtest-jars-StaticsFromCode.jar')
740 self._checker.check_art_test_data('art-gtest-jars-ProfileTestMultiDex.jar')
David Srbeckyedda3ca2020-07-08 00:41:08 +0100741 self._checker.check_art_test_data('art-gtest-jars-VerifySoftFailDuringClinit.dex')
David Srbecky4a88a5a2020-05-05 16:21:57 +0100742 self._checker.check_art_test_data('art-gtest-jars-MainStripped.jar')
743 self._checker.check_art_test_data('art-gtest-jars-ForClassLoaderA.jar')
744 self._checker.check_art_test_data('art-gtest-jars-StaticLeafMethods.jar')
745 self._checker.check_art_test_data('art-gtest-jars-MultiDex.jar')
746 self._checker.check_art_test_data('art-gtest-jars-Packages.jar')
747 self._checker.check_art_test_data('art-gtest-jars-ProtoCompare2.jar')
748 self._checker.check_art_test_data('art-gtest-jars-Statics.jar')
749 self._checker.check_art_test_data('art-gtest-jars-AllFields.jar')
750 self._checker.check_art_test_data('art-gtest-jars-IMTA.jar')
751 self._checker.check_art_test_data('art-gtest-jars-ImageLayoutA.jar')
752 self._checker.check_art_test_data('art-gtest-jars-MainEmptyUncompressed.jar')
Calin Juravle33787682019-07-26 14:27:18 -0700753 self._checker.check_art_test_data('art-gtest-jars-Dex2oatVdexTestDex.jar')
754 self._checker.check_art_test_data('art-gtest-jars-Dex2oatVdexPublicSdkDex.dex')
David Srbecky4a88a5a2020-05-05 16:21:57 +0100755
Roland Levillain61f07162019-06-26 12:44:04 +0100756
Martin Stjernholm2babede2019-03-18 21:04:49 +0000757class NoSuperfluousBinariesChecker:
758 def __init__(self, checker):
759 self._checker = checker
760
761 def __str__(self):
762 return 'No superfluous binaries checker'
763
764 def run(self):
765 self._checker.check_no_superfluous_files('bin')
766
767
768class NoSuperfluousLibrariesChecker:
769 def __init__(self, checker):
770 self._checker = checker
771
772 def __str__(self):
773 return 'No superfluous libraries checker'
774
775 def run(self):
776 self._checker.check_no_superfluous_files('javalib')
777 self._checker.check_no_superfluous_files('lib')
Martin Stjernholm2babede2019-03-18 21:04:49 +0000778 self._checker.check_no_superfluous_files('lib64')
Martin Stjernholm2babede2019-03-18 21:04:49 +0000779
Andreas Gampeb1d55672019-01-29 22:17:02 +0000780
Roland Levillain61f07162019-06-26 12:44:04 +0100781class NoSuperfluousArtTestsChecker:
782 def __init__(self, checker):
783 self._checker = checker
784
785 def __str__(self):
786 return 'No superfluous ART tests checker'
787
788 def run(self):
Victor Hsieh52f7f632021-09-24 11:50:55 -0700789 for arch in self._checker.possible_archs():
Orion Hodsonaf3ed622019-10-03 16:30:54 +0100790 self._checker.check_no_superfluous_files('%s/%s' % (ART_TEST_DIR, arch))
Roland Levillain61f07162019-06-26 12:44:04 +0100791
792
Luca Stefani4e91ee92019-03-06 15:08:16 +0100793class List:
Roland Levillain77251f92019-08-09 15:00:04 +0100794 def __init__(self, provider, print_size=False):
Luca Stefani4e91ee92019-03-06 15:08:16 +0100795 self._provider = provider
Roland Levillaine91d7872019-07-25 18:56:06 +0100796 self._print_size = print_size
Luca Stefani4e91ee92019-03-06 15:08:16 +0100797
798 def print_list(self):
Roland Levillain09744ac2019-06-06 18:23:02 +0100799
800 def print_list_rec(path):
801 apex_map = self._provider.read_dir(path)
802 if apex_map is None:
803 return
804 apex_map = dict(apex_map)
805 if '.' in apex_map:
806 del apex_map['.']
807 if '..' in apex_map:
808 del apex_map['..']
809 for (_, val) in sorted(apex_map.items()):
810 val_path = os.path.join(path, val.name)
Roland Levillaine91d7872019-07-25 18:56:06 +0100811 if self._print_size:
812 if val.size < 0:
813 print('[ n/a ] %s' % val_path)
814 else:
815 print('[%11d] %s' % (val.size, val_path))
816 else:
817 print(val_path)
Roland Levillain09744ac2019-06-06 18:23:02 +0100818 if val.is_dir:
819 print_list_rec(val_path)
820
821 print_list_rec('')
Luca Stefani4e91ee92019-03-06 15:08:16 +0100822
823
824class Tree:
Roland Levillain77251f92019-08-09 15:00:04 +0100825 def __init__(self, provider, title, print_size=False):
Luca Stefani4e91ee92019-03-06 15:08:16 +0100826 print('%s' % title)
827 self._provider = provider
Luca Stefani4e91ee92019-03-06 15:08:16 +0100828 self._has_next_list = []
Roland Levillain88e55692019-07-25 15:57:06 +0100829 self._print_size = print_size
Luca Stefani4e91ee92019-03-06 15:08:16 +0100830
831 @staticmethod
832 def get_vertical(has_next_list):
833 string = ''
834 for v in has_next_list:
835 string += '%s ' % ('│' if v else ' ')
836 return string
837
838 @staticmethod
839 def get_last_vertical(last):
840 return '└── ' if last else '├── '
841
842 def print_tree(self):
Roland Levillain09744ac2019-06-06 18:23:02 +0100843
844 def print_tree_rec(path):
845 apex_map = self._provider.read_dir(path)
846 if apex_map is None:
847 return
848 apex_map = dict(apex_map)
849 if '.' in apex_map:
850 del apex_map['.']
851 if '..' in apex_map:
852 del apex_map['..']
853 key_list = list(sorted(apex_map.keys()))
854 for i, key in enumerate(key_list):
855 prev = self.get_vertical(self._has_next_list)
856 last = self.get_last_vertical(i == len(key_list) - 1)
857 val = apex_map[key]
Roland Levillain88e55692019-07-25 15:57:06 +0100858 if self._print_size:
859 if val.size < 0:
860 print('%s%s[ n/a ] %s' % (prev, last, val.name))
861 else:
862 print('%s%s[%11d] %s' % (prev, last, val.size, val.name))
863 else:
864 print('%s%s%s' % (prev, last, val.name))
Roland Levillain09744ac2019-06-06 18:23:02 +0100865 if val.is_dir:
866 self._has_next_list.append(i < len(key_list) - 1)
867 val_path = os.path.join(path, val.name)
868 print_tree_rec(val_path)
869 self._has_next_list.pop()
870
871 print_tree_rec('')
Luca Stefani4e91ee92019-03-06 15:08:16 +0100872
Andreas Gampeb1d55672019-01-29 22:17:02 +0000873
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000874# Note: do not sys.exit early, for __del__ cleanup.
Luca Stefani4e91ee92019-03-06 15:08:16 +0100875def art_apex_test_main(test_args):
Roland Levillaindd20d002019-07-19 16:09:47 +0100876 if test_args.host and test_args.flattened:
877 logging.error("Both of --host and --flattened set")
878 return 1
Luca Stefani4e91ee92019-03-06 15:08:16 +0100879 if test_args.list and test_args.tree:
Andreas Gampeb1d55672019-01-29 22:17:02 +0000880 logging.error("Both of --list and --tree set")
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000881 return 1
Roland Levillaine91d7872019-07-25 18:56:06 +0100882 if test_args.size and not (test_args.list or test_args.tree):
883 logging.error("--size set but neither --list nor --tree set")
Roland Levillain88e55692019-07-25 15:57:06 +0100884 return 1
Martin Stjernholm3cb59a42019-08-07 17:18:29 +0100885 if not test_args.flattened and not test_args.tmpdir:
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000886 logging.error("Need a tmpdir.")
887 return 1
Martin Stjernholm571a6be2021-05-25 01:16:53 +0100888 if not test_args.flattened and not test_args.host:
889 if not test_args.deapexer:
890 logging.error("Need deapexer.")
891 return 1
892 if not test_args.debugfs:
893 logging.error("Need debugfs.")
894 return 1
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000895
Roland Levillainfdbe2072019-11-11 15:52:45 +0000896 if test_args.host:
897 # Host APEX.
898 if test_args.flavor not in [FLAVOR_DEBUG, FLAVOR_AUTO]:
899 logging.error("Using option --host with non-Debug APEX")
Roland Levillaindbd6a142019-10-03 15:08:28 +0100900 return 1
Roland Levillainfdbe2072019-11-11 15:52:45 +0000901 # Host APEX is always a debug flavor (for now).
902 test_args.flavor = FLAVOR_DEBUG
903 else:
904 # Device APEX.
905 if test_args.flavor == FLAVOR_AUTO:
906 logging.warning('--flavor=auto, trying to autodetect. This may be incorrect!')
Roland Levillain0c39de62021-04-14 17:53:20 +0100907 # The order of flavors in the list below matters, as the release tag (empty string) will
908 # match any package name.
909 for flavor in [ FLAVOR_DEBUG, FLAVOR_TESTING, FLAVOR_RELEASE ]:
910 flavor_tag = flavor
911 # Special handling for the release flavor, whose name is no longer part of the Release ART
Roland Levillain2af026d2021-06-14 12:25:04 +0100912 # APEX file name (`com.android.art.capex` / `com.android.art`).
Roland Levillain0c39de62021-04-14 17:53:20 +0100913 if flavor == FLAVOR_RELEASE:
914 flavor_tag = ''
915 flavor_pattern = '*.%s*' % flavor_tag
Roland Levillainfdbe2072019-11-11 15:52:45 +0000916 if fnmatch.fnmatch(test_args.apex, flavor_pattern):
917 test_args.flavor = flavor
Roland Levillain0c39de62021-04-14 17:53:20 +0100918 logging.warning(' Detected %s flavor', flavor)
Roland Levillainfdbe2072019-11-11 15:52:45 +0000919 break
920 if test_args.flavor == FLAVOR_AUTO:
Roland Levillain0c39de62021-04-14 17:53:20 +0100921 logging.error(' Could not detect APEX flavor, neither %s, %s nor %s for \'%s\'',
Roland Levillainfdbe2072019-11-11 15:52:45 +0000922 FLAVOR_RELEASE, FLAVOR_DEBUG, FLAVOR_TESTING, test_args.apex)
923 return 1
Roland Levillaindbd6a142019-10-03 15:08:28 +0100924
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000925 try:
Luca Stefani4e91ee92019-03-06 15:08:16 +0100926 if test_args.host:
927 apex_provider = HostApexProvider(test_args.apex, test_args.tmpdir)
Andreas Gampe09123952019-01-30 13:17:02 -0800928 else:
Martin Stjernholm571a6be2021-05-25 01:16:53 +0100929 apex_dir = test_args.apex
930 if not test_args.flattened:
931 # Extract the apex. It would be nice to use the output from "deapexer list"
932 # to avoid this work, but it doesn't provide info about executable bits.
933 apex_dir = extract_apex(test_args.apex, test_args.deapexer, test_args.debugfs,
934 test_args.tmpdir)
935 apex_provider = TargetApexProvider(apex_dir)
Luca Stefani4e91ee92019-03-06 15:08:16 +0100936 except (zipfile.BadZipFile, zipfile.LargeZipFile) as e:
Andreas Gampea0242cf2019-01-29 13:01:23 -0800937 logging.error('Failed to create provider: %s', e)
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000938 return 1
939
Luca Stefani4e91ee92019-03-06 15:08:16 +0100940 if test_args.tree:
Roland Levillain88e55692019-07-25 15:57:06 +0100941 Tree(apex_provider, test_args.apex, test_args.size).print_tree()
Andreas Gampeb1d55672019-01-29 22:17:02 +0000942 return 0
Luca Stefani4e91ee92019-03-06 15:08:16 +0100943 if test_args.list:
Roland Levillaine91d7872019-07-25 18:56:06 +0100944 List(apex_provider, test_args.size).print_list()
Andreas Gampeb1d55672019-01-29 22:17:02 +0000945 return 0
946
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000947 checkers = []
Orion Hodsonaf3ed622019-10-03 16:30:54 +0100948 if test_args.bitness == BITNESS_AUTO:
Luca Stefani4e91ee92019-03-06 15:08:16 +0100949 logging.warning('--bitness=auto, trying to autodetect. This may be incorrect!')
Andreas Gampeeb555b82019-01-30 14:47:49 -0800950 has_32 = apex_provider.get('lib') is not None
951 has_64 = apex_provider.get('lib64') is not None
952 if has_32 and has_64:
Luca Stefani4e91ee92019-03-06 15:08:16 +0100953 logging.warning(' Detected multilib')
Orion Hodsonaf3ed622019-10-03 16:30:54 +0100954 test_args.bitness = BITNESS_MULTILIB
Andreas Gampeeb555b82019-01-30 14:47:49 -0800955 elif has_32:
Luca Stefani4e91ee92019-03-06 15:08:16 +0100956 logging.warning(' Detected 32-only')
Orion Hodsonaf3ed622019-10-03 16:30:54 +0100957 test_args.bitness = BITNESS_32
Andreas Gampeeb555b82019-01-30 14:47:49 -0800958 elif has_64:
Luca Stefani4e91ee92019-03-06 15:08:16 +0100959 logging.warning(' Detected 64-only')
Orion Hodsonaf3ed622019-10-03 16:30:54 +0100960 test_args.bitness = BITNESS_64
Andreas Gampeeb555b82019-01-30 14:47:49 -0800961 else:
962 logging.error(' Could not detect bitness, neither lib nor lib64 contained.')
Roland Levillain77251f92019-08-09 15:00:04 +0100963 List(apex_provider).print_list()
Andreas Gampeeb555b82019-01-30 14:47:49 -0800964 return 1
965
Orion Hodsonaf3ed622019-10-03 16:30:54 +0100966 if test_args.bitness == BITNESS_32:
Andreas Gampeeb555b82019-01-30 14:47:49 -0800967 base_checker = Arch32Checker(apex_provider)
Orion Hodsonaf3ed622019-10-03 16:30:54 +0100968 elif test_args.bitness == BITNESS_64:
Andreas Gampeeb555b82019-01-30 14:47:49 -0800969 base_checker = Arch64Checker(apex_provider)
970 else:
Orion Hodsonaf3ed622019-10-03 16:30:54 +0100971 assert test_args.bitness == BITNESS_MULTILIB
Andreas Gampeeb555b82019-01-30 14:47:49 -0800972 base_checker = MultilibChecker(apex_provider)
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000973
Andreas Gampe9dc4b052019-01-30 13:47:25 -0800974 checkers.append(ReleaseChecker(base_checker))
Luca Stefani4e91ee92019-03-06 15:08:16 +0100975 if test_args.host:
Andreas Gampe9dc4b052019-01-30 13:47:25 -0800976 checkers.append(ReleaseHostChecker(base_checker))
Andreas Gampe09123952019-01-30 13:17:02 -0800977 else:
Andreas Gampe9dc4b052019-01-30 13:47:25 -0800978 checkers.append(ReleaseTargetChecker(base_checker))
Orion Hodsonaf3ed622019-10-03 16:30:54 +0100979 if test_args.flavor == FLAVOR_DEBUG or test_args.flavor == FLAVOR_TESTING:
Andreas Gampe9dc4b052019-01-30 13:47:25 -0800980 checkers.append(DebugChecker(base_checker))
Roland Levillain61f07162019-06-26 12:44:04 +0100981 if not test_args.host:
982 checkers.append(DebugTargetChecker(base_checker))
Orion Hodsonaf3ed622019-10-03 16:30:54 +0100983 if test_args.flavor == FLAVOR_TESTING:
Roland Levillain61f07162019-06-26 12:44:04 +0100984 checkers.append(TestingTargetChecker(base_checker))
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000985
Martin Stjernholm2babede2019-03-18 21:04:49 +0000986 # These checkers must be last.
987 checkers.append(NoSuperfluousBinariesChecker(base_checker))
Roland Levillain61f07162019-06-26 12:44:04 +0100988 checkers.append(NoSuperfluousArtTestsChecker(base_checker))
Martin Stjernholm2babede2019-03-18 21:04:49 +0000989 if not test_args.host:
990 # We only care about superfluous libraries on target, where their absence
991 # can be vital to ensure they get picked up from the right package.
992 checkers.append(NoSuperfluousLibrariesChecker(base_checker))
993
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000994 failed = False
995 for checker in checkers:
996 logging.info('%s...', checker)
997 checker.run()
Andreas Gampe9dc4b052019-01-30 13:47:25 -0800998 if base_checker.error_count() > 0:
Andreas Gampe2c846cd2019-01-29 22:06:46 +0000999 logging.error('%s FAILED', checker)
1000 failed = True
1001 else:
1002 logging.info('%s SUCCEEDED', checker)
Andreas Gampe9dc4b052019-01-30 13:47:25 -08001003 base_checker.reset_errors()
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001004
1005 return 1 if failed else 0
1006
Luca Stefani4e91ee92019-03-06 15:08:16 +01001007
1008def art_apex_test_default(test_parser):
1009 if 'ANDROID_PRODUCT_OUT' not in os.environ:
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001010 logging.error('No-argument use requires ANDROID_PRODUCT_OUT')
1011 sys.exit(1)
1012 product_out = os.environ['ANDROID_PRODUCT_OUT']
Luca Stefani4e91ee92019-03-06 15:08:16 +01001013 if 'ANDROID_HOST_OUT' not in os.environ:
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001014 logging.error('No-argument use requires ANDROID_HOST_OUT')
1015 sys.exit(1)
1016 host_out = os.environ['ANDROID_HOST_OUT']
1017
Roland Levillain4ee567f2020-07-27 17:02:54 +01001018 test_args = test_parser.parse_args(['unused']) # For consistency.
Luca Stefani4e91ee92019-03-06 15:08:16 +01001019 test_args.debugfs = '%s/bin/debugfs' % host_out
1020 test_args.tmpdir = '.'
1021 test_args.tree = False
1022 test_args.list = False
Orion Hodsonaf3ed622019-10-03 16:30:54 +01001023 test_args.bitness = BITNESS_AUTO
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001024 failed = False
1025
Luca Stefani4e91ee92019-03-06 15:08:16 +01001026 if not os.path.exists(test_args.debugfs):
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001027 logging.error("Cannot find debugfs (default path %s). Please build it, e.g., m debugfs",
Luca Stefani4e91ee92019-03-06 15:08:16 +01001028 test_args.debugfs)
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001029 sys.exit(1)
1030
Roland Levillaind7ea0432019-09-09 16:29:12 +01001031 # TODO: Add host support.
1032 # TODO: Add support for flattened APEX packages.
Luca Stefani4e91ee92019-03-06 15:08:16 +01001033 configs = [
Roland Levillain2af026d2021-06-14 12:25:04 +01001034 {'name': 'com.android.art.capex', 'flavor': FLAVOR_RELEASE, 'host': False},
1035 {'name': 'com.android.art.debug.capex', 'flavor': FLAVOR_DEBUG, 'host': False},
1036 # Note: The Testing ART APEX is not a Compressed APEX.
1037 {'name': 'com.android.art.testing.apex', 'flavor': FLAVOR_TESTING, 'host': False},
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001038 ]
1039
1040 for config in configs:
1041 logging.info(config['name'])
1042 # TODO: Host will need different path.
Roland Levillain2af026d2021-06-14 12:25:04 +01001043 test_args.apex = '%s/system/apex/%s' % (product_out, config['name'])
Luca Stefani4e91ee92019-03-06 15:08:16 +01001044 if not os.path.exists(test_args.apex):
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001045 failed = True
Luca Stefani4e91ee92019-03-06 15:08:16 +01001046 logging.error("Cannot find APEX %s. Please build it first.", test_args.apex)
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001047 continue
Roland Levillaind7ea0432019-09-09 16:29:12 +01001048 test_args.flavor = config['flavor']
Luca Stefani4e91ee92019-03-06 15:08:16 +01001049 test_args.host = config['host']
1050 failed = art_apex_test_main(test_args) != 0
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001051
1052 if failed:
1053 sys.exit(1)
1054
Luca Stefani4e91ee92019-03-06 15:08:16 +01001055
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001056if __name__ == "__main__":
Martin Stjernholme58624f2019-09-20 15:53:40 +01001057 parser = argparse.ArgumentParser(description='Check integrity of an ART APEX.')
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001058
Roland Levillaind7ea0432019-09-09 16:29:12 +01001059 parser.add_argument('apex', help='APEX file input')
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001060
Roland Levillaind7ea0432019-09-09 16:29:12 +01001061 parser.add_argument('--host', help='Check as host APEX', action='store_true')
Andreas Gampe09123952019-01-30 13:17:02 -08001062
Roland Levillaind7ea0432019-09-09 16:29:12 +01001063 parser.add_argument('--flattened', help='Check as flattened (target) APEX', action='store_true')
Roland Levillaindd20d002019-07-19 16:09:47 +01001064
Orion Hodsonaf3ed622019-10-03 16:30:54 +01001065 parser.add_argument('--flavor', help='Check as FLAVOR APEX', choices=FLAVORS_ALL,
1066 default=FLAVOR_AUTO)
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001067
Andreas Gampeb1d55672019-01-29 22:17:02 +00001068 parser.add_argument('--list', help='List all files', action='store_true')
1069 parser.add_argument('--tree', help='Print directory tree', action='store_true')
Roland Levillaine91d7872019-07-25 18:56:06 +01001070 parser.add_argument('--size', help='Print file sizes', action='store_true')
Andreas Gampeb1d55672019-01-29 22:17:02 +00001071
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001072 parser.add_argument('--tmpdir', help='Directory for temp files')
Martin Stjernholm571a6be2021-05-25 01:16:53 +01001073 parser.add_argument('--deapexer', help='Path to deapexer')
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001074 parser.add_argument('--debugfs', help='Path to debugfs')
1075
Orion Hodsonaf3ed622019-10-03 16:30:54 +01001076 parser.add_argument('--bitness', help='Bitness to check', choices=BITNESS_ALL,
1077 default=BITNESS_AUTO)
Andreas Gampeeb555b82019-01-30 14:47:49 -08001078
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001079 if len(sys.argv) == 1:
Luca Stefani4e91ee92019-03-06 15:08:16 +01001080 art_apex_test_default(parser)
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001081 else:
1082 args = parser.parse_args()
1083
1084 if args is None:
1085 sys.exit(1)
1086
Luca Stefani4e91ee92019-03-06 15:08:16 +01001087 exit_code = art_apex_test_main(args)
Andreas Gampe2c846cd2019-01-29 22:06:46 +00001088 sys.exit(exit_code)