blob: a5504098d8914722841c53258082bf9f0b311241 [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 Ajmera14de5c42017-03-13 10:51:14 -0700550def verify_knownfailure_entry(entry):
551 supported_field = {
552 'tests' : (list, unicode),
553 'description' : (list, unicode),
554 'bug' : (unicode,),
555 'variant' : (unicode,),
556 'env_vars' : (dict,),
557 }
558 for field in entry:
559 field_type = type(entry[field])
560 if field_type not in supported_field[field]:
561 raise ValueError('%s is not supported type for %s\n%s' % (
562 str(field_type),
563 field,
564 str(entry)))
565
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000566def get_disabled_test_info():
567 """Generate set of known failures.
568
569 It parses the art/test/knownfailures.json file to generate the list of
570 disabled tests.
571
572 Returns:
573 The method returns a dict of tests mapped to the variants list
574 for which the test should not be run.
575 """
576 known_failures_file = env.ANDROID_BUILD_TOP + '/art/test/knownfailures.json'
577 with open(known_failures_file) as known_failures_json:
578 known_failures_info = json.loads(known_failures_json.read())
579
580 disabled_test_info = {}
581 for failure in known_failures_info:
Shubham Ajmera14de5c42017-03-13 10:51:14 -0700582 verify_knownfailure_entry(failure)
583 tests = failure.get('tests', [])
584 if isinstance(tests, unicode):
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000585 tests = [tests]
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000586 variants = parse_variants(failure.get('variant'))
587 env_vars = failure.get('env_vars')
Shubham Ajmera14de5c42017-03-13 10:51:14 -0700588
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000589 if check_env_vars(env_vars):
590 for test in tests:
Shubham Ajmera14de5c42017-03-13 10:51:14 -0700591 if test not in RUN_TEST_SET:
592 raise ValueError('%s is not a valid run-test' % (
593 test))
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000594 if test in disabled_test_info:
595 disabled_test_info[test] = disabled_test_info[test].union(variants)
596 else:
597 disabled_test_info[test] = variants
598 return disabled_test_info
599
600
601def check_env_vars(env_vars):
602 """Checks if the env variables are set as required to run the test.
603
604 Returns:
605 True if all the env variables are set as required, otherwise False.
606 """
607
608 if not env_vars:
609 return True
610 for key in env_vars:
611 if env.get_env(key) != env_vars.get(key):
612 return False
613 return True
614
615
616def is_test_disabled(test, variant_set):
617 """Checks if the test along with the variant_set is disabled.
618
619 Args:
620 test: The name of the test as in art/test directory.
621 variant_set: Variants to be used for the test.
622 Returns:
623 True, if the test is disabled.
624 """
625 if dry_run:
626 return True
Alex Lightbc319b22017-02-17 14:21:33 -0800627 if test in env.EXTRA_DISABLED_TESTS:
628 return True
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000629 variants_list = DISABLED_TEST_CONTAINER.get(test, {})
630 for variants in variants_list:
631 variants_present = True
632 for variant in variants:
633 if variant not in variant_set:
634 variants_present = False
635 break
636 if variants_present:
637 return True
638 return False
639
640
641def parse_variants(variants):
642 """Parse variants fetched from art/test/knownfailures.json.
643 """
644 if not variants:
645 variants = ''
646 for variant in TOTAL_VARIANTS_SET:
647 variants += variant
648 variants += '|'
649 variants = variants[:-1]
650 variant_list = set()
651 or_variants = variants.split('|')
652 for or_variant in or_variants:
653 and_variants = or_variant.split('&')
654 variant = set()
655 for and_variant in and_variants:
656 and_variant = and_variant.strip()
Shubham Ajmera14de5c42017-03-13 10:51:14 -0700657 if and_variant not in TOTAL_VARIANTS_SET:
658 raise ValueError('%s is not a valid variant' % (
659 and_variant))
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000660 variant.add(and_variant)
661 variant_list.add(frozenset(variant))
662 return variant_list
663
664def print_text(output):
665 sys.stdout.write(output)
666 sys.stdout.flush()
667
668def print_analysis():
669 if not verbose:
Shubham Ajmera14d340c2017-02-15 18:49:10 +0000670 # Without --verbose, the testrunner erases passing test info. It
671 # does that by overriding the printed text with white spaces all across
672 # the console width.
673 console_width = int(os.popen('stty size', 'r').read().split()[1])
674 eraser_text = '\r' + ' ' * console_width + '\r'
675 print_text(eraser_text)
Shubham Ajmeracbf56282017-03-13 09:54:23 -0700676
677 # Prints information about the total tests run.
678 # E.g., "2/38 (5%) tests passed".
679 passed_test_count = total_test_count - len(skipped_tests) - len(failed_tests)
680 passed_test_information = ('%d/%d (%d%%) %s passed.\n') % (
681 passed_test_count,
682 total_test_count,
683 (passed_test_count*100)/total_test_count,
684 'tests' if passed_test_count > 1 else 'test')
685 print_text(passed_test_information)
686
687 # Prints the list of skipped tests, if any.
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000688 if skipped_tests:
689 print_text(COLOR_SKIP + 'SKIPPED TESTS' + COLOR_NORMAL + '\n')
690 for test in skipped_tests:
691 print_text(test + '\n')
692 print_text('\n')
693
Shubham Ajmeracbf56282017-03-13 09:54:23 -0700694 # Prints the list of failed tests, if any.
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000695 if failed_tests:
696 print_text(COLOR_ERROR + 'FAILED TESTS' + COLOR_NORMAL + '\n')
697 for test in failed_tests:
698 print_text(test + '\n')
699
700
701def parse_test_name(test_name):
702 """Parses the testname provided by the user.
703 It supports two types of test_name:
704 1) Like 001-HelloWorld. In this case, it will just verify if the test actually
705 exists and if it does, it returns the testname.
706 2) Like test-art-host-run-test-debug-prebuild-interpreter-no-relocate-ntrace-cms-checkjni-picimage-npictest-ndebuggable-001-HelloWorld32
707 In this case, it will parse all the variants and check if they are placed
708 correctly. If yes, it will set the various VARIANT_TYPES to use the
709 variants required to run the test. Again, it returns the test_name
710 without the variant information like 001-HelloWorld.
711 """
Shubham Ajmerafaf12502017-02-15 17:19:44 +0000712 test_set = set()
713 for test in RUN_TEST_SET:
714 if test.startswith(test_name):
715 test_set.add(test)
716 if test_set:
717 return test_set
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000718
719 regex = '^test-art-'
720 regex += '(' + '|'.join(VARIANT_TYPE_DICT['target']) + ')-'
721 regex += 'run-test-'
722 regex += '(' + '|'.join(VARIANT_TYPE_DICT['run']) + ')-'
723 regex += '(' + '|'.join(VARIANT_TYPE_DICT['prebuild']) + ')-'
724 regex += '(' + '|'.join(VARIANT_TYPE_DICT['compiler']) + ')-'
725 regex += '(' + '|'.join(VARIANT_TYPE_DICT['relocate']) + ')-'
726 regex += '(' + '|'.join(VARIANT_TYPE_DICT['trace']) + ')-'
727 regex += '(' + '|'.join(VARIANT_TYPE_DICT['gc']) + ')-'
728 regex += '(' + '|'.join(VARIANT_TYPE_DICT['jni']) + ')-'
729 regex += '(' + '|'.join(VARIANT_TYPE_DICT['image']) + ')-'
730 regex += '(' + '|'.join(VARIANT_TYPE_DICT['pictest']) + ')-'
731 regex += '(' + '|'.join(VARIANT_TYPE_DICT['debuggable']) + ')-'
732 regex += '(' + '|'.join(RUN_TEST_SET) + ')'
733 regex += '(' + '|'.join(VARIANT_TYPE_DICT['address_sizes']) + ')$'
734 match = re.match(regex, test_name)
735 if match:
736 TARGET_TYPES.add(match.group(1))
737 RUN_TYPES.add(match.group(2))
738 PREBUILD_TYPES.add(match.group(3))
739 COMPILER_TYPES.add(match.group(4))
740 RELOCATE_TYPES.add(match.group(5))
741 TRACE_TYPES.add(match.group(6))
742 GC_TYPES.add(match.group(7))
743 JNI_TYPES.add(match.group(8))
744 IMAGE_TYPES.add(match.group(9))
745 PICTEST_TYPES.add(match.group(10))
746 DEBUGGABLE_TYPES.add(match.group(11))
747 ADDRESS_SIZES.add(match.group(13))
748 return {match.group(12)}
Shubham Ajmerafaf12502017-02-15 17:19:44 +0000749 raise ValueError(test_name + " is not a valid test")
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000750
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800751
752def setup_env_for_build_target(build_target, parser, options):
753 """Setup environment for the build target
754
755 The method setup environment for the master-art-host targets.
756 """
757 os.environ.update(build_target['env'])
758 os.environ['SOONG_ALLOW_MISSING_DEPENDENCIES'] = 'true'
759 print_text('%s\n' % (str(os.environ)))
760
761 target_options = vars(parser.parse_args(build_target['flags']))
762 target_options['host'] = True
763 target_options['verbose'] = True
764 target_options['build'] = True
765 target_options['n_thread'] = options['n_thread']
766 target_options['dry_run'] = options['dry_run']
767
768 return target_options
769
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000770def parse_option():
771 global verbose
772 global dry_run
773 global n_thread
774 global build
775 global gdb
776 global gdb_arg
777
Alex Light7a1ccf82017-02-21 09:52:34 -0800778 parser = argparse.ArgumentParser(description="Runs all or a subset of the ART test suite.")
779 parser.add_argument('-t', '--test', dest='test', help='name of the test')
780 parser.add_argument('-j', type=int, dest='n_thread')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000781 for variant in TOTAL_VARIANTS_SET:
782 flag = '--' + variant
783 flag_dest = variant.replace('-', '_')
784 if variant == '32' or variant == '64':
785 flag_dest = 'n' + flag_dest
Alex Light7a1ccf82017-02-21 09:52:34 -0800786 parser.add_argument(flag, action='store_true', dest=flag_dest)
787 parser.add_argument('--verbose', '-v', action='store_true', dest='verbose')
788 parser.add_argument('--dry-run', action='store_true', dest='dry_run')
789 parser.add_argument("--skip", action="append", dest="skips", default=[],
790 help="Skip the given test in all circumstances.")
Alex Light9b6b13e2017-02-22 11:46:50 -0800791 parser.add_argument('--no-build-dependencies',
792 action='store_false', dest='build',
793 help="Don't build dependencies under any circumstances. This is the " +
794 "behavior if ART_TEST_RUN_TEST_ALWAYS_BUILD is not set to 'true'.")
795 parser.add_argument('-b', '--build-dependencies',
796 action='store_true', dest='build',
797 help="Build dependencies under all circumstances. By default we will " +
798 "not build dependencies unless ART_TEST_RUN_TEST_BUILD=true.")
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800799 parser.add_argument('--build-target', dest='build_target', help='master-art-host targets')
Alex Light9b6b13e2017-02-22 11:46:50 -0800800 parser.set_defaults(build = env.ART_TEST_RUN_TEST_BUILD)
Alex Light7a1ccf82017-02-21 09:52:34 -0800801 parser.add_argument('--gdb', action='store_true', dest='gdb')
802 parser.add_argument('--gdb-arg', dest='gdb_arg')
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000803
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800804 options = vars(parser.parse_args())
805 if options['build_target']:
806 options = setup_env_for_build_target(target_config[options['build_target']],
807 parser, options)
808
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000809 test = ''
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800810 env.EXTRA_DISABLED_TESTS.update(set(options['skips']))
811 if options['test']:
812 test = parse_test_name(options['test'])
813 if options['pictest']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000814 PICTEST_TYPES.add('pictest')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800815 if options['ndebug']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000816 RUN_TYPES.add('ndebug')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800817 if options['interp_ac']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000818 COMPILER_TYPES.add('interp-ac')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800819 if options['picimage']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000820 IMAGE_TYPES.add('picimage')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800821 if options['n64']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000822 ADDRESS_SIZES.add('64')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800823 if options['interpreter']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000824 COMPILER_TYPES.add('interpreter')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800825 if options['jni']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000826 JNI_TYPES.add('jni')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800827 if options['relocate_npatchoat']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000828 RELOCATE_TYPES.add('relocate-npatchoat')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800829 if options['no_prebuild']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000830 PREBUILD_TYPES.add('no-prebuild')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800831 if options['npictest']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000832 PICTEST_TYPES.add('npictest')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800833 if options['no_dex2oat']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000834 PREBUILD_TYPES.add('no-dex2oat')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800835 if options['jit']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000836 COMPILER_TYPES.add('jit')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800837 if options['relocate']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000838 RELOCATE_TYPES.add('relocate')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800839 if options['ndebuggable']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000840 DEBUGGABLE_TYPES.add('ndebuggable')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800841 if options['no_image']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000842 IMAGE_TYPES.add('no-image')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800843 if options['optimizing']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000844 COMPILER_TYPES.add('optimizing')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800845 if options['trace']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000846 TRACE_TYPES.add('trace')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800847 if options['gcstress']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000848 GC_TYPES.add('gcstress')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800849 if options['no_relocate']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000850 RELOCATE_TYPES.add('no-relocate')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800851 if options['target']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000852 TARGET_TYPES.add('target')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800853 if options['forcecopy']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000854 JNI_TYPES.add('forcecopy')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800855 if options['n32']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000856 ADDRESS_SIZES.add('32')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800857 if options['host']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000858 TARGET_TYPES.add('host')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800859 if options['gcverify']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000860 GC_TYPES.add('gcverify')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800861 if options['debuggable']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000862 DEBUGGABLE_TYPES.add('debuggable')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800863 if options['prebuild']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000864 PREBUILD_TYPES.add('prebuild')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800865 if options['debug']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000866 RUN_TYPES.add('debug')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800867 if options['checkjni']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000868 JNI_TYPES.add('checkjni')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800869 if options['ntrace']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000870 TRACE_TYPES.add('ntrace')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800871 if options['cms']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000872 GC_TYPES.add('cms')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800873 if options['multipicimage']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000874 IMAGE_TYPES.add('multipicimage')
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800875 if options['verbose']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000876 verbose = True
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800877 if options['n_thread']:
878 n_thread = max(1, options['n_thread'])
879 if options['dry_run']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000880 dry_run = True
881 verbose = True
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800882 build = options['build']
883 if options['gdb']:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000884 n_thread = 1
885 gdb = True
Shubham Ajmerab9d09ca2017-03-07 10:45:05 -0800886 if options['gdb_arg']:
887 gdb_arg = options['gdb_arg']
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000888
889 return test
890
891def main():
892 gather_test_info()
893 user_requested_test = parse_option()
894 setup_test_env()
895 if build:
896 build_targets = ''
897 if 'host' in TARGET_TYPES:
898 build_targets += 'test-art-host-run-test-dependencies'
899 if 'target' in TARGET_TYPES:
900 build_targets += 'test-art-target-run-test-dependencies'
Shubham Ajmera06cde292017-02-10 23:15:05 +0000901 build_command = 'make'
902 build_command += ' -j' + str(n_thread)
903 build_command += ' -C ' + env.ANDROID_BUILD_TOP
904 build_command += ' ' + build_targets
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000905 if subprocess.call(build_command.split()):
906 sys.exit(1)
907 if user_requested_test:
908 test_runner_thread = threading.Thread(target=run_tests, args=(user_requested_test,))
909 else:
910 test_runner_thread = threading.Thread(target=run_tests, args=(RUN_TEST_SET,))
911 test_runner_thread.daemon = True
912 try:
913 test_runner_thread.start()
914 while threading.active_count() > 1:
915 time.sleep(0.1)
916 print_analysis()
Shubham Ajmerafaf12502017-02-15 17:19:44 +0000917 except Exception, e:
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000918 print_analysis()
Shubham Ajmerafaf12502017-02-15 17:19:44 +0000919 print_text(str(e))
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000920 sys.exit(1)
Shubham Ajmerac5aae872017-02-16 19:58:59 +0000921 if failed_tests:
922 sys.exit(1)
923 sys.exit(0)
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000924
Shubham Ajmera65adb8b2017-02-06 16:04:25 +0000925if __name__ == '__main__':
926 main()