blob: f2be1d8b8c2c4c3b3f33fe295b95654da48c362f [file] [log] [blame]
David Srbecky9e73fcd2022-10-05 14:29:56 +00001#!/usr/bin/env python3
jeffhao5d1ac922011-09-29 17:41:15 -07002#
3# Copyright (C) 2007 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
David Srbecky4382c262022-11-14 15:45:33 +000017import os, sys, glob, re, shutil, subprocess, shlex, resource, atexit
David Srbeckye4e701b2022-10-24 11:00:31 +000018
David Srbeckye0cbf8e2022-11-03 10:42:21 +000019import default_run as default_run_module
David Srbeckye4e701b2022-10-24 11:00:31 +000020
David Srbecky49506de2022-11-25 12:00:06 +000021from default_run import get_target_arch
David Srbeckye4e701b2022-10-24 11:00:31 +000022from importlib.machinery import SourceFileLoader
David Srbecky9c8c2db2022-11-02 10:58:10 +000023from inspect import currentframe, getframeinfo, FrameInfo
David Srbeckye4e701b2022-10-24 11:00:31 +000024from pathlib import Path
David Srbeckye19d74b2022-11-02 11:27:08 +000025from shutil import copyfile
David Srbecky69f7aca2022-11-18 18:46:56 +000026from testrunner import env
David Srbeckyefb61262022-11-30 16:49:33 +000027from typing import Optional, Dict, List
David Srbecky83cede72022-11-21 15:56:12 +000028from zipfile import ZipFile
David Srbeckye4e701b2022-10-24 11:00:31 +000029
David Srbeckyf356dcd2022-11-21 12:14:50 +000030COLOR = (os.environ.get("LUCI_CONTEXT") == None) # Disable colors on LUCI.
31COLOR_BLUE = '\033[94m' if COLOR else ''
32COLOR_GREEN = '\033[92m' if COLOR else ''
33COLOR_NORMAL = '\033[0m' if COLOR else ''
34COLOR_RED = '\033[91m' if COLOR else ''
David Srbeckye4e701b2022-10-24 11:00:31 +000035
36# Helper class which allows us to access the environment using syntax sugar.
37# E.g. `env.ANDROID_BUILD_TOP` instead of `os.environ["ANDROID_BUILD_TOP"]`.
38class Environment:
39
40 def __getattr__(self, name):
41 return os.environ.get(name)
42
43 def __setattr__(self, name, value):
44 os.environ[name] = str(value)
45
46
47# Context passed to individual tests to let them customize the behaviour.
48class RunTestContext:
49
David Srbeckyefb61262022-11-30 16:49:33 +000050 def __init__(self, tmp_dir: Path, target: bool, chroot, dex_location, test_name) -> None:
David Srbeckye4e701b2022-10-24 11:00:31 +000051 self.env = Environment()
David Srbecky66bd69a2022-11-21 18:33:08 +000052 self.target = target
53 self.chroot = chroot
54 self.dex_location = dex_location
David Srbeckyefb61262022-11-30 16:49:33 +000055 self.test_name = test_name
David Srbeckye4e701b2022-10-24 11:00:31 +000056
David Srbeckye19d74b2022-11-02 11:27:08 +000057 # Note: The expected path can be modified by the tests.
58 self.expected_stdout = tmp_dir / "expected-stdout.txt"
59 self.expected_stderr = tmp_dir / "expected-stderr.txt"
60
David Srbeckyefb61262022-11-30 16:49:33 +000061 self.runner: List[str] = ["#!/bin/bash"]
62
David Srbeckye4e701b2022-10-24 11:00:31 +000063 def echo(self, text):
David Srbecky66bd69a2022-11-21 18:33:08 +000064 self.run(f"echo {text} > {test_stdout}")
David Srbeckye4e701b2022-10-24 11:00:31 +000065
David Srbeckyefb61262022-11-30 16:49:33 +000066 def export(self, **env: str) -> None:
67 self.runner.append("")
68 for name, value in env.items():
69 self.runner.append(f"export {name}={value}")
70
71 # Add "runner" script command. It is not executed now.
72 # All "runner" commands are executed later via single bash call.
73 def run(self, cmd: str, check: bool=True, expected_exit_code: int=0, desc:str = None) -> None:
74 if cmd == "true":
75 return
76 cmd_esc = cmd.replace("'", r"'\''")
77 self.runner.append("")
78 self.runner.append(f"echo '{COLOR_BLUE}$$ {cmd_esc}{COLOR_NORMAL}'")
79 self.runner.append(cmd)
80
81 # Check the exit code.
82 if check:
83 caller = getframeinfo(currentframe().f_back) # type: ignore
84 source = "{}:{}".format(Path(caller.filename).name, caller.lineno)
85 msg = f"{self.test_name} FAILED: [{source}] "
86 msg += "{} returned exit code ${{exit_code}}.".format(desc or "Command")
87 if expected_exit_code:
88 msg += f" Expected {expected_exit_code}."
89 self.runner.append(
90 f"exit_code=$?; if [ $exit_code -ne {expected_exit_code} ]; then "
91 f"echo {COLOR_RED}{msg}{COLOR_NORMAL}; exit 100; "
92 f"fi; ")
93 else:
94 self.runner.append("true; # Ignore previous exit code")
David Srbeckye4e701b2022-10-24 11:00:31 +000095
96 # Execute the default runner (possibly with modified arguments).
97 def default_run(self, args, **kwargs):
David Srbeckye0cbf8e2022-11-03 10:42:21 +000098 default_run_module.default_run(self, args, **kwargs)
David Srbeckye4e701b2022-10-24 11:00:31 +000099
David Srbecky9e73fcd2022-10-05 14:29:56 +0000100
David Srbecky94d21412022-10-10 16:02:51 +0100101# TODO: Replace with 'def main():' (which might change variables from globals to locals)
102if True:
103 progdir = os.path.dirname(__file__)
104 oldwd = os.getcwd()
105 os.chdir(progdir)
106 test_dir = "test-{}".format(os.getpid())
107 TMPDIR = os.environ.get("TMPDIR")
108 USER = os.environ.get("USER")
109 PYTHON3 = os.environ.get("PYTHON3")
110 if not TMPDIR:
111 tmp_dir = f"/tmp/{USER}/{test_dir}"
112 else:
113 tmp_dir = f"{TMPDIR}/{test_dir}"
114 checker = f"{progdir}/../tools/checker/checker.py"
David Srbecky9e73fcd2022-10-05 14:29:56 +0000115
Ulya Trafimovich513801a2023-01-19 18:26:43 +0000116 ON_VM = os.environ.get("ART_TEST_ON_VM")
117 SSH_USER = os.environ.get("ART_TEST_SSH_USER")
118 SSH_HOST = os.environ.get("ART_TEST_SSH_HOST")
119 SSH_PORT = os.environ.get("ART_TEST_SSH_PORT")
120 SSH_CMD = os.environ.get("ART_SSH_CMD")
121 SCP_CMD = os.environ.get("ART_SCP_CMD")
122 CHROOT = os.environ.get("ART_TEST_CHROOT")
123 CHROOT_CMD = os.environ.get("ART_CHROOT_CMD")
124
David Srbecky9c8c2db2022-11-02 10:58:10 +0000125 def fail(message: str, caller:Optional[FrameInfo]=None):
126 caller = caller or getframeinfo(currentframe().f_back) # type: ignore
David Srbeckyefb61262022-11-30 16:49:33 +0000127 assert caller
128 source = "{}:{}".format(Path(caller.filename).name, caller.lineno)
129 print(f"{COLOR_RED}{TEST_NAME} FAILED: [{source}] {message}{COLOR_NORMAL}",
David Srbecky9c8c2db2022-11-02 10:58:10 +0000130 file=sys.stderr)
131 sys.exit(1)
132
David Srbeckyefb61262022-11-30 16:49:33 +0000133 def run(cmdline: str, check=True, fail_message=None) -> subprocess.CompletedProcess:
134 print(f"{COLOR_BLUE}$ {cmdline}{COLOR_NORMAL}", flush=True)
David Srbecky94d21412022-10-10 16:02:51 +0100135 proc = subprocess.run([cmdline],
136 shell=True,
David Srbeckyefb61262022-11-30 16:49:33 +0000137 executable="/bin/bash",
138 stderr=subprocess.STDOUT)
David Srbecky94d21412022-10-10 16:02:51 +0100139 if (check and proc.returncode != 0):
David Srbeckyf66ea6c2022-11-01 15:10:17 +0000140 if fail_message:
141 # If we have custom fail message, exit without printing the full backtrace.
David Srbecky9c8c2db2022-11-02 10:58:10 +0000142 fail(fail_message, getframeinfo(currentframe().f_back)) # type: ignore
David Srbeckyf66ea6c2022-11-01 15:10:17 +0000143 raise Exception(f"Command failed (exit code {proc.returncode})")
David Srbecky94d21412022-10-10 16:02:51 +0100144 return proc
David Srbecky9e73fcd2022-10-05 14:29:56 +0000145
David Srbecky94d21412022-10-10 16:02:51 +0100146 def export(env: str, value: str) -> None:
147 os.environ[env] = value
148 globals()[env] = value
David Srbecky9e73fcd2022-10-05 14:29:56 +0000149
David Srbecky94d21412022-10-10 16:02:51 +0100150 def error(msg) -> None:
151 print(msg, file=sys.stderr, flush=True)
Andreas Gampe8fda9f22014-10-03 16:15:37 -0700152
David Srbeckye4e701b2022-10-24 11:00:31 +0000153 # ANDROID_BUILD_TOP is not set in a build environment.
David Srbecky94d21412022-10-10 16:02:51 +0100154 ANDROID_BUILD_TOP = os.environ.get("ANDROID_BUILD_TOP")
155 if not ANDROID_BUILD_TOP:
David Srbecky9e73fcd2022-10-05 14:29:56 +0000156 export("ANDROID_BUILD_TOP", oldwd)
Sebastien Hertz19ac0272015-02-24 17:39:50 +0100157
David Srbecky94d21412022-10-10 16:02:51 +0100158 export("JAVA", "java")
159 export("JAVAC", "javac -g -Xlint:-options -source 1.8 -target 1.8")
160 export("PYTHON3",
161 f"{ANDROID_BUILD_TOP}/prebuilts/build-tools/path/linux-x86/python3")
162 export("RUN", f"{PYTHON3} {progdir}/etc/run-test-jar")
163 export("DEX_LOCATION", f"/data/run-test/{test_dir}")
David Srbeckybfa76b32022-06-20 21:30:56 +0100164
David Srbecky94d21412022-10-10 16:02:51 +0100165 # OUT_DIR defaults to out, and may be relative to ANDROID_BUILD_TOP.
166 # Convert it to an absolute path, since we cd into the tmp_dir to run the tests.
167 OUT_DIR = os.environ.get("OUT_DIR", "")
168 export("OUT_DIR", OUT_DIR or "out")
169 if not OUT_DIR.startswith("/"):
David Srbecky9e73fcd2022-10-05 14:29:56 +0000170 export("OUT_DIR", f"{ANDROID_BUILD_TOP}/{OUT_DIR}")
Dan Willemsen12371e92017-03-06 17:55:20 -0800171
Andreas Gampef47fb2f2016-06-24 22:30:29 -0700172# ANDROID_HOST_OUT is not set in a build environment.
David Srbecky94d21412022-10-10 16:02:51 +0100173 ANDROID_HOST_OUT = os.environ.get("ANDROID_HOST_OUT")
174 if not ANDROID_HOST_OUT:
David Srbecky9e73fcd2022-10-05 14:29:56 +0000175 export("ANDROID_HOST_OUT", f"{OUT_DIR}/host/linux-x86")
Andreas Gampef47fb2f2016-06-24 22:30:29 -0700176
David Srbecky94d21412022-10-10 16:02:51 +0100177 host_lib_root = ANDROID_HOST_OUT
178 chroot = ""
179 info = "info.txt"
180 run_cmd = "run"
David Srbecky94d21412022-10-10 16:02:51 +0100181 test_stdout = "test-stdout.txt"
182 test_stderr = "test-stderr.txt"
183 cfg_output = "graph.cfg"
184 strace_output = "strace-output.txt"
185 lib = "libartd.so"
186 testlib = "arttestd"
187 run_args = []
188 run_checker = "no"
jeffhao5d1ac922011-09-29 17:41:15 -0700189
David Srbecky94d21412022-10-10 16:02:51 +0100190 quiet = "no"
191 debuggable = "no"
192 prebuild_mode = "yes"
193 target_mode = "yes"
194 dev_mode = "no"
195 create_runner = "no"
196 update_mode = "no"
197 debug_mode = "no"
198 relocate = "no"
199 runtime = "art"
200 usage = "no"
201 suffix64 = ""
202 trace = "false"
203 trace_stream = "false"
204 basic_verify = "false"
205 gc_verify = "false"
206 gc_stress = "false"
207 jvmti_trace_stress = "false"
208 jvmti_field_stress = "false"
209 jvmti_step_stress = "false"
210 jvmti_redefine_stress = "false"
211 strace = "false"
212 always_clean = "no"
213 never_clean = "no"
214 have_image = "yes"
215 android_root = "/system"
216 bisection_search = "no"
217 timeout = ""
218 suspend_timeout = "500000"
219 run_optimizing = "false"
220 dump_cfg = "false"
221 dump_cfg_path = ""
222 # To cause tests to fail fast, limit the file sizes created by dx, dex2oat and
223 # ART output to approximately 128MB. This should be more than sufficient
224 # for any test while still catching cases of runaway output.
225 # Set a hard limit to encourage ART developers to increase the ulimit here if
226 # needed to support a test case rather than resetting the limit in the run
227 # script for the particular test in question. Adjust this if needed for
228 # particular configurations.
229 file_ulimit = 128000
Alex Light20802ca2018-12-05 15:36:03 -0800230
David Srbecky94d21412022-10-10 16:02:51 +0100231 args = list(sys.argv)
232 arg = args[0]
Andreas Gampe11410de2019-07-02 15:53:53 -0700233
David Srbecky94d21412022-10-10 16:02:51 +0100234 def shift():
235 global arg
236 args.pop(0)
237 arg = args[0] if args else ""
238
239 shift()
240
241 while True:
David Srbecky9e73fcd2022-10-05 14:29:56 +0000242 if arg == "--host":
David Srbecky94d21412022-10-10 16:02:51 +0100243 target_mode = "no"
244 DEX_LOCATION = tmp_dir
245 run_args += ["--host"]
David Srbecky92eba602022-10-25 11:11:55 +0000246 os.environ["RUN_MODE"] = "host"
David Srbecky94d21412022-10-10 16:02:51 +0100247 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000248 elif arg == "--quiet":
David Srbecky94d21412022-10-10 16:02:51 +0100249 quiet = "yes"
250 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000251 elif arg == "--use-java-home":
David Srbecky94d21412022-10-10 16:02:51 +0100252 JAVA_HOME = os.environ.get("JAVA_HOME")
253 if JAVA_HOME:
254 export("JAVA", f"{JAVA_HOME}/bin/java")
255 export("JAVAC", f"{JAVA_HOME}/bin/javac -g")
256 else:
257 error("Passed --use-java-home without JAVA_HOME variable set!")
258 usage = "yes"
259 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000260 elif arg == "--jvm":
David Srbecky94d21412022-10-10 16:02:51 +0100261 target_mode = "no"
262 DEX_LOCATION = tmp_dir
263 runtime = "jvm"
264 prebuild_mode = "no"
265 run_args += ["--jvm"]
266 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000267 elif arg == "-O":
David Srbecky94d21412022-10-10 16:02:51 +0100268 lib = "libart.so"
269 testlib = "arttest"
270 run_args += ["-O"]
271 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000272 elif arg == "--dalvik":
David Srbecky94d21412022-10-10 16:02:51 +0100273 lib = "libdvm.so"
274 runtime = "dalvik"
275 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000276 elif arg == "--no-image":
David Srbecky94d21412022-10-10 16:02:51 +0100277 have_image = "no"
278 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000279 elif arg == "--relocate":
David Srbecky94d21412022-10-10 16:02:51 +0100280 relocate = "yes"
281 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000282 elif arg == "--no-relocate":
David Srbecky94d21412022-10-10 16:02:51 +0100283 relocate = "no"
284 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000285 elif arg == "--prebuild":
David Srbecky94d21412022-10-10 16:02:51 +0100286 run_args += ["--prebuild"]
287 prebuild_mode = "yes"
288 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000289 elif arg == "--compact-dex-level":
David Srbecky94d21412022-10-10 16:02:51 +0100290 option = arg
291 shift()
292 run_args += [f'"{option}" "{arg}"']
293 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000294 elif arg == "--strip-dex":
David Srbecky94d21412022-10-10 16:02:51 +0100295 run_args += ["--strip-dex"]
296 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000297 elif arg == "--debuggable":
David Srbecky94d21412022-10-10 16:02:51 +0100298 run_args += ["-Xcompiler-option --debuggable"]
299 debuggable = "yes"
300 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000301 elif arg == "--no-prebuild":
David Srbecky94d21412022-10-10 16:02:51 +0100302 run_args += ["--no-prebuild"]
303 prebuild_mode = "no"
304 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000305 elif arg == "--gcverify":
David Srbecky94d21412022-10-10 16:02:51 +0100306 basic_verify = "true"
307 gc_verify = "true"
308 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000309 elif arg == "--gcstress":
David Srbecky94d21412022-10-10 16:02:51 +0100310 basic_verify = "true"
311 gc_stress = "true"
312 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000313 elif arg == "--jvmti-step-stress":
David Srbecky94d21412022-10-10 16:02:51 +0100314 jvmti_step_stress = "true"
David Srbecky92eba602022-10-25 11:11:55 +0000315 os.environ["JVMTI_STEP_STRESS"] = "true"
David Srbecky94d21412022-10-10 16:02:51 +0100316 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000317 elif arg == "--jvmti-redefine-stress":
David Srbecky94d21412022-10-10 16:02:51 +0100318 jvmti_redefine_stress = "true"
David Srbecky92eba602022-10-25 11:11:55 +0000319 os.environ["JVMTI_REDEFINE_STRESS"] = "true"
David Srbecky94d21412022-10-10 16:02:51 +0100320 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000321 elif arg == "--jvmti-field-stress":
David Srbecky94d21412022-10-10 16:02:51 +0100322 jvmti_field_stress = "true"
David Srbecky92eba602022-10-25 11:11:55 +0000323 os.environ["JVMTI_FIELD_STRESS"] = "true"
David Srbecky94d21412022-10-10 16:02:51 +0100324 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000325 elif arg == "--jvmti-trace-stress":
David Srbecky94d21412022-10-10 16:02:51 +0100326 jvmti_trace_stress = "true"
David Srbecky92eba602022-10-25 11:11:55 +0000327 os.environ["JVMTI_TRACE_STRESS"] = "true"
David Srbecky94d21412022-10-10 16:02:51 +0100328 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000329 elif arg == "--suspend-timeout":
David Srbecky94d21412022-10-10 16:02:51 +0100330 shift()
331 suspend_timeout = arg
332 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000333 elif arg == "--image":
David Srbecky94d21412022-10-10 16:02:51 +0100334 shift()
335 image = arg
336 run_args += [f'--image "{image}"']
337 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000338 elif arg == "-Xcompiler-option":
David Srbecky94d21412022-10-10 16:02:51 +0100339 shift()
340 option = arg
341 run_args += [f'-Xcompiler-option "{option}"']
342 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000343 elif arg == "--runtime-option":
David Srbecky94d21412022-10-10 16:02:51 +0100344 shift()
345 option = arg
346 run_args += [f'--runtime-option "{option}"']
347 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000348 elif arg == "--gdb-arg":
David Srbecky94d21412022-10-10 16:02:51 +0100349 shift()
350 gdb_arg = arg
351 run_args += [f'--gdb-arg "{gdb_arg}"']
352 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000353 elif arg == "--gdb-dex2oat-args":
David Srbecky94d21412022-10-10 16:02:51 +0100354 shift()
355 gdb_dex2oat_args = arg
356 run_args += ['--gdb-dex2oat-args "{gdb_dex2oat_args}"']
357 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000358 elif arg == "--debug":
David Srbecky94d21412022-10-10 16:02:51 +0100359 run_args += ["--debug"]
360 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000361 elif arg == "--debug-wrap-agent":
David Srbecky94d21412022-10-10 16:02:51 +0100362 run_args += ["--debug-wrap-agent"]
363 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000364 elif arg == "--with-agent":
David Srbecky94d21412022-10-10 16:02:51 +0100365 shift()
366 option = arg
367 run_args += [f'--with-agent "{arg}"']
368 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000369 elif arg == "--debug-agent":
David Srbecky94d21412022-10-10 16:02:51 +0100370 shift()
371 option = arg
372 run_args += [f'--debug-agent "{arg}"']
373 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000374 elif arg == "--dump-cfg":
David Srbecky94d21412022-10-10 16:02:51 +0100375 shift()
376 dump_cfg = "true"
Richard Neillb4633822022-10-13 17:15:25 +0100377 dump_cfg_path = arg
David Srbecky94d21412022-10-10 16:02:51 +0100378 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000379 elif arg == "--gdb":
David Srbecky94d21412022-10-10 16:02:51 +0100380 run_args += ["--gdb"]
381 dev_mode = "yes"
382 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000383 elif arg == "--gdb-dex2oat":
David Srbecky94d21412022-10-10 16:02:51 +0100384 run_args += ["--gdb-dex2oat"]
385 dev_mode = "yes"
386 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000387 elif arg == "--gdbserver-bin":
David Srbecky94d21412022-10-10 16:02:51 +0100388 shift()
389 run_args += [f'--gdbserver-bin "{arg}"']
390 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000391 elif arg == "--gdbserver-port":
David Srbecky94d21412022-10-10 16:02:51 +0100392 shift()
393 run_args += [f'--gdbserver-port "{arg}"']
394 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000395 elif arg == "--gdbserver":
David Srbecky94d21412022-10-10 16:02:51 +0100396 run_args += ["--gdbserver"]
397 dev_mode = "yes"
398 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000399 elif arg == "--strace":
David Srbecky94d21412022-10-10 16:02:51 +0100400 strace = "yes"
401 run_args += [
402 f'--invoke-with=strace --invoke-with=-o --invoke-with="{tmp_dir}/{strace_output}"'
403 ]
404 timeout = timeout or "1800"
405 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000406 elif arg == "--zygote":
David Srbecky94d21412022-10-10 16:02:51 +0100407 run_args += ["--zygote"]
408 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000409 elif arg == "--interpreter":
David Srbecky94d21412022-10-10 16:02:51 +0100410 run_args += ["--interpreter"]
411 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000412 elif arg == "--jit":
David Srbecky94d21412022-10-10 16:02:51 +0100413 run_args += ["--jit"]
414 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000415 elif arg == "--baseline":
David Srbecky94d21412022-10-10 16:02:51 +0100416 run_args += ["--baseline"]
417 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000418 elif arg == "--optimizing":
David Srbecky94d21412022-10-10 16:02:51 +0100419 run_optimizing = "true"
420 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000421 elif arg == "--no-verify":
David Srbecky94d21412022-10-10 16:02:51 +0100422 run_args += ["--no-verify"]
423 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000424 elif arg == "--verify-soft-fail":
David Srbecky94d21412022-10-10 16:02:51 +0100425 run_args += ["--verify-soft-fail"]
David Srbecky63538502022-10-19 11:21:21 +0100426 os.environ["VERIFY_SOFT_FAIL"] = "true"
David Srbecky94d21412022-10-10 16:02:51 +0100427 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000428 elif arg == "--no-optimize":
David Srbecky94d21412022-10-10 16:02:51 +0100429 run_args += ["--no-optimize"]
430 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000431 elif arg == "--no-precise":
David Srbecky94d21412022-10-10 16:02:51 +0100432 run_args += ["--no-precise"]
433 shift()
David Srbeckyfe3d9c92022-11-10 18:57:15 +0000434 elif arg.startswith("--android-log-tags"):
435 run_args += [arg]
436 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000437 elif arg == "--external-log-tags":
David Srbecky94d21412022-10-10 16:02:51 +0100438 run_args += ["--external-log-tags"]
439 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000440 elif arg == "--invoke-with":
David Srbecky94d21412022-10-10 16:02:51 +0100441 shift()
442 what = arg
443 if not arg:
444 error("missing argument to --invoke-with")
445 usage = "yes"
446 break
447 run_args += [f'--invoke-with "{what}"']
448 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000449 elif arg == "--create-runner":
David Srbecky94d21412022-10-10 16:02:51 +0100450 run_args += ["--create-runner --dry-run"]
451 dev_mode = "yes"
452 never_clean = "yes"
453 create_runner = "yes"
454 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000455 elif arg == "--dev":
David Srbecky94d21412022-10-10 16:02:51 +0100456 dev_mode = "yes"
457 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000458 elif arg == "--temp-path":
David Srbecky94d21412022-10-10 16:02:51 +0100459 shift()
460 if not arg:
461 error("missing argument to --temp-path")
462 usage = "yes"
463 break
464 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000465 elif arg == "--chroot":
David Srbecky94d21412022-10-10 16:02:51 +0100466 shift()
467 if not arg:
468 error("missing argument to --chroot")
469 usage = "yes"
470 break
471 chroot = arg
472 run_args += [f'--chroot "{arg}"']
473 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000474 elif arg == "--simpleperf":
David Srbecky94d21412022-10-10 16:02:51 +0100475 run_args += ["--simpleperf"]
476 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000477 elif arg == "--android-root":
David Srbecky94d21412022-10-10 16:02:51 +0100478 shift()
479 if not arg:
480 error("missing argument to --android-root")
481 usage = "yes"
482 break
483 android_root = arg
484 run_args += [f'--android-root "{arg}"']
485 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000486 elif arg == "--android-art-root":
David Srbecky94d21412022-10-10 16:02:51 +0100487 shift()
488 if not arg:
489 error("missing argument to --android-art-root")
490 usage = "yes"
491 break
492 run_args += [f'--android-art-root "{arg}"']
493 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000494 elif arg == "--android-tzdata-root":
David Srbecky94d21412022-10-10 16:02:51 +0100495 shift()
496 if not arg:
497 error("missing argument to --android-tzdata-root")
498 usage = "yes"
499 break
500 run_args += [f'--android-tzdata-root "{arg}"']
501 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000502 elif arg == "--update":
David Srbecky94d21412022-10-10 16:02:51 +0100503 update_mode = "yes"
504 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000505 elif arg == "--help":
David Srbecky94d21412022-10-10 16:02:51 +0100506 usage = "yes"
507 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000508 elif arg == "--64":
David Srbecky94d21412022-10-10 16:02:51 +0100509 run_args += ["--64"]
510 suffix64 = "64"
511 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000512 elif arg == "--bionic":
David Srbecky94d21412022-10-10 16:02:51 +0100513 # soong linux_bionic builds are 64bit only.
514 run_args += ["--bionic --host --64"]
515 suffix64 = "64"
516 target_mode = "no"
517 DEX_LOCATION = tmp_dir
518 host_lib_root = f"{OUT_DIR}/soong/host/linux_bionic-x86"
519 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000520 elif arg == "--runtime-extracted-zipapex":
David Srbecky94d21412022-10-10 16:02:51 +0100521 shift()
522 # TODO Should we allow the java.library.path to search the zipapex too?
523 # Not needed at the moment and adding it will be complicated so for now
524 # we'll ignore this.
525 run_args += [f'--host --runtime-extracted-zipapex "{arg}"']
526 target_mode = "no"
527 DEX_LOCATION = tmp_dir
528 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000529 elif arg == "--runtime-zipapex":
David Srbecky94d21412022-10-10 16:02:51 +0100530 shift()
531 # TODO Should we allow the java.library.path to search the zipapex too?
532 # Not needed at the moment and adding it will be complicated so for now
533 # we'll ignore this.
534 run_args += [f'--host --runtime-zipapex "{arg}"']
535 target_mode = "no"
536 DEX_LOCATION = tmp_dir
537 # apex_payload.zip is quite large we need a high enough ulimit to
538 # extract it. 512mb should be good enough.
539 file_ulimit = 512000
540 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000541 elif arg == "--timeout":
David Srbecky94d21412022-10-10 16:02:51 +0100542 shift()
543 if not arg:
544 error("missing argument to --timeout")
545 usage = "yes"
546 break
547 timeout = arg
548 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000549 elif arg == "--trace":
David Srbecky94d21412022-10-10 16:02:51 +0100550 trace = "true"
551 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000552 elif arg == "--stream":
David Srbecky94d21412022-10-10 16:02:51 +0100553 trace_stream = "true"
554 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000555 elif arg == "--always-clean":
David Srbecky94d21412022-10-10 16:02:51 +0100556 always_clean = "yes"
557 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000558 elif arg == "--never-clean":
David Srbecky94d21412022-10-10 16:02:51 +0100559 never_clean = "yes"
560 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000561 elif arg == "--dex2oat-swap":
David Srbecky94d21412022-10-10 16:02:51 +0100562 run_args += ["--dex2oat-swap"]
563 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000564 elif arg == "--instruction-set-features":
David Srbecky94d21412022-10-10 16:02:51 +0100565 shift()
566 run_args += [f'--instruction-set-features "{arg}"']
567 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000568 elif arg == "--bisection-search":
David Srbecky94d21412022-10-10 16:02:51 +0100569 bisection_search = "yes"
570 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000571 elif arg == "--vdex":
David Srbecky94d21412022-10-10 16:02:51 +0100572 run_args += ["--vdex"]
573 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000574 elif arg == "--dm":
David Srbecky94d21412022-10-10 16:02:51 +0100575 run_args += ["--dm"]
576 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000577 elif arg == "--vdex-filter":
David Srbecky94d21412022-10-10 16:02:51 +0100578 shift()
579 filter = arg
580 run_args += ['--vdex-filter "{filter}"']
581 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000582 elif arg == "--random-profile":
David Srbecky94d21412022-10-10 16:02:51 +0100583 run_args += ["--random-profile"]
584 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000585 elif arg == "--dex2oat-jobs":
David Srbecky94d21412022-10-10 16:02:51 +0100586 shift()
587 run_args += [f'-Xcompiler-option "-j{arg}"']
588 shift()
David Srbecky9e73fcd2022-10-05 14:29:56 +0000589 elif arg.startswith("--"):
David Srbecky94d21412022-10-10 16:02:51 +0100590 error(f"unknown option: {arg}")
591 usage = "yes"
592 break
David Srbecky9e73fcd2022-10-05 14:29:56 +0000593 else:
David Srbecky94d21412022-10-10 16:02:51 +0100594 break
Andreas Gampe3a12cfe2014-08-13 15:40:22 -0700595
David Srbecky94d21412022-10-10 16:02:51 +0100596 export("DEX_LOCATION", DEX_LOCATION)
David Srbecky9e73fcd2022-10-05 14:29:56 +0000597
David Srbecky94d21412022-10-10 16:02:51 +0100598 if usage == "no" and not arg:
599 error("missing test to run")
600 usage = "yes"
Orion Hodson6aa4e0d2018-05-25 09:39:16 +0100601
Roland Levillain76cfe612017-10-30 13:14:28 +0000602# The DEX_LOCATION with the chroot prefix, if any.
David Srbecky94d21412022-10-10 16:02:51 +0100603 chroot_dex_location = f"{chroot}{DEX_LOCATION}"
Alex Light91de25f2015-10-28 17:00:06 -0700604
David Srbecky94d21412022-10-10 16:02:51 +0100605 # tmp_dir may be relative, resolve.
606 os.chdir(oldwd)
607 tmp_dir = os.path.realpath(tmp_dir)
608 os.chdir(progdir)
609 if not tmp_dir:
610 error(f"Failed to resolve {tmp_dir}")
611 sys.exit(1)
612 os.makedirs(tmp_dir, exist_ok=True)
jeffhao5d1ac922011-09-29 17:41:15 -0700613
David Srbecky94d21412022-10-10 16:02:51 +0100614 # Add thread suspend timeout flag
615 if runtime != "jvm":
616 run_args += [
617 f'--runtime-option "-XX:ThreadSuspendTimeout={suspend_timeout}"'
618 ]
Mathieu Chartier3fceaf52017-01-22 13:33:40 -0800619
David Srbecky94d21412022-10-10 16:02:51 +0100620 if basic_verify == "true":
621 # Set HspaceCompactForOOMMinIntervalMs to zero to run hspace compaction for OOM more frequently in tests.
622 run_args += [
623 "--runtime-option -Xgc:preverify --runtime-option -Xgc:postverify "
624 "--runtime-option -XX:HspaceCompactForOOMMinIntervalMs=0"
625 ]
626 if gc_verify == "true":
627 run_args += [
628 "--runtime-option -Xgc:preverify_rosalloc --runtime-option "
629 "-Xgc:postverify_rosalloc"
630 ]
631 if gc_stress == "true":
632 run_args += [
633 "--gc-stress --runtime-option -Xgc:gcstress --runtime-option -Xms2m "
634 "--runtime-option -Xmx16m"
635 ]
636 if jvmti_redefine_stress == "true":
637 run_args += ["--no-app-image --jvmti-redefine-stress"]
638 if jvmti_step_stress == "true":
639 run_args += ["--no-app-image --jvmti-step-stress"]
640 if jvmti_field_stress == "true":
641 run_args += ["--no-app-image --jvmti-field-stress"]
642 if jvmti_trace_stress == "true":
643 run_args += ["--no-app-image --jvmti-trace-stress"]
644 if trace == "true":
645 run_args += [
646 "--runtime-option -Xmethod-trace --runtime-option "
647 "-Xmethod-trace-file-size:2000000"
648 ]
David Srbecky9e73fcd2022-10-05 14:29:56 +0000649 if trace_stream == "true":
David Srbecky94d21412022-10-10 16:02:51 +0100650 # Streaming mode uses the file size as the buffer size. So output gets really large. Drop
651 # the ability to analyze the file and just write to /dev/null.
652 run_args += ["--runtime-option -Xmethod-trace-file:/dev/null"]
653 # Enable streaming mode.
654 run_args += ["--runtime-option -Xmethod-trace-stream"]
David Srbecky9e73fcd2022-10-05 14:29:56 +0000655 else:
David Srbecky94d21412022-10-10 16:02:51 +0100656 run_args += [
657 f'--runtime-option "-Xmethod-trace-file:{DEX_LOCATION}/trace.bin"'
658 ]
659 elif trace_stream == "true":
David Srbecky9e73fcd2022-10-05 14:29:56 +0000660 error("Cannot use --stream without --trace.")
661 sys.exit(1)
David Srbecky94d21412022-10-10 16:02:51 +0100662 if timeout:
663 run_args += [f'--timeout "{timeout}"']
Jeff Hao85139a32014-07-23 11:52:52 -0700664
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700665# Most interesting target architecture variables are Makefile variables, not environment variables.
David Srbecky9e73fcd2022-10-05 14:29:56 +0000666# Try to map the suffix64 flag and what we find in {ANDROID_PRODUCT_OUT}/data/art-test to an architecture name.
David Srbecky94d21412022-10-10 16:02:51 +0100667
668 def guess_target_arch_name():
David Srbeckyefb61262022-11-30 16:49:33 +0000669 return get_target_arch(suffix64 == "64")
Andreas Gampe1c83cbc2014-07-22 18:52:29 -0700670
David Srbecky94d21412022-10-10 16:02:51 +0100671 def guess_host_arch_name():
David Srbecky9e73fcd2022-10-05 14:29:56 +0000672 if suffix64 == "64":
David Srbecky94d21412022-10-10 16:02:51 +0100673 return "x86_64"
David Srbecky9e73fcd2022-10-05 14:29:56 +0000674 else:
David Srbecky94d21412022-10-10 16:02:51 +0100675 return "x86"
David Brazdil853a4c32015-09-28 16:15:50 +0100676
David Srbecky94d21412022-10-10 16:02:51 +0100677 if target_mode == "no":
David Srbecky9e73fcd2022-10-05 14:29:56 +0000678 if runtime == "jvm":
David Srbecky94d21412022-10-10 16:02:51 +0100679 if prebuild_mode == "yes":
680 error("--prebuild with --jvm is unsupported")
David Srbecky9e73fcd2022-10-05 14:29:56 +0000681 sys.exit(1)
David Srbecky94d21412022-10-10 16:02:51 +0100682 else:
683 # ART/Dalvik host mode.
684 if chroot:
685 error("--chroot with --host is unsupported")
686 sys.exit(1)
Alex Light03a112d2014-08-25 13:25:56 -0700687
David Srbecky94d21412022-10-10 16:02:51 +0100688 if runtime != "jvm":
689 run_args += [f'--lib "{lib}"']
690
691 ANDROID_PRODUCT_OUT = os.environ.get("ANDROID_PRODUCT_OUT")
692 if runtime == "dalvik":
693 if target_mode == "no":
694 framework = f"{ANDROID_PRODUCT_OUT}/system/framework"
695 bpath = f"{framework}/core-icu4j.jar:{framework}/core-libart.jar:{framework}/core-oj.jar:{framework}/conscrypt.jar:{framework}/okhttp.jar:{framework}/bouncycastle.jar:{framework}/ext.jar"
696 run_args += [f'--boot --runtime-option "-Xbootclasspath:{bpath}"']
697 else:
698 pass # defaults to using target BOOTCLASSPATH
699 elif runtime == "art":
700 if target_mode == "no":
701 host_arch_name = guess_host_arch_name()
702 run_args += [
703 f'--boot "{ANDROID_HOST_OUT}/apex/art_boot_images/javalib/boot.art"'
704 ]
705 run_args += [
706 f'--runtime-option "-Djava.library.path={host_lib_root}/lib{suffix64}:{host_lib_root}/nativetest{suffix64}"'
707 ]
708 else:
709 target_arch_name = guess_target_arch_name()
710 # Note that libarttest(d).so and other test libraries that depend on ART
711 # internal libraries must not be in this path for JNI libraries - they
712 # need to be loaded through LD_LIBRARY_PATH and
713 # NATIVELOADER_DEFAULT_NAMESPACE_LIBS instead.
714 run_args += [
715 f'--runtime-option "-Djava.library.path=/data/nativetest{suffix64}/art/{target_arch_name}"'
716 ]
717 run_args += ['--boot "/system/framework/art_boot_images/boot.art"']
718 if relocate == "yes":
719 run_args += ["--relocate"]
720 else:
721 run_args += ["--no-relocate"]
722 elif runtime == "jvm":
723 # TODO: Detect whether the host is 32-bit or 64-bit.
724 run_args += [
725 f'--runtime-option "-Djava.library.path={ANDROID_HOST_OUT}/lib64:{ANDROID_HOST_OUT}/nativetest64"'
726 ]
727
728 if have_image == "no":
729 if runtime != "art":
730 error("--no-image is only supported on the art runtime")
731 sys.exit(1)
732 run_args += ["--no-image"]
733
734 if create_runner == "yes" and target_mode == "yes":
David Srbecky9e73fcd2022-10-05 14:29:56 +0000735 error("--create-runner does not function for non --host tests")
David Srbecky94d21412022-10-10 16:02:51 +0100736 usage = "yes"
Alex Light8d94ddd2019-12-18 11:13:03 -0800737
David Srbecky94d21412022-10-10 16:02:51 +0100738 if dev_mode == "yes" and update_mode == "yes":
David Srbecky9e73fcd2022-10-05 14:29:56 +0000739 error("--dev and --update are mutually exclusive")
David Srbecky94d21412022-10-10 16:02:51 +0100740 usage = "yes"
Alex Light91de25f2015-10-28 17:00:06 -0700741
David Srbecky94d21412022-10-10 16:02:51 +0100742 if dev_mode == "yes" and quiet == "yes":
David Srbecky9e73fcd2022-10-05 14:29:56 +0000743 error("--dev and --quiet are mutually exclusive")
David Srbecky94d21412022-10-10 16:02:51 +0100744 usage = "yes"
jeffhao5d1ac922011-09-29 17:41:15 -0700745
David Srbecky94d21412022-10-10 16:02:51 +0100746 if bisection_search == "yes" and prebuild_mode == "yes":
David Srbecky9e73fcd2022-10-05 14:29:56 +0000747 error("--bisection-search and --prebuild are mutually exclusive")
David Srbecky94d21412022-10-10 16:02:51 +0100748 usage = "yes"
Wojciech Staszkiewiczd7a819a2016-09-01 14:43:39 -0700749
Roland Levillain76cfe612017-10-30 13:14:28 +0000750# TODO: Chroot-based bisection search is not supported yet (see below); implement it.
David Srbecky94d21412022-10-10 16:02:51 +0100751 if bisection_search == "yes" and chroot:
752 error("--chroot with --bisection-search is unsupported")
753 sys.exit(1)
Roland Levillain76cfe612017-10-30 13:14:28 +0000754
David Srbecky94d21412022-10-10 16:02:51 +0100755 if usage == "no":
David Srbecky9e73fcd2022-10-05 14:29:56 +0000756 if not arg or arg == "-":
David Srbecky94d21412022-10-10 16:02:51 +0100757 test_dir = os.path.basename(oldwd)
David Srbecky9e73fcd2022-10-05 14:29:56 +0000758 else:
David Srbecky94d21412022-10-10 16:02:51 +0100759 test_dir = arg
jeffhao5d1ac922011-09-29 17:41:15 -0700760
David Srbecky9e73fcd2022-10-05 14:29:56 +0000761 if not os.path.isdir(test_dir):
David Srbecky94d21412022-10-10 16:02:51 +0100762 td2 = glob.glob(f"{test_dir}-*")
763 if len(td2) == 1 and os.path.isdir(td2[0]):
764 test_dir = td2[0]
765 else:
766 error(f"{test_dir}: no such test directory")
767 usage = "yes"
jeffhao5d1ac922011-09-29 17:41:15 -0700768 # Shift to get rid of the test name argument. The rest of the arguments
769 # will get passed to the test run.
David Srbecky9e73fcd2022-10-05 14:29:56 +0000770 shift()
jeffhao5d1ac922011-09-29 17:41:15 -0700771
David Srbecky94d21412022-10-10 16:02:51 +0100772 if usage == "yes":
773 prog = os.path.basename(__file__)
774 # pyformat: disable
David Srbecky9e73fcd2022-10-05 14:29:56 +0000775 help=(
David Srbecky2096c1f2022-10-10 12:47:07 +0100776 "usage:\n"
777 f" $prog --help Print this message.\n"
778 f" $prog [options] [test-name] Run test normally.\n"
779 f" $prog --dev [options] [test-name] Development mode\n"
780 "(dumps to stdout).\n"
781 f" $prog --create-runner [options] [test-name]\n"
782 " Creates a runner script for use with other \n"
783 "tools (e.g. parallel_run.py).\n"
784 " The script will only run the test portion, and \n"
785 "share oat and dex files.\n"
786 f" $prog --update [options] [test-name] Update mode\n"
787 "(replaces expected-stdout.txt and expected-stderr.txt).\n"
788 ' Omitting the test name or specifying "-" will use the\n'
789 "current directory.\n"
790 " Runtime Options:\n"
791 " -O Run non-debug rather than debug build (off by default).\n"
792 " -Xcompiler-option Pass an option to the compiler.\n"
793 " --runtime-option Pass an option to the runtime.\n"
794 " --compact-dex-level Specify a compact dex level to the compiler.\n"
795 " --debug Wait for the default debugger to attach.\n"
796 " --debug-agent <agent-path>\n"
797 " Wait for the given debugger agent to attach. Currently\n"
798 " only supported on host.\n"
799 " --debug-wrap-agent use libwrapagentproperties and tools/libjdwp-compat.props\n"
800 " to load the debugger agent specified by --debug-agent.\n"
801 " --with-agent <agent> Run the test with the given agent loaded with -agentpath:\n"
802 " --debuggable Whether to compile Java code for a debugger.\n"
803 " --gdb Run under gdb; incompatible with some tests.\n"
804 " --gdb-dex2oat Run dex2oat under the prebuilt lldb.\n"
805 " --gdbserver Start gdbserver (defaults to port :5039).\n"
806 " --gdbserver-port <port>\n"
807 " Start gdbserver with the given COMM (see man gdbserver).\n"
808 " --gdbserver-bin <binary>\n"
809 " Use the given binary as gdbserver.\n"
810 " --gdb-arg Pass an option to gdb or gdbserver.\n"
811 " --gdb-dex2oat-args Pass options separated by ';' to lldb for dex2oat.\n"
812 " --simpleperf Wraps the dalvikvm invocation in 'simpleperf record ...\n"
813 " ... simpleperf report' and dumps stats to stdout.\n"
814 " --temp-path [path] Location where to execute the tests.\n"
815 " --interpreter Enable interpreter only mode (off by default).\n"
816 " --jit Enable jit (off by default).\n"
817 " --optimizing Enable optimizing compiler (default).\n"
818 " --no-verify Turn off verification (on by default).\n"
819 " --verify-soft-fail Force soft fail verification (off by default).\n"
820 " Verification is enabled if neither --no-verify\n"
821 " nor --verify-soft-fail is specified.\n"
822 " --no-optimize Turn off optimization (on by default).\n"
823 " --no-precise Turn off precise GC (on by default).\n"
824 " --zygote Spawn the process from the Zygote.\n"
825 "If used, then the\n"
826 " other runtime options are ignored.\n"
827 " --prebuild Run dex2oat on the files before starting test. (default)\n"
828 " --no-prebuild Do not run dex2oat on the files before starting\n"
829 " the test.\n"
830 " --strip-dex Strip the dex files before starting test.\n"
831 " --relocate Force the use of relocating in the test, making\n"
832 " the image and oat files be relocated to a random\n"
833 " address before running.\n"
834 " --no-relocate Force the use of no relocating in the test. (default)\n"
835 " --image Run the test using a precompiled boot image. (default)\n"
836 " --no-image Run the test without a precompiled boot image.\n"
837 " --host Use the host-mode virtual machine.\n"
838 " --invoke-with Pass --invoke-with option to runtime.\n"
839 " --dalvik Use Dalvik (off by default).\n"
840 " --jvm Use a host-local RI virtual machine.\n"
841 " --use-java-home Use the JAVA_HOME environment variable\n"
842 " to find the java compiler and runtime\n"
843 " (if applicable) to run the test with.\n"
844 " --64 Run the test in 64-bit mode\n"
845 " --bionic Use the (host, 64-bit only) linux_bionic libc runtime\n"
846 " --runtime-zipapex [file]\n"
847 " Use the given zipapex file to provide runtime binaries\n"
848 " --runtime-extracted-zipapex [dir]\n"
849 " Use the given extracted zipapex directory to provide\n"
850 " runtime binaries\n"
851 " --timeout n Test timeout in seconds\n"
852 " --trace Run with method tracing\n"
853 " --strace Run with syscall tracing from strace.\n"
854 " --stream Run method tracing in streaming mode (requires --trace)\n"
855 " --gcstress Run with gc stress testing\n"
856 " --gcverify Run with gc verification\n"
857 " --jvmti-trace-stress Run with jvmti method tracing stress testing\n"
858 " --jvmti-step-stress Run with jvmti single step stress testing\n"
859 " --jvmti-redefine-stress\n"
860 " Run with jvmti method redefinition stress testing\n"
861 " --always-clean Delete the test files even if the test fails.\n"
862 " --never-clean Keep the test files even if the test succeeds.\n"
863 " --chroot [newroot] Run with root directory set to newroot.\n"
864 " --android-root [path] The path on target for the android root. (/system by default).\n"
865 " --android-i18n-root [path]\n"
866 " The path on target for the i18n module root.\n"
867 " (/apex/com.android.i18n by default).\n"
868 " --android-art-root [path]\n"
869 " The path on target for the ART module root.\n"
870 " (/apex/com.android.art by default).\n"
871 " --android-tzdata-root [path]\n"
872 " The path on target for the Android Time Zone Data root.\n"
873 " (/apex/com.android.tzdata by default).\n"
874 " --dex2oat-swap Use a dex2oat swap file.\n"
875 " --instruction-set-features [string]\n"
876 " Set instruction-set-features for compilation.\n"
877 " --quiet Don't print anything except failure messages\n"
878 " --external-log-tags Use ANDROID_LOG_TAGS to set a custom logging level for\n"
879 " a test run.\n"
880 " --bisection-search Perform bisection bug search.\n"
881 " --vdex Test using vdex as in input to dex2oat. Only works with --prebuild.\n"
882 " --suspend-timeout Change thread suspend timeout ms (default 500000).\n"
883 " --dex2oat-jobs Number of dex2oat jobs.\n"
David Srbecky9e73fcd2022-10-05 14:29:56 +0000884 )
David Srbecky94d21412022-10-10 16:02:51 +0100885 # pyformat: enable
David Srbecky9e73fcd2022-10-05 14:29:56 +0000886 error(help)
887 sys.exit(1)
jeffhao5d1ac922011-09-29 17:41:15 -0700888
David Srbecky94d21412022-10-10 16:02:51 +0100889 os.chdir(test_dir)
890 test_dir = os.getcwd()
jeffhao5d1ac922011-09-29 17:41:15 -0700891
David Srbecky94d21412022-10-10 16:02:51 +0100892 TEST_NAME = os.path.basename(test_dir)
893 export("TEST_NAME", TEST_NAME)
Elliott Hughes8cbc8bc2011-10-04 11:19:45 -0700894
David Srbecky94d21412022-10-10 16:02:51 +0100895 # Tests named '<number>-checker-*' will also have their CFGs verified with
896 # Checker when compiled with Optimizing on host.
897 # Additionally, if the user specifies that the CFG must be dumped, it will
898 # run the checker for any type of test to generate the CFG.
899 if re.match("[0-9]+-checker-", TEST_NAME) or dump_cfg == "true":
900 if runtime == "art" and run_optimizing == "true":
901 # In no-prebuild or no-image mode, the compiler only quickens so disable the checker.
902 if prebuild_mode == "yes":
903 run_checker = "yes"
Nicolas Geoffray1949baf2017-10-17 12:14:53 +0000904
David Srbecky94d21412022-10-10 16:02:51 +0100905 if target_mode == "no":
906 cfg_output_dir = tmp_dir
907 checker_args = f"--arch={host_arch_name.upper()}"
908 else:
909 cfg_output_dir = DEX_LOCATION
910 checker_args = f"--arch={target_arch_name.upper()}"
Nicolas Geoffray1949baf2017-10-17 12:14:53 +0000911
David Srbecky94d21412022-10-10 16:02:51 +0100912 if debuggable == "yes":
913 checker_args += " --debuggable"
Nicolas Geoffray1949baf2017-10-17 12:14:53 +0000914
David Srbecky94d21412022-10-10 16:02:51 +0100915 run_args += [
916 f'-Xcompiler-option "--dump-cfg={cfg_output_dir}/{cfg_output}" -Xcompiler-option -j1'
917 ]
918 checker_args = f"{checker_args} --print-cfg"
Nicolas Geoffray1949baf2017-10-17 12:14:53 +0000919
David Srbecky94d21412022-10-10 16:02:51 +0100920 run_args += [f'--testlib "{testlib}"']
Mathieu Chartier031768a2015-08-27 10:25:02 -0700921
David Srbeckye4e701b2022-10-24 11:00:31 +0000922 resource.setrlimit(resource.RLIMIT_FSIZE, (file_ulimit * 1024, resource.RLIM_INFINITY))
Ian Rogers997f0f92014-06-21 22:58:05 -0700923
David Srbecky94d21412022-10-10 16:02:51 +0100924 # Extract run-test data from the zip file.
925 shutil.rmtree(tmp_dir)
926 os.makedirs(f"{tmp_dir}/.unzipped")
927 os.chdir(tmp_dir)
928 m = re.match("[0-9]*([0-9][0-9])-.*", TEST_NAME)
929 assert m, "Can not find test number in " + TEST_NAME
David Srbeckyc282bef2022-11-16 21:52:33 +0000930 SHARD = "HiddenApi" if "hiddenapi" in TEST_NAME else m.group(1)
David Srbecky94d21412022-10-10 16:02:51 +0100931 if target_mode == "yes":
932 zip_file = f"{ANDROID_HOST_OUT}/etc/art/art-run-test-target-data-shard{SHARD}.zip"
David Srbecky83cede72022-11-21 15:56:12 +0000933 zip_entry = f"target/{TEST_NAME}/"
David Srbecky94d21412022-10-10 16:02:51 +0100934 elif runtime == "jvm":
935 zip_file = f"{ANDROID_HOST_OUT}/etc/art/art-run-test-jvm-data-shard{SHARD}.zip"
David Srbecky83cede72022-11-21 15:56:12 +0000936 zip_entry = f"jvm/{TEST_NAME}/"
David Srbecky94d21412022-10-10 16:02:51 +0100937 else:
938 zip_file = f"{ANDROID_HOST_OUT}/etc/art/art-run-test-host-data-shard{SHARD}.zip"
David Srbecky83cede72022-11-21 15:56:12 +0000939 zip_entry = f"host/{TEST_NAME}/"
940 zip = ZipFile(zip_file, "r")
941 zip_entries = [e for e in zip.namelist() if e.startswith(zip_entry)]
942 zip.extractall(Path(tmp_dir) / ".unzipped", members=zip_entries)
943 for entry in (Path(tmp_dir) / ".unzipped" / zip_entry).iterdir():
944 entry.rename(Path(tmp_dir) / entry.name)
David Srbecky9e73fcd2022-10-05 14:29:56 +0000945
David Srbecky4382c262022-11-14 15:45:33 +0000946 def clean_up(passed: bool):
947 if always_clean == "yes" or (passed and never_clean == "no"):
948 os.chdir(oldwd)
949 shutil.rmtree(tmp_dir)
950 if target_mode == "yes":
Ulya Trafimovich513801a2023-01-19 18:26:43 +0000951 if ON_VM:
952 run(f"{SSH_CMD} \"rm -rf {chroot_dex_location}\"")
953 else:
954 run(f"adb shell rm -rf {chroot_dex_location}")
David Srbecky4382c262022-11-14 15:45:33 +0000955 print(f"{TEST_NAME} files deleted from host" +
956 (" and from target" if target_mode == "yes" else ""))
957 else:
958 print(f"{TEST_NAME} files left in {tmp_dir} on host" +
959 (f" and in {chroot_dex_location} on target" if target_mode == "yes" else ""))
960 atexit.unregister(clean_up)
961 # TODO: Run this in global try-finally once the script is more refactored.
962 atexit.register(clean_up, passed=False)
963
David Srbeckyefb61262022-11-30 16:49:33 +0000964 ctx = RunTestContext(Path(tmp_dir), target_mode == "yes", chroot, DEX_LOCATION, TEST_NAME)
David Srbeckye19d74b2022-11-02 11:27:08 +0000965 td_info = f"{test_dir}/{info}"
966 for td_file in [td_info, ctx.expected_stdout, ctx.expected_stderr]:
967 assert os.access(td_file, os.R_OK)
968
David Srbecky94d21412022-10-10 16:02:51 +0100969 joined_run_args = " ".join(run_args)
970 joined_args = " ".join(args)
David Srbeckyca15b8d2021-04-23 12:25:08 +0100971
David Srbeckyefb61262022-11-30 16:49:33 +0000972 # Create runner (bash script that executes the whole test)
973 def create_runner_script() -> Path:
David Srbeckye0cbf8e2022-11-03 10:42:21 +0000974 parsed_args = default_run_module.parse_args(shlex.split(" ".join(run_args + args)))
David Srbecky66bd69a2022-11-21 18:33:08 +0000975 parsed_args.stdout_file = os.path.join(DEX_LOCATION, test_stdout)
976 parsed_args.stderr_file = os.path.join(DEX_LOCATION, test_stderr)
David Srbecky895c2702022-10-06 11:26:27 +0100977
David Srbeckyefb61262022-11-30 16:49:33 +0000978 ctx.run(f"cd {DEX_LOCATION}")
979 if target_mode != "yes":
980 # Make "out" directory accessible from test directory.
981 ctx.run(f"ln -s -f -t {DEX_LOCATION} {ANDROID_BUILD_TOP}/out")
982 # Clear the stdout/stderr files (create empty files).
983 ctx.run(f"echo -n > {test_stdout} && echo -n > {test_stderr}")
984
985 script = Path(tmp_dir) / "run.py"
986 if script.exists():
987 module = SourceFileLoader("run_" + TEST_NAME, str(script)).load_module()
David Srbeckye4e701b2022-10-24 11:00:31 +0000988 module.run(ctx, parsed_args)
David Srbecky8d6a4e02022-10-23 19:23:12 +0000989 else:
David Srbeckye0cbf8e2022-11-03 10:42:21 +0000990 default_run_module.default_run(ctx, parsed_args)
David Srbeckye4e701b2022-10-24 11:00:31 +0000991
David Srbeckyefb61262022-11-30 16:49:33 +0000992 runner = Path(tmp_dir) / "run.sh"
993 runner.write_text("\n".join(ctx.runner))
994 runner.chmod(0o777)
995 return runner
996
David Srbeckye4e701b2022-10-24 11:00:31 +0000997 # Test might not execute anything but we still expect the output files to exist.
998 Path(test_stdout).touch()
999 Path(test_stderr).touch()
1000
David Srbeckye4e701b2022-10-24 11:00:31 +00001001 export("TEST_RUNTIME", runtime)
1002
David Srbeckyefb61262022-11-30 16:49:33 +00001003 print(f"{test_dir}: Create runner script...")
1004 runner = create_runner_script()
1005
1006 print(f"{test_dir}: Run...")
David Srbecky66bd69a2022-11-21 18:33:08 +00001007 if target_mode == "yes":
1008 # Prepare the on-device test directory
Ulya Trafimovich513801a2023-01-19 18:26:43 +00001009 if ON_VM:
1010 run(f"{SSH_CMD} 'rm -rf {chroot_dex_location} && mkdir -p {chroot_dex_location}'")
1011 else:
1012 run("adb root")
1013 run("adb wait-for-device")
1014 run(f"adb shell 'rm -rf {chroot_dex_location} && mkdir -p {chroot_dex_location}'")
David Srbeckyefb61262022-11-30 16:49:33 +00001015 push_files = [Path(runner.name)]
1016 push_files += list(Path(".").glob(f"{TEST_NAME}*.jar"))
David Srbecky66bd69a2022-11-21 18:33:08 +00001017 push_files += list(Path(".").glob(f"expected-*.txt"))
1018 push_files += [p for p in [Path("profile"), Path("res")] if p.exists()]
Ulya Trafimovich513801a2023-01-19 18:26:43 +00001019 push_files = " ".join(map(str, push_files))
1020 if ON_VM:
1021 run(f"{SCP_CMD} {push_files} {SSH_USER}@{SSH_HOST}:{chroot_dex_location}")
1022 else:
1023 run("adb push {} {}".format(push_files, chroot_dex_location))
David Srbecky66bd69a2022-11-21 18:33:08 +00001024
Ulya Trafimovich513801a2023-01-19 18:26:43 +00001025 if ON_VM:
1026 run(f"{SSH_CMD} {CHROOT_CMD} bash {DEX_LOCATION}/run.sh",
1027 fail_message=f"Runner {chroot_dex_location}/run.sh failed")
1028 else:
1029 chroot_prefix = f"chroot {chroot}" if chroot else ""
1030 run(f"adb shell {chroot_prefix} sh {DEX_LOCATION}/run.sh",
1031 fail_message=f"Runner {chroot_dex_location}/run.sh failed")
David Srbecky66bd69a2022-11-21 18:33:08 +00001032
1033 # Copy the on-device stdout/stderr to host.
1034 pull_files = [test_stdout, test_stderr, "expected-stdout.txt", "expected-stderr.txt"]
Ulya Trafimovich513801a2023-01-19 18:26:43 +00001035 if ON_VM:
1036 srcs = " ".join(f"{SSH_USER}@{SSH_HOST}:{chroot_dex_location}/{f}" for f in pull_files)
1037 run(f"{SCP_CMD} {srcs} .")
1038 else:
1039 run("adb pull {} .".format(" ".join(f"{chroot_dex_location}/{f}" for f in pull_files)))
David Srbecky66bd69a2022-11-21 18:33:08 +00001040 else:
David Srbeckyefb61262022-11-30 16:49:33 +00001041 run(str(runner), fail_message=f"Runner {str(runner)} failed")
1042
David Srbeckye4e701b2022-10-24 11:00:31 +00001043 # NB: There is no exit code or return value.
1044 # Failing tests just raise python exception.
1045 os.chdir(tmp_dir)
David Srbeckye4e701b2022-10-24 11:00:31 +00001046 if update_mode == "yes":
David Srbeckye19d74b2022-11-02 11:27:08 +00001047 for src, dst in [(test_stdout, os.path.join(test_dir, ctx.expected_stdout.name)),
1048 (test_stderr, os.path.join(test_dir, ctx.expected_stderr.name))]:
1049 if "[DO_NOT_UPDATE]" not in open(dst).readline():
1050 copyfile(src, dst)
David Srbeckye4e701b2022-10-24 11:00:31 +00001051
David Srbecky9c8c2db2022-11-02 10:58:10 +00001052 print("#################### info")
1053 run(f'cat "{td_info}" | sed "s/^/# /g"')
1054 print("#################### stdout diff")
David Srbeckye19d74b2022-11-02 11:27:08 +00001055 proc_out = run(f'diff --strip-trailing-cr -u '
1056 f'"{ctx.expected_stdout}" "{test_stdout}"', check=False)
David Srbecky9c8c2db2022-11-02 10:58:10 +00001057 print("#################### stderr diff")
David Srbeckye19d74b2022-11-02 11:27:08 +00001058 proc_err = run(f'diff --strip-trailing-cr -u '
1059 f'"{ctx.expected_stderr}" "{test_stderr}"', check=False)
David Srbecky9c8c2db2022-11-02 10:58:10 +00001060 if strace == "yes":
1061 print("#################### strace output (trimmed to 3000 lines)")
David Srbecky6fd7de52022-11-04 15:42:38 +00001062 # Some tests do not run dalvikvm, in which case the trace does not exist.
1063 run(f'tail -n 3000 "{tmp_dir}/{strace_output}"', check=False)
David Srbecky9c8c2db2022-11-02 10:58:10 +00001064 SANITIZE_HOST = os.environ.get("SANITIZE_HOST")
1065 if target_mode == "no" and SANITIZE_HOST == "address":
1066 # Run the stack script to symbolize any ASAN aborts on the host for SANITIZE_HOST. The
1067 # tools used by the given ABI work for both x86 and x86-64.
1068 print("#################### symbolizer (trimmed to 3000 lines)")
1069 run(f'''echo "ABI: 'x86_64'" | cat - "{test_stdout}" "{test_stderr}"'''
1070 f"""| {ANDROID_BUILD_TOP}/development/scripts/stack | tail -n 3000""")
1071 print("####################", flush=True)
1072 if proc_out.returncode != 0 or proc_err.returncode != 0:
1073 kind = ((["stdout"] if proc_out.returncode != 0 else []) +
1074 (["stderr"] if proc_err.returncode != 0 else []))
1075 fail("{} did not match the expected file".format(" and ".join(kind)))
Alex Lightbfac14a2014-07-30 09:41:21 -07001076
David Srbeckyf66ea6c2022-11-01 15:10:17 +00001077 if run_checker == "yes":
1078 if target_mode == "yes":
Ulya Trafimovich513801a2023-01-19 18:26:43 +00001079 if ON_VM:
1080 run(f'{SCP_CMD} "{SSH_USER}@${SSH_HOST}:{CHROOT}/{cfg_output_dir}/{cfg_output}"')
1081 else:
1082 run(f'adb pull "{chroot}/{cfg_output_dir}/{cfg_output}"')
David Srbeckyf66ea6c2022-11-01 15:10:17 +00001083 run(f'"{checker}" -q {checker_args} "{cfg_output}" "{tmp_dir}"',
1084 fail_message="CFG checker failed")
1085
1086 # Copy the generated CFG to the specified path.
David Srbecky94d21412022-10-10 16:02:51 +01001087 if dump_cfg == "true":
David Srbeckyf66ea6c2022-11-01 15:10:17 +00001088 assert run_optimizing == "true", "The CFG can be dumped only in optimizing mode"
1089 if target_mode == "yes":
Ulya Trafimovich513801a2023-01-19 18:26:43 +00001090 if ON_VM:
1091 run(f'{SCP_CMD} "{SSH_USER}@${SSH_HOST}:{CHROOT}/{cfg_output_dir}/{cfg_output} {dump_cfg_output}"')
1092 else:
1093 run(f"adb pull {chroot}/{cfg_output_dir}/{cfg_output} {dump_cfg_path}")
David Srbecky9e73fcd2022-10-05 14:29:56 +00001094 else:
David Srbeckyf66ea6c2022-11-01 15:10:17 +00001095 run(f"cp {cfg_output_dir}/{cfg_output} {dump_cfg_path}")
Wojciech Staszkiewiczd7a819a2016-09-01 14:43:39 -07001096
David Srbecky4382c262022-11-14 15:45:33 +00001097 clean_up(passed=True)
1098 print(f"{COLOR_GREEN}{test_dir}: PASSED{COLOR_NORMAL}")