blob: d68d1f86bdd80cfff1bff70e2928ead790c4e136 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001#!/usr/bin/env python
2#
3# Copyright 2012 the V8 project authors. All rights reserved.
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met:
7#
8# * Redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer.
10# * Redistributions in binary form must reproduce the above
11# copyright notice, this list of conditions and the following
12# disclaimer in the documentation and/or other materials provided
13# with the distribution.
14# * Neither the name of Google Inc. nor the names of its
15# contributors may be used to endorse or promote products derived
16# from this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30
31from collections import OrderedDict
32import itertools
33import multiprocessing
34import optparse
35import os
36from os.path import join
37import platform
38import random
39import shlex
40import subprocess
41import sys
42import time
43
44from testrunner.local import execution
45from testrunner.local import progress
46from testrunner.local import testsuite
Emily Bernierd0a1eb72015-03-24 16:35:39 -040047from testrunner.local.testsuite import VARIANT_FLAGS
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048from testrunner.local import utils
49from testrunner.local import verbose
50from testrunner.network import network_execution
51from testrunner.objects import context
52
53
54ARCH_GUESS = utils.DefaultArch()
Emily Bernierd0a1eb72015-03-24 16:35:39 -040055DEFAULT_TESTS = [
56 "mjsunit",
57 "unittests",
58 "cctest",
59 "message",
60 "preparser",
61]
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062
63# Map of test name synonyms to lists of test suites. Should be ordered by
64# expected runtimes (suites with slow test cases first). These groups are
65# invoked in seperate steps on the bots.
66TEST_MAP = {
67 "default": [
68 "mjsunit",
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 "cctest",
70 "message",
71 "preparser",
72 ],
73 "optimize_for_size": [
74 "mjsunit",
75 "cctest",
76 "webkit",
77 ],
78 "unittests": [
Emily Bernierd0a1eb72015-03-24 16:35:39 -040079 "unittests",
Ben Murdochb8a8cc12014-11-26 15:28:44 +000080 ],
81}
82
83TIMEOUT_DEFAULT = 60
84TIMEOUT_SCALEFACTOR = {"debug" : 4,
85 "release" : 1 }
86
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087VARIANTS = ["default", "stress", "turbofan", "nocrankshaft"]
88
89MODE_FLAGS = {
90 "debug" : ["--nohard-abort", "--nodead-code-elimination",
91 "--nofold-constants", "--enable-slow-asserts",
92 "--debug-code", "--verify-heap"],
93 "release" : ["--nohard-abort", "--nodead-code-elimination",
94 "--nofold-constants"]}
95
96GC_STRESS_FLAGS = ["--gc-interval=500", "--stress-compaction",
97 "--concurrent-recompilation-queue-length=64",
98 "--concurrent-recompilation-delay=500",
99 "--concurrent-recompilation"]
100
101SUPPORTED_ARCHS = ["android_arm",
102 "android_arm64",
103 "android_ia32",
104 "arm",
105 "ia32",
106 "x87",
107 "mips",
108 "mipsel",
109 "mips64el",
110 "nacl_ia32",
111 "nacl_x64",
112 "x64",
113 "x32",
114 "arm64"]
115# Double the timeout for these:
116SLOW_ARCHS = ["android_arm",
117 "android_arm64",
118 "android_ia32",
119 "arm",
120 "mips",
121 "mipsel",
122 "mips64el",
123 "nacl_ia32",
124 "nacl_x64",
125 "x87",
126 "arm64"]
127
128
129def BuildOptions():
130 result = optparse.OptionParser()
131 result.add_option("--arch",
132 help=("The architecture to run tests for, "
133 "'auto' or 'native' for auto-detect"),
134 default="ia32,x64,arm")
135 result.add_option("--arch-and-mode",
136 help="Architecture and mode in the format 'arch.mode'",
137 default=None)
138 result.add_option("--asan",
139 help="Regard test expectations for ASAN",
140 default=False, action="store_true")
141 result.add_option("--buildbot",
142 help="Adapt to path structure used on buildbots",
143 default=False, action="store_true")
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400144 result.add_option("--dcheck-always-on",
145 help="Indicates that V8 was compiled with DCHECKs enabled",
146 default=False, action="store_true")
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147 result.add_option("--cat", help="Print the source of the tests",
148 default=False, action="store_true")
149 result.add_option("--flaky-tests",
150 help="Regard tests marked as flaky (run|skip|dontcare)",
151 default="dontcare")
152 result.add_option("--slow-tests",
153 help="Regard slow tests (run|skip|dontcare)",
154 default="dontcare")
155 result.add_option("--pass-fail-tests",
156 help="Regard pass|fail tests (run|skip|dontcare)",
157 default="dontcare")
158 result.add_option("--gc-stress",
159 help="Switch on GC stress mode",
160 default=False, action="store_true")
161 result.add_option("--command-prefix",
162 help="Prepended to each shell command used to run a test",
163 default="")
164 result.add_option("--download-data", help="Download missing test suite data",
165 default=False, action="store_true")
166 result.add_option("--extra-flags",
167 help="Additional flags to pass to each test command",
168 default="")
169 result.add_option("--isolates", help="Whether to test isolates",
170 default=False, action="store_true")
171 result.add_option("-j", help="The number of parallel tasks to run",
172 default=0, type="int")
173 result.add_option("-m", "--mode",
174 help="The test modes in which to run (comma-separated)",
175 default="release,debug")
176 result.add_option("--no-i18n", "--noi18n",
177 help="Skip internationalization tests",
178 default=False, action="store_true")
179 result.add_option("--no-network", "--nonetwork",
180 help="Don't distribute tests on the network",
181 default=(utils.GuessOS() != "linux"),
182 dest="no_network", action="store_true")
183 result.add_option("--no-presubmit", "--nopresubmit",
184 help='Skip presubmit checks',
185 default=False, dest="no_presubmit", action="store_true")
186 result.add_option("--no-snap", "--nosnap",
187 help='Test a build compiled without snapshot.',
188 default=False, dest="no_snap", action="store_true")
189 result.add_option("--no-sorting", "--nosorting",
190 help="Don't sort tests according to duration of last run.",
191 default=False, dest="no_sorting", action="store_true")
192 result.add_option("--no-stress", "--nostress",
193 help="Don't run crankshaft --always-opt --stress-op test",
194 default=False, dest="no_stress", action="store_true")
195 result.add_option("--no-variants", "--novariants",
196 help="Don't run any testing variants",
197 default=False, dest="no_variants", action="store_true")
198 result.add_option("--variants",
199 help="Comma-separated list of testing variants")
200 result.add_option("--outdir", help="Base directory with compile output",
201 default="out")
202 result.add_option("--predictable",
203 help="Compare output of several reruns of each test",
204 default=False, action="store_true")
205 result.add_option("-p", "--progress",
206 help=("The style of progress indicator"
207 " (verbose, dots, color, mono)"),
208 choices=progress.PROGRESS_INDICATORS.keys(), default="mono")
209 result.add_option("--quickcheck", default=False, action="store_true",
210 help=("Quick check mode (skip slow/flaky tests)"))
211 result.add_option("--report", help="Print a summary of the tests to be run",
212 default=False, action="store_true")
213 result.add_option("--json-test-results",
214 help="Path to a file for storing json results.")
215 result.add_option("--rerun-failures-count",
216 help=("Number of times to rerun each failing test case. "
217 "Very slow tests will be rerun only once."),
218 default=0, type="int")
219 result.add_option("--rerun-failures-max",
220 help="Maximum number of failing test cases to rerun.",
221 default=100, type="int")
222 result.add_option("--shard-count",
223 help="Split testsuites into this number of shards",
224 default=1, type="int")
225 result.add_option("--shard-run",
226 help="Run this shard from the split up tests.",
227 default=1, type="int")
228 result.add_option("--shell", help="DEPRECATED! use --shell-dir", default="")
229 result.add_option("--shell-dir", help="Directory containing executables",
230 default="")
231 result.add_option("--dont-skip-slow-simulator-tests",
232 help="Don't skip more slow tests when using a simulator.",
233 default=False, action="store_true",
234 dest="dont_skip_simulator_slow_tests")
235 result.add_option("--stress-only",
236 help="Only run tests with --always-opt --stress-opt",
237 default=False, action="store_true")
238 result.add_option("--time", help="Print timing information after running",
239 default=False, action="store_true")
240 result.add_option("-t", "--timeout", help="Timeout in seconds",
241 default= -1, type="int")
242 result.add_option("--tsan",
243 help="Regard test expectations for TSAN",
244 default=False, action="store_true")
245 result.add_option("-v", "--verbose", help="Verbose output",
246 default=False, action="store_true")
247 result.add_option("--valgrind", help="Run tests through valgrind",
248 default=False, action="store_true")
249 result.add_option("--warn-unused", help="Report unused rules",
250 default=False, action="store_true")
251 result.add_option("--junitout", help="File name of the JUnit output")
252 result.add_option("--junittestsuite",
253 help="The testsuite name in the JUnit output file",
254 default="v8tests")
255 result.add_option("--random-seed", default=0, dest="random_seed",
256 help="Default seed for initializing random generator")
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400257 result.add_option("--msan",
258 help="Regard test expectations for MSAN",
259 default=False, action="store_true")
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260 return result
261
262
263def ProcessOptions(options):
264 global VARIANT_FLAGS
265 global VARIANTS
266
267 # Architecture and mode related stuff.
268 if options.arch_and_mode:
269 options.arch_and_mode = [arch_and_mode.split(".")
270 for arch_and_mode in options.arch_and_mode.split(",")]
271 options.arch = ",".join([tokens[0] for tokens in options.arch_and_mode])
272 options.mode = ",".join([tokens[1] for tokens in options.arch_and_mode])
273 options.mode = options.mode.split(",")
274 for mode in options.mode:
275 if not mode.lower() in ["debug", "release", "optdebug"]:
276 print "Unknown mode %s" % mode
277 return False
278 if options.arch in ["auto", "native"]:
279 options.arch = ARCH_GUESS
280 options.arch = options.arch.split(",")
281 for arch in options.arch:
282 if not arch in SUPPORTED_ARCHS:
283 print "Unknown architecture %s" % arch
284 return False
285
286 # Store the final configuration in arch_and_mode list. Don't overwrite
287 # predefined arch_and_mode since it is more expressive than arch and mode.
288 if not options.arch_and_mode:
289 options.arch_and_mode = itertools.product(options.arch, options.mode)
290
291 # Special processing of other options, sorted alphabetically.
292
293 if options.buildbot:
294 # Buildbots run presubmit tests as a separate step.
295 options.no_presubmit = True
296 options.no_network = True
297 if options.command_prefix:
298 print("Specifying --command-prefix disables network distribution, "
299 "running tests locally.")
300 options.no_network = True
301 options.command_prefix = shlex.split(options.command_prefix)
302 options.extra_flags = shlex.split(options.extra_flags)
303
304 if options.gc_stress:
305 options.extra_flags += GC_STRESS_FLAGS
306
307 if options.asan:
308 options.extra_flags.append("--invoke-weak-callbacks")
309
310 if options.tsan:
311 VARIANTS = ["default"]
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400312 suppressions_file = os.path.join(os.path.dirname(os.path.abspath(__file__)),
313 'sanitizers', 'tsan_suppressions.txt')
314 tsan_options = '%s suppressions=%s' % (
315 os.environ.get('TSAN_OPTIONS', ''), suppressions_file)
316 os.environ['TSAN_OPTIONS'] = tsan_options
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317
318 if options.j == 0:
319 options.j = multiprocessing.cpu_count()
320
321 while options.random_seed == 0:
322 options.random_seed = random.SystemRandom().randint(-2147483648, 2147483647)
323
324 def excl(*args):
325 """Returns true if zero or one of multiple arguments are true."""
326 return reduce(lambda x, y: x + y, args) <= 1
327
328 if not excl(options.no_stress, options.stress_only, options.no_variants,
329 bool(options.variants)):
330 print("Use only one of --no-stress, --stress-only, --no-variants, "
331 "or --variants.")
332 return False
333 if options.quickcheck:
334 VARIANTS = ["default", "stress"]
335 options.flaky_tests = "skip"
336 options.slow_tests = "skip"
337 options.pass_fail_tests = "skip"
338 if options.no_stress:
339 VARIANTS = ["default", "nocrankshaft"]
340 if options.no_variants:
341 VARIANTS = ["default"]
342 if options.stress_only:
343 VARIANTS = ["stress"]
344 if options.variants:
345 VARIANTS = options.variants.split(",")
346 if not set(VARIANTS).issubset(VARIANT_FLAGS.keys()):
347 print "All variants must be in %s" % str(VARIANT_FLAGS.keys())
348 return False
349 if options.predictable:
350 VARIANTS = ["default"]
351 options.extra_flags.append("--predictable")
352 options.extra_flags.append("--verify_predictable")
353 options.extra_flags.append("--no-inline-new")
354
355 if not options.shell_dir:
356 if options.shell:
357 print "Warning: --shell is deprecated, use --shell-dir instead."
358 options.shell_dir = os.path.dirname(options.shell)
359 if options.valgrind:
360 run_valgrind = os.path.join("tools", "run-valgrind.py")
361 # This is OK for distributed running, so we don't need to set no_network.
362 options.command_prefix = (["python", "-u", run_valgrind] +
363 options.command_prefix)
364 def CheckTestMode(name, option):
365 if not option in ["run", "skip", "dontcare"]:
366 print "Unknown %s mode %s" % (name, option)
367 return False
368 return True
369 if not CheckTestMode("flaky test", options.flaky_tests):
370 return False
371 if not CheckTestMode("slow test", options.slow_tests):
372 return False
373 if not CheckTestMode("pass|fail test", options.pass_fail_tests):
374 return False
375 if not options.no_i18n:
376 DEFAULT_TESTS.append("intl")
377 return True
378
379
380def ShardTests(tests, shard_count, shard_run):
381 if shard_count < 2:
382 return tests
383 if shard_run < 1 or shard_run > shard_count:
384 print "shard-run not a valid number, should be in [1:shard-count]"
385 print "defaulting back to running all tests"
386 return tests
387 count = 0
388 shard = []
389 for test in tests:
390 if count % shard_count == shard_run - 1:
391 shard.append(test)
392 count += 1
393 return shard
394
395
396def Main():
397 parser = BuildOptions()
398 (options, args) = parser.parse_args()
399 if not ProcessOptions(options):
400 parser.print_help()
401 return 1
402
403 exit_code = 0
404 workspace = os.path.abspath(join(os.path.dirname(sys.argv[0]), ".."))
405 if not options.no_presubmit:
406 print ">>> running presubmit tests"
407 exit_code = subprocess.call(
408 [sys.executable, join(workspace, "tools", "presubmit.py")])
409
410 suite_paths = utils.GetSuitePaths(join(workspace, "test"))
411
412 # Expand arguments with grouped tests. The args should reflect the list of
413 # suites as otherwise filters would break.
414 def ExpandTestGroups(name):
415 if name in TEST_MAP:
416 return [suite for suite in TEST_MAP[arg]]
417 else:
418 return [name]
419 args = reduce(lambda x, y: x + y,
420 [ExpandTestGroups(arg) for arg in args],
421 [])
422
423 if len(args) == 0:
424 suite_paths = [ s for s in DEFAULT_TESTS if s in suite_paths ]
425 else:
426 args_suites = OrderedDict() # Used as set
427 for arg in args:
428 args_suites[arg.split(os.path.sep)[0]] = True
429 suite_paths = [ s for s in args_suites if s in suite_paths ]
430
431 suites = []
432 for root in suite_paths:
433 suite = testsuite.TestSuite.LoadTestSuite(
434 os.path.join(workspace, "test", root))
435 if suite:
436 suites.append(suite)
437
438 if options.download_data:
439 for s in suites:
440 s.DownloadData()
441
442 for (arch, mode) in options.arch_and_mode:
443 try:
444 code = Execute(arch, mode, args, options, suites, workspace)
445 except KeyboardInterrupt:
446 return 2
447 exit_code = exit_code or code
448 return exit_code
449
450
451def Execute(arch, mode, args, options, suites, workspace):
452 print(">>> Running tests for %s.%s" % (arch, mode))
453
454 shell_dir = options.shell_dir
455 if not shell_dir:
456 if options.buildbot:
457 shell_dir = os.path.join(workspace, options.outdir, mode)
458 mode = mode.lower()
459 else:
460 shell_dir = os.path.join(workspace, options.outdir,
461 "%s.%s" % (arch, mode))
462 shell_dir = os.path.relpath(shell_dir)
463
464 if mode == "optdebug":
465 mode = "debug" # "optdebug" is just an alias.
466
467 # Populate context object.
468 mode_flags = MODE_FLAGS[mode]
469 timeout = options.timeout
470 if timeout == -1:
471 # Simulators are slow, therefore allow a longer default timeout.
472 if arch in SLOW_ARCHS:
473 timeout = 2 * TIMEOUT_DEFAULT;
474 else:
475 timeout = TIMEOUT_DEFAULT;
476
477 timeout *= TIMEOUT_SCALEFACTOR[mode]
478
479 if options.predictable:
480 # Predictable mode is slower.
481 timeout *= 2
482
483 ctx = context.Context(arch, mode, shell_dir,
484 mode_flags, options.verbose,
485 timeout, options.isolates,
486 options.command_prefix,
487 options.extra_flags,
488 options.no_i18n,
489 options.random_seed,
490 options.no_sorting,
491 options.rerun_failures_count,
492 options.rerun_failures_max,
493 options.predictable)
494
495 # TODO(all): Combine "simulator" and "simulator_run".
496 simulator_run = not options.dont_skip_simulator_slow_tests and \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400497 arch in ['arm64', 'arm', 'mipsel', 'mips', 'mips64el'] and \
498 ARCH_GUESS and arch != ARCH_GUESS
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499 # Find available test suites and read test cases from them.
500 variables = {
501 "arch": arch,
502 "asan": options.asan,
503 "deopt_fuzzer": False,
504 "gc_stress": options.gc_stress,
505 "isolates": options.isolates,
506 "mode": mode,
507 "no_i18n": options.no_i18n,
508 "no_snap": options.no_snap,
509 "simulator_run": simulator_run,
510 "simulator": utils.UseSimulator(arch),
511 "system": utils.GuessOS(),
512 "tsan": options.tsan,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400513 "msan": options.msan,
514 "dcheck_always_on": options.dcheck_always_on,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000515 }
516 all_tests = []
517 num_tests = 0
518 test_id = 0
519 for s in suites:
520 s.ReadStatusFile(variables)
521 s.ReadTestCases(ctx)
522 if len(args) > 0:
523 s.FilterTestCasesByArgs(args)
524 all_tests += s.tests
525 s.FilterTestCasesByStatus(options.warn_unused, options.flaky_tests,
526 options.slow_tests, options.pass_fail_tests)
527 if options.cat:
528 verbose.PrintTestSource(s.tests)
529 continue
530 variant_flags = [VARIANT_FLAGS[var] for var in VARIANTS]
531 s.tests = [ t.CopyAddingFlags(v)
532 for t in s.tests
533 for v in s.VariantFlags(t, variant_flags) ]
534 s.tests = ShardTests(s.tests, options.shard_count, options.shard_run)
535 num_tests += len(s.tests)
536 for t in s.tests:
537 t.id = test_id
538 test_id += 1
539
540 if options.cat:
541 return 0 # We're done here.
542
543 if options.report:
544 verbose.PrintReport(all_tests)
545
546 if num_tests == 0:
547 print "No tests to run."
548 return 0
549
550 # Run the tests, either locally or distributed on the network.
551 start_time = time.time()
552 progress_indicator = progress.PROGRESS_INDICATORS[options.progress]()
553 if options.junitout:
554 progress_indicator = progress.JUnitTestProgressIndicator(
555 progress_indicator, options.junitout, options.junittestsuite)
556 if options.json_test_results:
557 progress_indicator = progress.JsonTestProgressIndicator(
558 progress_indicator, options.json_test_results, arch, mode)
559
560 run_networked = not options.no_network
561 if not run_networked:
562 print("Network distribution disabled, running tests locally.")
563 elif utils.GuessOS() != "linux":
564 print("Network distribution is only supported on Linux, sorry!")
565 run_networked = False
566 peers = []
567 if run_networked:
568 peers = network_execution.GetPeers()
569 if not peers:
570 print("No connection to distribution server; running tests locally.")
571 run_networked = False
572 elif len(peers) == 1:
573 print("No other peers on the network; running tests locally.")
574 run_networked = False
575 elif num_tests <= 100:
576 print("Less than 100 tests, running them locally.")
577 run_networked = False
578
579 if run_networked:
580 runner = network_execution.NetworkedRunner(suites, progress_indicator,
581 ctx, peers, workspace)
582 else:
583 runner = execution.Runner(suites, progress_indicator, ctx)
584
585 exit_code = runner.Run(options.j)
586 overall_duration = time.time() - start_time
587
588 if options.time:
589 verbose.PrintTestDurations(suites, overall_duration)
590 return exit_code
591
592
593if __name__ == "__main__":
594 sys.exit(Main())