blob: be84f898b2cabf326b9e42f1b1134f6ab79ab40b [file] [log] [blame]
Shubham Ajmera65adb8b2017-02-06 16:04:25 +00001#!/usr/bin/env python
2#
3# Copyright 2017, 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
17"""ART Run-Test TestRunner
18
19The testrunner runs the ART run-tests by simply invoking the script.
20It fetches the list of eligible tests from art/test directory, and list of
21disabled tests from art/test/knownfailures.json. It runs the tests by
22invoking art/test/run-test script and checks the exit value to decide if the
23test passed or failed.
24
25Before invoking the script, first build all the tests dependencies.
26There are two major build targets for building target and host tests
27dependencies:
281) test-art-host-run-test
292) test-art-target-run-test
30
31There are various options to invoke the script which are:
32-t: Either the test name as in art/test or the test name including the variant
33 information. Eg, "-t 001-HelloWorld",
34 "-t test-art-host-run-test-debug-prebuild-optimizing-relocate-ntrace-cms-checkjni-picimage-npictest-ndebuggable-001-HelloWorld32"
35-j: Number of thread workers to be used. Eg - "-j64"
36--dry-run: Instead of running the test name, just print its name.
37--verbose
38-b / --build-dependencies: to build the dependencies before running the test
39
40To specify any specific variants for the test, use --<<variant-name>>.
41For eg, for compiler type as optimizing, use --optimizing.
42
43
44In the end, the script will print the failed and skipped tests if any.
45
46"""
Alex Light7a1ccf82017-02-21 09:52:34 -080047import argparse
Shubham Ajmera65adb8b2017-02-06 16:04:25 +000048import fnmatch
49import itertools
50import json
Shubham Ajmera65adb8b2017-02-06 16:04:25 +000051import os
52import re
53import subprocess
54import sys
55import threading
56import time
57
58import env
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -080059from target_config import target_config
Shubham Ajmera65adb8b2017-02-06 16:04:25 +000060
61TARGET_TYPES = set()
62RUN_TYPES = set()
63PREBUILD_TYPES = set()
64COMPILER_TYPES = set()
65RELOCATE_TYPES = set()
66TRACE_TYPES = set()
67GC_TYPES = set()
68JNI_TYPES = set()
69IMAGE_TYPES = set()
70PICTEST_TYPES = set()
71DEBUGGABLE_TYPES = set()
72ADDRESS_SIZES = set()
73OPTIMIZING_COMPILER_TYPES = set()
74ADDRESS_SIZES_TARGET = {'host': set(), 'target': set()}
75
76# DISABLED_TEST_CONTAINER holds information about the disabled tests. It is a map
77# that has key as the test name (like 001-HelloWorld), and value as set of
78# variants that the test is disabled for.
79DISABLED_TEST_CONTAINER = {}
80
81# The Dict contains the list of all possible variants for a given type. For example,
82# for key TARGET, the value would be target and host. The list is used to parse
83# the test name given as the argument to run.
84VARIANT_TYPE_DICT = {}
85
86# The set contains all the variants of each time.
87TOTAL_VARIANTS_SET = set()
88
89# The colors are used in the output. When a test passes, COLOR_PASS is used,
90# and so on.
91COLOR_ERROR = '\033[91m'
92COLOR_PASS = '\033[92m'
93COLOR_SKIP = '\033[93m'
94COLOR_NORMAL = '\033[0m'
95
96# The mutex object is used by the threads for exclusive access of test_count
97# to make any changes in its value.
98test_count_mutex = threading.Lock()
Shubham Ajmera14d340c2017-02-15 18:49:10 +000099
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000100# The set contains the list of all the possible run tests that are in art/test
101# directory.
102RUN_TEST_SET = set()
Shubham Ajmera14d340c2017-02-15 18:49:10 +0000103
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000104# The semaphore object is used by the testrunner to limit the number of
105# threads to the user requested concurrency value.
106semaphore = threading.Semaphore(1)
Shubham Ajmera14d340c2017-02-15 18:49:10 +0000107
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000108# The mutex object is used to provide exclusive access to a thread to print
109# its output.
110print_mutex = threading.Lock()
111failed_tests = []
112skipped_tests = []
113
114# Flags
115n_thread = 1
116test_count = 0
117total_test_count = 0
118verbose = False
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000119dry_run = False
120build = False
121gdb = False
122gdb_arg = ''
123stop_testrunner = False
124
125def gather_test_info():
126 """The method gathers test information about the test to be run which includes
127 generating the list of total tests from the art/test directory and the list
128 of disabled test. It also maps various variants to types.
129 """
130 global TOTAL_VARIANTS_SET
131 global DISABLED_TEST_CONTAINER
132 # TODO: Avoid duplication of the variant names in different lists.
133 VARIANT_TYPE_DICT['pictest'] = {'pictest', 'npictest'}
134 VARIANT_TYPE_DICT['run'] = {'ndebug', 'debug'}
135 VARIANT_TYPE_DICT['target'] = {'target', 'host'}
136 VARIANT_TYPE_DICT['trace'] = {'trace', 'ntrace', 'stream'}
Richard Uhlerbb00f812017-02-16 14:21:10 +0000137 VARIANT_TYPE_DICT['image'] = {'picimage', 'no-image', 'multipicimage'}
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000138 VARIANT_TYPE_DICT['debuggable'] = {'ndebuggable', 'debuggable'}
139 VARIANT_TYPE_DICT['gc'] = {'gcstress', 'gcverify', 'cms'}
140 VARIANT_TYPE_DICT['prebuild'] = {'no-prebuild', 'no-dex2oat', 'prebuild'}
141 VARIANT_TYPE_DICT['relocate'] = {'relocate-npatchoat', 'relocate', 'no-relocate'}
142 VARIANT_TYPE_DICT['jni'] = {'jni', 'forcecopy', 'checkjni'}
143 VARIANT_TYPE_DICT['address_sizes'] = {'64', '32'}
144 VARIANT_TYPE_DICT['compiler'] = {'interp-ac', 'interpreter', 'jit', 'optimizing',
145 'regalloc_gc'}
146
147 for v_type in VARIANT_TYPE_DICT:
148 TOTAL_VARIANTS_SET = TOTAL_VARIANTS_SET.union(VARIANT_TYPE_DICT.get(v_type))
149
150 test_dir = env.ANDROID_BUILD_TOP + '/art/test'
151 for f in os.listdir(test_dir):
152 if fnmatch.fnmatch(f, '[0-9]*'):
153 RUN_TEST_SET.add(f)
154 DISABLED_TEST_CONTAINER = get_disabled_test_info()
155
156
157def setup_test_env():
158 """The method sets default value for the various variants of the tests if they
159 are already not set.
160 """
161 if env.ART_TEST_BISECTION:
162 env.ART_TEST_RUN_TEST_NO_PREBUILD = True
163 env.ART_TEST_RUN_TEST_PREBUILD = False
164 # Bisection search writes to standard output.
165 env.ART_TEST_QUIET = False
166
167 if not TARGET_TYPES:
168 TARGET_TYPES.add('host')
169 TARGET_TYPES.add('target')
170
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000171 if env.ART_TEST_RUN_TEST_NO_PREBUILD:
172 PREBUILD_TYPES.add('no-prebuild')
173 if env.ART_TEST_RUN_TEST_NO_DEX2OAT:
174 PREBUILD_TYPES.add('no-dex2oat')
Shubham Ajmera4b8c53d2017-02-15 16:38:16 +0000175 if env.ART_TEST_RUN_TEST_PREBUILD or not PREBUILD_TYPES: # Default
176 PREBUILD_TYPES.add('prebuild')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000177
178 if env.ART_TEST_INTERPRETER_ACCESS_CHECKS:
179 COMPILER_TYPES.add('interp-ac')
180 if env.ART_TEST_INTERPRETER:
181 COMPILER_TYPES.add('interpreter')
182 if env.ART_TEST_JIT:
183 COMPILER_TYPES.add('jit')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000184 if env.ART_TEST_OPTIMIZING_GRAPH_COLOR:
185 COMPILER_TYPES.add('regalloc_gc')
186 OPTIMIZING_COMPILER_TYPES.add('regalloc_gc')
Nicolas Geoffray70b21bd2017-03-15 10:18:50 +0000187 if env.ART_TEST_OPTIMIZING:
Shubham Ajmera4b8c53d2017-02-15 16:38:16 +0000188 COMPILER_TYPES.add('optimizing')
189 OPTIMIZING_COMPILER_TYPES.add('optimizing')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000190
Nicolas Geoffray70b21bd2017-03-15 10:18:50 +0000191 # By default we run all 'compiler' variants.
192 if not COMPILER_TYPES:
193 COMPILER_TYPES.add('optimizing')
194 COMPILER_TYPES.add('jit')
195 COMPILER_TYPES.add('interpreter')
196 COMPILER_TYPES.add('interp-ac')
197 OPTIMIZING_COMPILER_TYPES.add('optimizing')
198
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000199 if env.ART_TEST_RUN_TEST_RELOCATE:
200 RELOCATE_TYPES.add('relocate')
201 if env.ART_TEST_RUN_TEST_RELOCATE_NO_PATCHOAT:
202 RELOCATE_TYPES.add('relocate-npatchoat')
Shubham Ajmera4b8c53d2017-02-15 16:38:16 +0000203 if not RELOCATE_TYPES: # Default
204 RELOCATE_TYPES.add('no-relocate')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000205
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000206 if env.ART_TEST_TRACE:
207 TRACE_TYPES.add('trace')
208 if env.ART_TEST_TRACE_STREAM:
209 TRACE_TYPES.add('stream')
Shubham Ajmera4b8c53d2017-02-15 16:38:16 +0000210 if not TRACE_TYPES: # Default
211 TRACE_TYPES.add('ntrace')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000212
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000213 if env.ART_TEST_GC_STRESS:
214 GC_TYPES.add('gcstress')
215 if env.ART_TEST_GC_VERIFY:
216 GC_TYPES.add('gcverify')
Shubham Ajmera4b8c53d2017-02-15 16:38:16 +0000217 if not GC_TYPES: # Default
218 GC_TYPES.add('cms')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000219
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000220 if env.ART_TEST_JNI_FORCECOPY:
221 JNI_TYPES.add('forcecopy')
Shubham Ajmera4b8c53d2017-02-15 16:38:16 +0000222 if not JNI_TYPES: # Default
223 JNI_TYPES.add('checkjni')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000224
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000225 if env.ART_TEST_RUN_TEST_NO_IMAGE:
226 IMAGE_TYPES.add('no-image')
227 if env.ART_TEST_RUN_TEST_MULTI_IMAGE:
228 IMAGE_TYPES.add('multipicimage')
Shubham Ajmera4b8c53d2017-02-15 16:38:16 +0000229 if env.ART_TEST_RUN_TEST_IMAGE or not IMAGE_TYPES: # Default
230 IMAGE_TYPES.add('picimage')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000231
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000232 if env.ART_TEST_PIC_TEST:
233 PICTEST_TYPES.add('pictest')
Shubham Ajmera4b8c53d2017-02-15 16:38:16 +0000234 if not PICTEST_TYPES: # Default
235 PICTEST_TYPES.add('npictest')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000236
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000237 if env.ART_TEST_RUN_TEST_NDEBUG:
238 RUN_TYPES.add('ndebug')
Shubham Ajmera4b8c53d2017-02-15 16:38:16 +0000239 if env.ART_TEST_RUN_TEST_DEBUG or not RUN_TYPES: # Default
240 RUN_TYPES.add('debug')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000241
242 if env.ART_TEST_RUN_TEST_DEBUGGABLE:
243 DEBUGGABLE_TYPES.add('debuggable')
Shubham Ajmera4b8c53d2017-02-15 16:38:16 +0000244 if not DEBUGGABLE_TYPES: # Default
245 DEBUGGABLE_TYPES.add('ndebuggable')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000246
247 if not ADDRESS_SIZES:
248 ADDRESS_SIZES_TARGET['target'].add(env.ART_PHONY_TEST_TARGET_SUFFIX)
249 ADDRESS_SIZES_TARGET['host'].add(env.ART_PHONY_TEST_HOST_SUFFIX)
250 if env.ART_TEST_RUN_TEST_2ND_ARCH:
251 ADDRESS_SIZES_TARGET['host'].add(env._2ND_ART_PHONY_TEST_HOST_SUFFIX)
252 ADDRESS_SIZES_TARGET['target'].add(env._2ND_ART_PHONY_TEST_TARGET_SUFFIX)
253 else:
254 ADDRESS_SIZES_TARGET['host'] = ADDRESS_SIZES_TARGET['host'].union(ADDRESS_SIZES)
255 ADDRESS_SIZES_TARGET['target'] = ADDRESS_SIZES_TARGET['target'].union(ADDRESS_SIZES)
256
257 global semaphore
258 semaphore = threading.Semaphore(n_thread)
259
260
261def run_tests(tests):
262 """Creates thread workers to run the tests.
263
264 The method generates command and thread worker to run the tests. Depending on
265 the user input for the number of threads to be used, the method uses a
266 semaphore object to keep a count in control for the thread workers. When a new
267 worker is created, it acquires the semaphore object, and when the number of
268 workers reaches the maximum allowed concurrency, the method wait for an
269 existing thread worker to release the semaphore object. Worker releases the
270 semaphore object when they finish printing the output.
271
272 Args:
273 tests: The set of tests to be run.
274 """
275 options_all = ''
276 global total_test_count
277 total_test_count = len(tests)
278 total_test_count *= len(RUN_TYPES)
279 total_test_count *= len(PREBUILD_TYPES)
280 total_test_count *= len(RELOCATE_TYPES)
281 total_test_count *= len(TRACE_TYPES)
282 total_test_count *= len(GC_TYPES)
283 total_test_count *= len(JNI_TYPES)
284 total_test_count *= len(IMAGE_TYPES)
285 total_test_count *= len(PICTEST_TYPES)
286 total_test_count *= len(DEBUGGABLE_TYPES)
287 total_test_count *= len(COMPILER_TYPES)
288 target_address_combinations = 0
289 for target in TARGET_TYPES:
290 for address_size in ADDRESS_SIZES_TARGET[target]:
291 target_address_combinations += 1
292 total_test_count *= target_address_combinations
293
294 if env.ART_TEST_WITH_STRACE:
295 options_all += ' --strace'
296
297 if env.ART_TEST_RUN_TEST_ALWAYS_CLEAN:
298 options_all += ' --always-clean'
299
300 if env.ART_TEST_BISECTION:
301 options_all += ' --bisection-search'
302
303 if env.ART_TEST_ANDROID_ROOT:
304 options_all += ' --android-root ' + env.ART_TEST_ANDROID_ROOT
305
306 if gdb:
307 options_all += ' --gdb'
308 if gdb_arg:
309 options_all += ' --gdb-arg ' + gdb_arg
310
311 config = itertools.product(tests, TARGET_TYPES, RUN_TYPES, PREBUILD_TYPES,
312 COMPILER_TYPES, RELOCATE_TYPES, TRACE_TYPES,
313 GC_TYPES, JNI_TYPES, IMAGE_TYPES, PICTEST_TYPES,
314 DEBUGGABLE_TYPES)
315
316 for test, target, run, prebuild, compiler, relocate, trace, gc, \
317 jni, image, pictest, debuggable in config:
318 for address_size in ADDRESS_SIZES_TARGET[target]:
319 if stop_testrunner:
320 # When ART_TEST_KEEP_GOING is set to false, then as soon as a test
321 # fails, stop_testrunner is set to True. When this happens, the method
322 # stops creating any any thread and wait for all the exising threads
323 # to end.
324 while threading.active_count() > 2:
325 time.sleep(0.1)
326 return
327 test_name = 'test-art-'
328 test_name += target + '-run-test-'
329 test_name += run + '-'
330 test_name += prebuild + '-'
331 test_name += compiler + '-'
332 test_name += relocate + '-'
333 test_name += trace + '-'
334 test_name += gc + '-'
335 test_name += jni + '-'
336 test_name += image + '-'
337 test_name += pictest + '-'
338 test_name += debuggable + '-'
339 test_name += test
340 test_name += address_size
341
342 variant_set = {target, run, prebuild, compiler, relocate, trace, gc, jni,
343 image, pictest, debuggable, address_size}
344
345 options_test = options_all
346
347 if target == 'host':
348 options_test += ' --host'
349
350 if run == 'ndebug':
351 options_test += ' -O'
352
353 if prebuild == 'prebuild':
354 options_test += ' --prebuild'
355 elif prebuild == 'no-prebuild':
356 options_test += ' --no-prebuild'
357 elif prebuild == 'no-dex2oat':
358 options_test += ' --no-prebuild --no-dex2oat'
359
360 if compiler == 'optimizing':
361 options_test += ' --optimizing'
362 elif compiler == 'regalloc_gc':
363 options_test += ' --optimizing -Xcompiler-option --register-allocation-strategy=graph-color'
364 elif compiler == 'interpreter':
365 options_test += ' --interpreter'
366 elif compiler == 'interp-ac':
367 options_test += ' --interpreter --verify-soft-fail'
368 elif compiler == 'jit':
369 options_test += ' --jit'
370
371 if relocate == 'relocate':
372 options_test += ' --relocate'
373 elif relocate == 'no-relocate':
374 options_test += ' --no-relocate'
375 elif relocate == 'relocate-npatchoat':
376 options_test += ' --relocate --no-patchoat'
377
378 if trace == 'trace':
379 options_test += ' --trace'
380 elif trace == 'stream':
381 options_test += ' --trace --stream'
382
383 if gc == 'gcverify':
384 options_test += ' --gcverify'
385 elif gc == 'gcstress':
386 options_test += ' --gcstress'
387
388 if jni == 'forcecopy':
389 options_test += ' --runtime-option -Xjniopts:forcecopy'
390 elif jni == 'checkjni':
391 options_test += ' --runtime-option -Xcheck:jni'
392
393 if image == 'no-image':
394 options_test += ' --no-image'
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000395 elif image == 'multipicimage':
396 options_test += ' --multi-image'
397
398 if pictest == 'pictest':
399 options_test += ' --pic-test'
400
401 if debuggable == 'debuggable':
402 options_test += ' --debuggable'
403
404 if address_size == '64':
405 options_test += ' --64'
406
407 if env.DEX2OAT_HOST_INSTRUCTION_SET_FEATURES:
408 options_test += ' --instruction-set-features' + env.DEX2OAT_HOST_INSTRUCTION_SET_FEATURES
409
410 elif address_size == '32':
411 if env.HOST_2ND_ARCH_PREFIX_DEX2OAT_HOST_INSTRUCTION_SET_FEATURES:
412 options_test += ' --instruction-set-features ' + \
413 env.HOST_2ND_ARCH_PREFIX_DEX2OAT_HOST_INSTRUCTION_SET_FEATURES
414
415 options_test = (' --output-path %s/run-test-output/%s') % (
416 env.ART_HOST_TEST_DIR, test_name) + options_test
417
418 run_test_sh = env.ANDROID_BUILD_TOP + '/art/test/run-test'
419 command = run_test_sh + ' ' + options_test + ' ' + test
420
421 semaphore.acquire()
422 worker = threading.Thread(target=run_test, args=(command, test, variant_set, test_name))
423 worker.daemon = True
424 worker.start()
425
426 while threading.active_count() > 2:
427 time.sleep(0.1)
428
429
430def run_test(command, test, test_variant, test_name):
431 """Runs the test.
432
433 It invokes art/test/run-test script to run the test. The output of the script
434 is checked, and if it ends with "Succeeded!", it assumes that the tests
435 passed, otherwise, put it in the list of failed test. Before actually running
436 the test, it also checks if the test is placed in the list of disabled tests,
437 and if yes, it skips running it, and adds the test in the list of skipped
438 tests. The method uses print_text method to actually print the output. After
439 successfully running and capturing the output for the test, it releases the
440 semaphore object.
441
442 Args:
443 command: The command to be used to invoke the script
444 test: The name of the test without the variant information.
445 test_variant: The set of variant for the test.
446 test_name: The name of the test along with the variants.
447 """
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000448 global stop_testrunner
Shubham Ajmerabbd84332017-02-17 00:41:10 +0000449 try:
450 if is_test_disabled(test, test_variant):
451 test_skipped = True
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000452 else:
Shubham Ajmerabbd84332017-02-17 00:41:10 +0000453 test_skipped = False
454 proc = subprocess.Popen(command.split(), stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
455 script_output = proc.stdout.read().strip()
456 test_passed = not proc.wait()
457
458 if not test_skipped:
459 if test_passed:
460 print_test_info(test_name, 'PASS')
461 else:
462 failed_tests.append(test_name)
463 if not env.ART_TEST_KEEP_GOING:
464 stop_testrunner = True
465 print_test_info(test_name, 'FAIL', ('%s\n%s') % (
466 command, script_output))
467 elif not dry_run:
468 print_test_info(test_name, 'SKIP')
469 skipped_tests.append(test_name)
470 else:
471 print_test_info(test_name, '')
472 except Exception, e:
473 failed_tests.append(test_name)
474 print_text(('%s\n%s\n') % (command, str(e)))
475 finally:
476 semaphore.release()
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000477
478
Shubham Ajmera14d340c2017-02-15 18:49:10 +0000479def print_test_info(test_name, result, failed_test_info=""):
480 """Print the continous test information
481
482 If verbose is set to True, it continuously prints test status information
483 on a new line.
484 If verbose is set to False, it keeps on erasing test
485 information by overriding it with the latest test information. Also,
486 in this case it stictly makes sure that the information length doesn't
487 exceed the console width. It does so by shortening the test_name.
488
489 When a test fails, it prints the output of the run-test script and
490 command used to invoke the script. It doesn't override the failing
491 test information in either of the cases.
492 """
Shubham Ajmerabbd84332017-02-17 00:41:10 +0000493
Shubham Ajmera14d340c2017-02-15 18:49:10 +0000494 global test_count
495 info = ''
496 if not verbose:
497 # Without --verbose, the testrunner erases passing test info. It
498 # does that by overriding the printed text with white spaces all across
499 # the console width.
500 console_width = int(os.popen('stty size', 'r').read().split()[1])
501 info = '\r' + ' ' * console_width + '\r'
Shubham Ajmerabbd84332017-02-17 00:41:10 +0000502 try:
503 print_mutex.acquire()
504 test_count += 1
505 percent = (test_count * 100) / total_test_count
506 progress_info = ('[ %d%% %d/%d ]') % (
507 percent,
508 test_count,
509 total_test_count)
Shubham Ajmera14d340c2017-02-15 18:49:10 +0000510
Shubham Ajmerabbd84332017-02-17 00:41:10 +0000511 if result == "FAIL":
512 info += ('%s %s %s\n%s\n') % (
Shubham Ajmera14d340c2017-02-15 18:49:10 +0000513 progress_info,
514 test_name,
Shubham Ajmerabbd84332017-02-17 00:41:10 +0000515 COLOR_ERROR + 'FAIL' + COLOR_NORMAL,
516 failed_test_info)
517 else:
518 result_text = ''
519 if result == 'PASS':
520 result_text += COLOR_PASS + 'PASS' + COLOR_NORMAL
521 elif result == 'SKIP':
522 result_text += COLOR_SKIP + 'SKIP' + COLOR_NORMAL
523
524 if verbose:
525 info += ('%s %s %s\n') % (
526 progress_info,
527 test_name,
528 result_text)
529 else:
530 total_output_length = 2 # Two spaces
531 total_output_length += len(progress_info)
532 total_output_length += len(result)
533 allowed_test_length = console_width - total_output_length
534 test_name_len = len(test_name)
535 if allowed_test_length < test_name_len:
536 test_name = ('%s...%s') % (
537 test_name[:(allowed_test_length - 3)/2],
538 test_name[-(allowed_test_length - 3)/2:])
Alex Lightc14311c2017-02-23 17:02:46 -0800539 info += ('%s %s %s') % (
540 progress_info,
541 test_name,
542 result_text)
Shubham Ajmerabbd84332017-02-17 00:41:10 +0000543 print_text(info)
544 except Exception, e:
545 print_text(('%s\n%s\n') % (test_name, str(e)))
546 failed_tests.append(test_name)
547 finally:
548 print_mutex.release()
Shubham Ajmera14d340c2017-02-15 18:49:10 +0000549
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000550def get_disabled_test_info():
551 """Generate set of known failures.
552
553 It parses the art/test/knownfailures.json file to generate the list of
554 disabled tests.
555
556 Returns:
557 The method returns a dict of tests mapped to the variants list
558 for which the test should not be run.
559 """
560 known_failures_file = env.ANDROID_BUILD_TOP + '/art/test/knownfailures.json'
561 with open(known_failures_file) as known_failures_json:
562 known_failures_info = json.loads(known_failures_json.read())
563
564 disabled_test_info = {}
565 for failure in known_failures_info:
566 tests = failure.get('test')
567 if tests:
568 tests = [tests]
569 else:
570 tests = failure.get('tests', [])
571 variants = parse_variants(failure.get('variant'))
572 env_vars = failure.get('env_vars')
573 if check_env_vars(env_vars):
574 for test in tests:
575 if test in disabled_test_info:
576 disabled_test_info[test] = disabled_test_info[test].union(variants)
577 else:
578 disabled_test_info[test] = variants
579 return disabled_test_info
580
581
582def check_env_vars(env_vars):
583 """Checks if the env variables are set as required to run the test.
584
585 Returns:
586 True if all the env variables are set as required, otherwise False.
587 """
588
589 if not env_vars:
590 return True
591 for key in env_vars:
592 if env.get_env(key) != env_vars.get(key):
593 return False
594 return True
595
596
597def is_test_disabled(test, variant_set):
598 """Checks if the test along with the variant_set is disabled.
599
600 Args:
601 test: The name of the test as in art/test directory.
602 variant_set: Variants to be used for the test.
603 Returns:
604 True, if the test is disabled.
605 """
606 if dry_run:
607 return True
Alex Lightbc319b22017-02-17 14:21:33 -0800608 if test in env.EXTRA_DISABLED_TESTS:
609 return True
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000610 variants_list = DISABLED_TEST_CONTAINER.get(test, {})
611 for variants in variants_list:
612 variants_present = True
613 for variant in variants:
614 if variant not in variant_set:
615 variants_present = False
616 break
617 if variants_present:
618 return True
619 return False
620
621
622def parse_variants(variants):
623 """Parse variants fetched from art/test/knownfailures.json.
624 """
625 if not variants:
626 variants = ''
627 for variant in TOTAL_VARIANTS_SET:
628 variants += variant
629 variants += '|'
630 variants = variants[:-1]
631 variant_list = set()
632 or_variants = variants.split('|')
633 for or_variant in or_variants:
634 and_variants = or_variant.split('&')
635 variant = set()
636 for and_variant in and_variants:
637 and_variant = and_variant.strip()
638 variant.add(and_variant)
639 variant_list.add(frozenset(variant))
640 return variant_list
641
642def print_text(output):
643 sys.stdout.write(output)
644 sys.stdout.flush()
645
646def print_analysis():
647 if not verbose:
Shubham Ajmera14d340c2017-02-15 18:49:10 +0000648 # Without --verbose, the testrunner erases passing test info. It
649 # does that by overriding the printed text with white spaces all across
650 # the console width.
651 console_width = int(os.popen('stty size', 'r').read().split()[1])
652 eraser_text = '\r' + ' ' * console_width + '\r'
653 print_text(eraser_text)
Shubham Ajmeracbf56282017-03-13 09:54:23 -0700654
655 # Prints information about the total tests run.
656 # E.g., "2/38 (5%) tests passed".
657 passed_test_count = total_test_count - len(skipped_tests) - len(failed_tests)
658 passed_test_information = ('%d/%d (%d%%) %s passed.\n') % (
659 passed_test_count,
660 total_test_count,
661 (passed_test_count*100)/total_test_count,
662 'tests' if passed_test_count > 1 else 'test')
663 print_text(passed_test_information)
664
665 # Prints the list of skipped tests, if any.
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000666 if skipped_tests:
667 print_text(COLOR_SKIP + 'SKIPPED TESTS' + COLOR_NORMAL + '\n')
668 for test in skipped_tests:
669 print_text(test + '\n')
670 print_text('\n')
671
Shubham Ajmeracbf56282017-03-13 09:54:23 -0700672 # Prints the list of failed tests, if any.
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000673 if failed_tests:
674 print_text(COLOR_ERROR + 'FAILED TESTS' + COLOR_NORMAL + '\n')
675 for test in failed_tests:
676 print_text(test + '\n')
677
678
679def parse_test_name(test_name):
680 """Parses the testname provided by the user.
681 It supports two types of test_name:
682 1) Like 001-HelloWorld. In this case, it will just verify if the test actually
683 exists and if it does, it returns the testname.
684 2) Like test-art-host-run-test-debug-prebuild-interpreter-no-relocate-ntrace-cms-checkjni-picimage-npictest-ndebuggable-001-HelloWorld32
685 In this case, it will parse all the variants and check if they are placed
686 correctly. If yes, it will set the various VARIANT_TYPES to use the
687 variants required to run the test. Again, it returns the test_name
688 without the variant information like 001-HelloWorld.
689 """
Shubham Ajmerafaf12502017-02-15 17:19:44 +0000690 test_set = set()
691 for test in RUN_TEST_SET:
692 if test.startswith(test_name):
693 test_set.add(test)
694 if test_set:
695 return test_set
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000696
697 regex = '^test-art-'
698 regex += '(' + '|'.join(VARIANT_TYPE_DICT['target']) + ')-'
699 regex += 'run-test-'
700 regex += '(' + '|'.join(VARIANT_TYPE_DICT['run']) + ')-'
701 regex += '(' + '|'.join(VARIANT_TYPE_DICT['prebuild']) + ')-'
702 regex += '(' + '|'.join(VARIANT_TYPE_DICT['compiler']) + ')-'
703 regex += '(' + '|'.join(VARIANT_TYPE_DICT['relocate']) + ')-'
704 regex += '(' + '|'.join(VARIANT_TYPE_DICT['trace']) + ')-'
705 regex += '(' + '|'.join(VARIANT_TYPE_DICT['gc']) + ')-'
706 regex += '(' + '|'.join(VARIANT_TYPE_DICT['jni']) + ')-'
707 regex += '(' + '|'.join(VARIANT_TYPE_DICT['image']) + ')-'
708 regex += '(' + '|'.join(VARIANT_TYPE_DICT['pictest']) + ')-'
709 regex += '(' + '|'.join(VARIANT_TYPE_DICT['debuggable']) + ')-'
710 regex += '(' + '|'.join(RUN_TEST_SET) + ')'
711 regex += '(' + '|'.join(VARIANT_TYPE_DICT['address_sizes']) + ')$'
712 match = re.match(regex, test_name)
713 if match:
714 TARGET_TYPES.add(match.group(1))
715 RUN_TYPES.add(match.group(2))
716 PREBUILD_TYPES.add(match.group(3))
717 COMPILER_TYPES.add(match.group(4))
718 RELOCATE_TYPES.add(match.group(5))
719 TRACE_TYPES.add(match.group(6))
720 GC_TYPES.add(match.group(7))
721 JNI_TYPES.add(match.group(8))
722 IMAGE_TYPES.add(match.group(9))
723 PICTEST_TYPES.add(match.group(10))
724 DEBUGGABLE_TYPES.add(match.group(11))
725 ADDRESS_SIZES.add(match.group(13))
726 return {match.group(12)}
Shubham Ajmerafaf12502017-02-15 17:19:44 +0000727 raise ValueError(test_name + " is not a valid test")
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000728
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800729
730def setup_env_for_build_target(build_target, parser, options):
731 """Setup environment for the build target
732
733 The method setup environment for the master-art-host targets.
734 """
735 os.environ.update(build_target['env'])
736 os.environ['SOONG_ALLOW_MISSING_DEPENDENCIES'] = 'true'
737 print_text('%s\n' % (str(os.environ)))
738
739 target_options = vars(parser.parse_args(build_target['flags']))
740 target_options['host'] = True
741 target_options['verbose'] = True
742 target_options['build'] = True
743 target_options['n_thread'] = options['n_thread']
744 target_options['dry_run'] = options['dry_run']
745
746 return target_options
747
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000748def parse_option():
749 global verbose
750 global dry_run
751 global n_thread
752 global build
753 global gdb
754 global gdb_arg
755
Alex Light7a1ccf82017-02-21 09:52:34 -0800756 parser = argparse.ArgumentParser(description="Runs all or a subset of the ART test suite.")
757 parser.add_argument('-t', '--test', dest='test', help='name of the test')
758 parser.add_argument('-j', type=int, dest='n_thread')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000759 for variant in TOTAL_VARIANTS_SET:
760 flag = '--' + variant
761 flag_dest = variant.replace('-', '_')
762 if variant == '32' or variant == '64':
763 flag_dest = 'n' + flag_dest
Alex Light7a1ccf82017-02-21 09:52:34 -0800764 parser.add_argument(flag, action='store_true', dest=flag_dest)
765 parser.add_argument('--verbose', '-v', action='store_true', dest='verbose')
766 parser.add_argument('--dry-run', action='store_true', dest='dry_run')
767 parser.add_argument("--skip", action="append", dest="skips", default=[],
768 help="Skip the given test in all circumstances.")
Alex Light9b6b13e2017-02-22 11:46:50 -0800769 parser.add_argument('--no-build-dependencies',
770 action='store_false', dest='build',
771 help="Don't build dependencies under any circumstances. This is the " +
772 "behavior if ART_TEST_RUN_TEST_ALWAYS_BUILD is not set to 'true'.")
773 parser.add_argument('-b', '--build-dependencies',
774 action='store_true', dest='build',
775 help="Build dependencies under all circumstances. By default we will " +
776 "not build dependencies unless ART_TEST_RUN_TEST_BUILD=true.")
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800777 parser.add_argument('--build-target', dest='build_target', help='master-art-host targets')
Alex Light9b6b13e2017-02-22 11:46:50 -0800778 parser.set_defaults(build = env.ART_TEST_RUN_TEST_BUILD)
Alex Light7a1ccf82017-02-21 09:52:34 -0800779 parser.add_argument('--gdb', action='store_true', dest='gdb')
780 parser.add_argument('--gdb-arg', dest='gdb_arg')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000781
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800782 options = vars(parser.parse_args())
783 if options['build_target']:
784 options = setup_env_for_build_target(target_config[options['build_target']],
785 parser, options)
786
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000787 test = ''
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800788 env.EXTRA_DISABLED_TESTS.update(set(options['skips']))
789 if options['test']:
790 test = parse_test_name(options['test'])
791 if options['pictest']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000792 PICTEST_TYPES.add('pictest')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800793 if options['ndebug']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000794 RUN_TYPES.add('ndebug')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800795 if options['interp_ac']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000796 COMPILER_TYPES.add('interp-ac')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800797 if options['picimage']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000798 IMAGE_TYPES.add('picimage')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800799 if options['n64']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000800 ADDRESS_SIZES.add('64')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800801 if options['interpreter']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000802 COMPILER_TYPES.add('interpreter')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800803 if options['jni']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000804 JNI_TYPES.add('jni')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800805 if options['relocate_npatchoat']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000806 RELOCATE_TYPES.add('relocate-npatchoat')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800807 if options['no_prebuild']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000808 PREBUILD_TYPES.add('no-prebuild')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800809 if options['npictest']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000810 PICTEST_TYPES.add('npictest')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800811 if options['no_dex2oat']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000812 PREBUILD_TYPES.add('no-dex2oat')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800813 if options['jit']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000814 COMPILER_TYPES.add('jit')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800815 if options['relocate']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000816 RELOCATE_TYPES.add('relocate')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800817 if options['ndebuggable']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000818 DEBUGGABLE_TYPES.add('ndebuggable')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800819 if options['no_image']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000820 IMAGE_TYPES.add('no-image')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800821 if options['optimizing']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000822 COMPILER_TYPES.add('optimizing')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800823 if options['trace']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000824 TRACE_TYPES.add('trace')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800825 if options['gcstress']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000826 GC_TYPES.add('gcstress')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800827 if options['no_relocate']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000828 RELOCATE_TYPES.add('no-relocate')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800829 if options['target']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000830 TARGET_TYPES.add('target')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800831 if options['forcecopy']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000832 JNI_TYPES.add('forcecopy')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800833 if options['n32']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000834 ADDRESS_SIZES.add('32')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800835 if options['host']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000836 TARGET_TYPES.add('host')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800837 if options['gcverify']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000838 GC_TYPES.add('gcverify')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800839 if options['debuggable']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000840 DEBUGGABLE_TYPES.add('debuggable')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800841 if options['prebuild']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000842 PREBUILD_TYPES.add('prebuild')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800843 if options['debug']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000844 RUN_TYPES.add('debug')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800845 if options['checkjni']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000846 JNI_TYPES.add('checkjni')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800847 if options['ntrace']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000848 TRACE_TYPES.add('ntrace')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800849 if options['cms']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000850 GC_TYPES.add('cms')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800851 if options['multipicimage']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000852 IMAGE_TYPES.add('multipicimage')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800853 if options['verbose']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000854 verbose = True
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800855 if options['n_thread']:
856 n_thread = max(1, options['n_thread'])
857 if options['dry_run']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000858 dry_run = True
859 verbose = True
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800860 build = options['build']
861 if options['gdb']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000862 n_thread = 1
863 gdb = True
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800864 if options['gdb_arg']:
865 gdb_arg = options['gdb_arg']
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000866
867 return test
868
869def main():
870 gather_test_info()
871 user_requested_test = parse_option()
872 setup_test_env()
873 if build:
874 build_targets = ''
875 if 'host' in TARGET_TYPES:
876 build_targets += 'test-art-host-run-test-dependencies'
877 if 'target' in TARGET_TYPES:
878 build_targets += 'test-art-target-run-test-dependencies'
Shubham Ajmera06cde292017-02-10 23:15:05 +0000879 build_command = 'make'
880 build_command += ' -j' + str(n_thread)
881 build_command += ' -C ' + env.ANDROID_BUILD_TOP
882 build_command += ' ' + build_targets
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000883 if subprocess.call(build_command.split()):
884 sys.exit(1)
885 if user_requested_test:
886 test_runner_thread = threading.Thread(target=run_tests, args=(user_requested_test,))
887 else:
888 test_runner_thread = threading.Thread(target=run_tests, args=(RUN_TEST_SET,))
889 test_runner_thread.daemon = True
890 try:
891 test_runner_thread.start()
892 while threading.active_count() > 1:
893 time.sleep(0.1)
894 print_analysis()
Shubham Ajmerafaf12502017-02-15 17:19:44 +0000895 except Exception, e:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000896 print_analysis()
Shubham Ajmerafaf12502017-02-15 17:19:44 +0000897 print_text(str(e))
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000898 sys.exit(1)
Shubham Ajmerac5aae872017-02-16 19:58:59 +0000899 if failed_tests:
900 sys.exit(1)
901 sys.exit(0)
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000902
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000903if __name__ == '__main__':
904 main()