11cb0ef41Sopenharmony_ci#!/usr/bin/env python3
21cb0ef41Sopenharmony_ci#
31cb0ef41Sopenharmony_ci# Copyright 2017 the V8 project authors. All rights reserved.
41cb0ef41Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be
51cb0ef41Sopenharmony_ci# found in the LICENSE file.
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_cifrom functools import reduce
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciimport datetime
101cb0ef41Sopenharmony_ciimport json
111cb0ef41Sopenharmony_ciimport os
121cb0ef41Sopenharmony_ciimport sys
131cb0ef41Sopenharmony_ciimport tempfile
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ci# Adds testrunner to the path hence it has to be imported at the beggining.
161cb0ef41Sopenharmony_ciimport testrunner.base_runner as base_runner
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cifrom testrunner.local import utils
191cb0ef41Sopenharmony_cifrom testrunner.local.variants import ALL_VARIANTS
201cb0ef41Sopenharmony_cifrom testrunner.objects import predictable
211cb0ef41Sopenharmony_cifrom testrunner.testproc.execution import ExecutionProc
221cb0ef41Sopenharmony_cifrom testrunner.testproc.filter import StatusFileFilterProc, NameFilterProc
231cb0ef41Sopenharmony_cifrom testrunner.testproc.loader import LoadProc
241cb0ef41Sopenharmony_cifrom testrunner.testproc.seed import SeedProc
251cb0ef41Sopenharmony_cifrom testrunner.testproc.sequence import SequenceProc
261cb0ef41Sopenharmony_cifrom testrunner.testproc.variant import VariantProc
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ciVARIANTS = ['default']
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ciMORE_VARIANTS = [
321cb0ef41Sopenharmony_ci  'jitless',
331cb0ef41Sopenharmony_ci  'stress',
341cb0ef41Sopenharmony_ci  'stress_js_bg_compile_wasm_code_gc',
351cb0ef41Sopenharmony_ci  'stress_incremental_marking',
361cb0ef41Sopenharmony_ci]
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ciVARIANT_ALIASES = {
391cb0ef41Sopenharmony_ci  # The default for developer workstations.
401cb0ef41Sopenharmony_ci  'dev': VARIANTS,
411cb0ef41Sopenharmony_ci  # Additional variants, run on all bots.
421cb0ef41Sopenharmony_ci  'more': MORE_VARIANTS,
431cb0ef41Sopenharmony_ci  # Shortcut for the two above ('more' first - it has the longer running tests)
441cb0ef41Sopenharmony_ci  'exhaustive': MORE_VARIANTS + VARIANTS,
451cb0ef41Sopenharmony_ci  # Additional variants, run on a subset of bots.
461cb0ef41Sopenharmony_ci  'extra': ['nooptimization', 'future', 'no_wasm_traps',
471cb0ef41Sopenharmony_ci            'instruction_scheduling', 'always_sparkplug'],
481cb0ef41Sopenharmony_ci}
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci# Extra flags passed to all tests using the standard test runner.
511cb0ef41Sopenharmony_ciEXTRA_DEFAULT_FLAGS = ['--testing-d8-test-runner']
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ciGC_STRESS_FLAGS = ['--gc-interval=500', '--stress-compaction',
541cb0ef41Sopenharmony_ci                   '--concurrent-recompilation-queue-length=64',
551cb0ef41Sopenharmony_ci                   '--concurrent-recompilation-delay=500',
561cb0ef41Sopenharmony_ci                   '--concurrent-recompilation',
571cb0ef41Sopenharmony_ci                   '--stress-flush-code', '--flush-bytecode',
581cb0ef41Sopenharmony_ci                   '--wasm-code-gc', '--stress-wasm-code-gc']
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ciRANDOM_GC_STRESS_FLAGS = ['--random-gc-interval=5000',
611cb0ef41Sopenharmony_ci                          '--stress-compaction-random']
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ciPREDICTABLE_WRAPPER = os.path.join(
651cb0ef41Sopenharmony_ci    base_runner.BASE_DIR, 'tools', 'predictable_wrapper.py')
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ciclass StandardTestRunner(base_runner.BaseTestRunner):
691cb0ef41Sopenharmony_ci  def __init__(self, *args, **kwargs):
701cb0ef41Sopenharmony_ci    super(StandardTestRunner, self).__init__(*args, **kwargs)
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci    self.sancov_dir = None
731cb0ef41Sopenharmony_ci    self._variants = None
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  @property
761cb0ef41Sopenharmony_ci  def framework_name(self):
771cb0ef41Sopenharmony_ci    return 'standard_runner'
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  def _get_default_suite_names(self):
801cb0ef41Sopenharmony_ci    return ['default']
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  def _add_parser_options(self, parser):
831cb0ef41Sopenharmony_ci    parser.add_option('--novfp3',
841cb0ef41Sopenharmony_ci                      help='Indicates that V8 was compiled without VFP3'
851cb0ef41Sopenharmony_ci                      ' support',
861cb0ef41Sopenharmony_ci                      default=False, action='store_true')
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci    # Variants
891cb0ef41Sopenharmony_ci    parser.add_option('--no-variants', '--novariants',
901cb0ef41Sopenharmony_ci                      help='Deprecated. '
911cb0ef41Sopenharmony_ci                           'Equivalent to passing --variants=default',
921cb0ef41Sopenharmony_ci                      default=False, dest='no_variants', action='store_true')
931cb0ef41Sopenharmony_ci    parser.add_option('--variants',
941cb0ef41Sopenharmony_ci                      help='Comma-separated list of testing variants;'
951cb0ef41Sopenharmony_ci                      ' default: "%s"' % ','.join(VARIANTS))
961cb0ef41Sopenharmony_ci    parser.add_option('--exhaustive-variants',
971cb0ef41Sopenharmony_ci                      default=False, action='store_true',
981cb0ef41Sopenharmony_ci                      help='Deprecated. '
991cb0ef41Sopenharmony_ci                           'Equivalent to passing --variants=exhaustive')
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci    # Filters
1021cb0ef41Sopenharmony_ci    parser.add_option('--slow-tests', default='dontcare',
1031cb0ef41Sopenharmony_ci                      help='Regard slow tests (run|skip|dontcare)')
1041cb0ef41Sopenharmony_ci    parser.add_option('--pass-fail-tests', default='dontcare',
1051cb0ef41Sopenharmony_ci                      help='Regard pass|fail tests (run|skip|dontcare)')
1061cb0ef41Sopenharmony_ci    parser.add_option('--quickcheck', default=False, action='store_true',
1071cb0ef41Sopenharmony_ci                      help=('Quick check mode (skip slow tests)'))
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci    # Stress modes
1101cb0ef41Sopenharmony_ci    parser.add_option('--gc-stress',
1111cb0ef41Sopenharmony_ci                      help='Switch on GC stress mode',
1121cb0ef41Sopenharmony_ci                      default=False, action='store_true')
1131cb0ef41Sopenharmony_ci    parser.add_option('--random-gc-stress',
1141cb0ef41Sopenharmony_ci                      help='Switch on random GC stress mode',
1151cb0ef41Sopenharmony_ci                      default=False, action='store_true')
1161cb0ef41Sopenharmony_ci    parser.add_option('--random-seed-stress-count', default=1, type='int',
1171cb0ef41Sopenharmony_ci                      dest='random_seed_stress_count',
1181cb0ef41Sopenharmony_ci                      help='Number of runs with different random seeds. Only '
1191cb0ef41Sopenharmony_ci                           'with test processors: 0 means infinite '
1201cb0ef41Sopenharmony_ci                           'generation.')
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci    # Extra features.
1231cb0ef41Sopenharmony_ci    parser.add_option('--max-heavy-tests', default=1, type='int',
1241cb0ef41Sopenharmony_ci                      help='Maximum number of heavy tests run in parallel')
1251cb0ef41Sopenharmony_ci    parser.add_option('--time', help='Print timing information after running',
1261cb0ef41Sopenharmony_ci                      default=False, action='store_true')
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci    # Noop
1291cb0ef41Sopenharmony_ci    parser.add_option('--cfi-vptr',
1301cb0ef41Sopenharmony_ci                      help='Run tests with UBSAN cfi_vptr option.',
1311cb0ef41Sopenharmony_ci                      default=False, action='store_true')
1321cb0ef41Sopenharmony_ci    parser.add_option('--no-sorting', '--nosorting',
1331cb0ef41Sopenharmony_ci                      help='Don\'t sort tests according to duration of last'
1341cb0ef41Sopenharmony_ci                      ' run.',
1351cb0ef41Sopenharmony_ci                      default=False, dest='no_sorting', action='store_true')
1361cb0ef41Sopenharmony_ci    parser.add_option('--no-presubmit', '--nopresubmit',
1371cb0ef41Sopenharmony_ci                      help='Skip presubmit checks (deprecated)',
1381cb0ef41Sopenharmony_ci                      default=False, dest='no_presubmit', action='store_true')
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci    # Unimplemented for test processors
1411cb0ef41Sopenharmony_ci    parser.add_option('--sancov-dir',
1421cb0ef41Sopenharmony_ci                      help='Directory where to collect coverage data')
1431cb0ef41Sopenharmony_ci    parser.add_option('--cat', help='Print the source of the tests',
1441cb0ef41Sopenharmony_ci                      default=False, action='store_true')
1451cb0ef41Sopenharmony_ci    parser.add_option('--flakiness-results',
1461cb0ef41Sopenharmony_ci                      help='Path to a file for storing flakiness json.')
1471cb0ef41Sopenharmony_ci    parser.add_option('--warn-unused', help='Report unused rules',
1481cb0ef41Sopenharmony_ci                      default=False, action='store_true')
1491cb0ef41Sopenharmony_ci    parser.add_option('--report', default=False, action='store_true',
1501cb0ef41Sopenharmony_ci                      help='Print a summary of the tests to be run')
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  def _process_options(self, options):
1531cb0ef41Sopenharmony_ci    if options.sancov_dir:
1541cb0ef41Sopenharmony_ci      self.sancov_dir = options.sancov_dir
1551cb0ef41Sopenharmony_ci      if not os.path.exists(self.sancov_dir):
1561cb0ef41Sopenharmony_ci        print('sancov-dir %s doesn\'t exist' % self.sancov_dir)
1571cb0ef41Sopenharmony_ci        raise base_runner.TestRunnerError()
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci    if options.gc_stress:
1601cb0ef41Sopenharmony_ci      options.extra_flags += GC_STRESS_FLAGS
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci    if options.random_gc_stress:
1631cb0ef41Sopenharmony_ci      options.extra_flags += RANDOM_GC_STRESS_FLAGS
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci    if self.build_config.asan:
1661cb0ef41Sopenharmony_ci      options.extra_flags.append('--invoke-weak-callbacks')
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci    if options.novfp3:
1691cb0ef41Sopenharmony_ci      options.extra_flags.append('--noenable-vfp3')
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci    if options.no_variants:  # pragma: no cover
1721cb0ef41Sopenharmony_ci      print ('Option --no-variants is deprecated. '
1731cb0ef41Sopenharmony_ci             'Pass --variants=default instead.')
1741cb0ef41Sopenharmony_ci      assert not options.variants
1751cb0ef41Sopenharmony_ci      options.variants = 'default'
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci    if options.exhaustive_variants:  # pragma: no cover
1781cb0ef41Sopenharmony_ci      # TODO(machenbach): Switch infra to --variants=exhaustive after M65.
1791cb0ef41Sopenharmony_ci      print ('Option --exhaustive-variants is deprecated. '
1801cb0ef41Sopenharmony_ci             'Pass --variants=exhaustive instead.')
1811cb0ef41Sopenharmony_ci      # This is used on many bots. It includes a larger set of default
1821cb0ef41Sopenharmony_ci      # variants.
1831cb0ef41Sopenharmony_ci      # Other options for manipulating variants still apply afterwards.
1841cb0ef41Sopenharmony_ci      assert not options.variants
1851cb0ef41Sopenharmony_ci      options.variants = 'exhaustive'
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci    if options.quickcheck:
1881cb0ef41Sopenharmony_ci      assert not options.variants
1891cb0ef41Sopenharmony_ci      options.variants = 'stress,default'
1901cb0ef41Sopenharmony_ci      options.slow_tests = 'skip'
1911cb0ef41Sopenharmony_ci      options.pass_fail_tests = 'skip'
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci    if self.build_config.predictable:
1941cb0ef41Sopenharmony_ci      options.variants = 'default'
1951cb0ef41Sopenharmony_ci      options.extra_flags.append('--predictable')
1961cb0ef41Sopenharmony_ci      options.extra_flags.append('--verify-predictable')
1971cb0ef41Sopenharmony_ci      options.extra_flags.append('--no-inline-new')
1981cb0ef41Sopenharmony_ci      # Add predictable wrapper to command prefix.
1991cb0ef41Sopenharmony_ci      options.command_prefix = (
2001cb0ef41Sopenharmony_ci          [sys.executable, PREDICTABLE_WRAPPER] + options.command_prefix)
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci    # TODO(machenbach): Figure out how to test a bigger subset of variants on
2031cb0ef41Sopenharmony_ci    # msan.
2041cb0ef41Sopenharmony_ci    if self.build_config.msan:
2051cb0ef41Sopenharmony_ci      options.variants = 'default'
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci    if options.variants == 'infra_staging':
2081cb0ef41Sopenharmony_ci      options.variants = 'exhaustive'
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ci    self._variants = self._parse_variants(options.variants)
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci    def CheckTestMode(name, option):  # pragma: no cover
2131cb0ef41Sopenharmony_ci      if option not in ['run', 'skip', 'dontcare']:
2141cb0ef41Sopenharmony_ci        print('Unknown %s mode %s' % (name, option))
2151cb0ef41Sopenharmony_ci        raise base_runner.TestRunnerError()
2161cb0ef41Sopenharmony_ci    CheckTestMode('slow test', options.slow_tests)
2171cb0ef41Sopenharmony_ci    CheckTestMode('pass|fail test', options.pass_fail_tests)
2181cb0ef41Sopenharmony_ci    if self.build_config.no_i18n:
2191cb0ef41Sopenharmony_ci      base_runner.TEST_MAP['bot_default'].remove('intl')
2201cb0ef41Sopenharmony_ci      base_runner.TEST_MAP['default'].remove('intl')
2211cb0ef41Sopenharmony_ci      # TODO(machenbach): uncomment after infra side lands.
2221cb0ef41Sopenharmony_ci      # base_runner.TEST_MAP['d8_default'].remove('intl')
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci    if options.time and not options.json_test_results:
2251cb0ef41Sopenharmony_ci      # We retrieve the slowest tests from the JSON output file, so create
2261cb0ef41Sopenharmony_ci      # a temporary output file (which will automatically get deleted on exit)
2271cb0ef41Sopenharmony_ci      # if the user didn't specify one.
2281cb0ef41Sopenharmony_ci      self._temporary_json_output_file = tempfile.NamedTemporaryFile(
2291cb0ef41Sopenharmony_ci          prefix="v8-test-runner-")
2301cb0ef41Sopenharmony_ci      options.json_test_results = self._temporary_json_output_file.name
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci  def _runner_flags(self):
2331cb0ef41Sopenharmony_ci    return EXTRA_DEFAULT_FLAGS
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci  def _parse_variants(self, aliases_str):
2361cb0ef41Sopenharmony_ci    # Use developer defaults if no variant was specified.
2371cb0ef41Sopenharmony_ci    aliases_str = aliases_str or 'dev'
2381cb0ef41Sopenharmony_ci    aliases = aliases_str.split(',')
2391cb0ef41Sopenharmony_ci    user_variants = set(reduce(
2401cb0ef41Sopenharmony_ci        list.__add__, [VARIANT_ALIASES.get(a, [a]) for a in aliases]))
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci    result = [v for v in ALL_VARIANTS if v in user_variants]
2431cb0ef41Sopenharmony_ci    if len(result) == len(user_variants):
2441cb0ef41Sopenharmony_ci      return result
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci    for v in user_variants:
2471cb0ef41Sopenharmony_ci      if v not in ALL_VARIANTS:
2481cb0ef41Sopenharmony_ci        print('Unknown variant: %s' % v)
2491cb0ef41Sopenharmony_ci        print('    Available variants: %s' % ALL_VARIANTS)
2501cb0ef41Sopenharmony_ci        print('    Available variant aliases: %s' % VARIANT_ALIASES.keys());
2511cb0ef41Sopenharmony_ci        raise base_runner.TestRunnerError()
2521cb0ef41Sopenharmony_ci    assert False, 'Unreachable'
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  def _setup_env(self):
2551cb0ef41Sopenharmony_ci    super(StandardTestRunner, self)._setup_env()
2561cb0ef41Sopenharmony_ci
2571cb0ef41Sopenharmony_ci    symbolizer_option = self._get_external_symbolizer_option()
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci    if self.sancov_dir:
2601cb0ef41Sopenharmony_ci      os.environ['ASAN_OPTIONS'] = ':'.join([
2611cb0ef41Sopenharmony_ci        'coverage=1',
2621cb0ef41Sopenharmony_ci        'coverage_dir=%s' % self.sancov_dir,
2631cb0ef41Sopenharmony_ci        symbolizer_option,
2641cb0ef41Sopenharmony_ci        'allow_user_segv_handler=1',
2651cb0ef41Sopenharmony_ci      ])
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci  def _get_statusfile_variables(self, options):
2681cb0ef41Sopenharmony_ci    variables = (
2691cb0ef41Sopenharmony_ci        super(StandardTestRunner, self)._get_statusfile_variables(options))
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci    variables.update({
2721cb0ef41Sopenharmony_ci      'gc_stress': options.gc_stress or options.random_gc_stress,
2731cb0ef41Sopenharmony_ci      'gc_fuzzer': options.random_gc_stress,
2741cb0ef41Sopenharmony_ci      'novfp3': options.novfp3,
2751cb0ef41Sopenharmony_ci    })
2761cb0ef41Sopenharmony_ci    return variables
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci  def _create_sequence_proc(self, options):
2791cb0ef41Sopenharmony_ci    """Create processor for sequencing heavy tests on swarming."""
2801cb0ef41Sopenharmony_ci    return SequenceProc(options.max_heavy_tests) if options.swarming else None
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci  def _do_execute(self, tests, args, options):
2831cb0ef41Sopenharmony_ci    jobs = options.j
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci    print('>>> Running with test processors')
2861cb0ef41Sopenharmony_ci    loader = LoadProc(tests)
2871cb0ef41Sopenharmony_ci    results = self._create_result_tracker(options)
2881cb0ef41Sopenharmony_ci    indicators = self._create_progress_indicators(
2891cb0ef41Sopenharmony_ci        tests.test_count_estimate, options)
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci    outproc_factory = None
2921cb0ef41Sopenharmony_ci    if self.build_config.predictable:
2931cb0ef41Sopenharmony_ci      outproc_factory = predictable.get_outproc
2941cb0ef41Sopenharmony_ci    execproc = ExecutionProc(jobs, outproc_factory)
2951cb0ef41Sopenharmony_ci    sigproc = self._create_signal_proc()
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_ci    procs = [
2981cb0ef41Sopenharmony_ci      loader,
2991cb0ef41Sopenharmony_ci      NameFilterProc(args) if args else None,
3001cb0ef41Sopenharmony_ci      StatusFileFilterProc(options.slow_tests, options.pass_fail_tests),
3011cb0ef41Sopenharmony_ci      VariantProc(self._variants),
3021cb0ef41Sopenharmony_ci      StatusFileFilterProc(options.slow_tests, options.pass_fail_tests),
3031cb0ef41Sopenharmony_ci      self._create_predictable_filter(),
3041cb0ef41Sopenharmony_ci      self._create_shard_proc(options),
3051cb0ef41Sopenharmony_ci      self._create_seed_proc(options),
3061cb0ef41Sopenharmony_ci      self._create_sequence_proc(options),
3071cb0ef41Sopenharmony_ci      sigproc,
3081cb0ef41Sopenharmony_ci    ] + indicators + [
3091cb0ef41Sopenharmony_ci      results,
3101cb0ef41Sopenharmony_ci      self._create_timeout_proc(options),
3111cb0ef41Sopenharmony_ci      self._create_rerun_proc(options),
3121cb0ef41Sopenharmony_ci      execproc,
3131cb0ef41Sopenharmony_ci    ]
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci    self._prepare_procs(procs)
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci    loader.load_initial_tests(initial_batch_size=options.j * 2)
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ci    # This starts up worker processes and blocks until all tests are
3201cb0ef41Sopenharmony_ci    # processed.
3211cb0ef41Sopenharmony_ci    execproc.run()
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci    for indicator in indicators:
3241cb0ef41Sopenharmony_ci      indicator.finished()
3251cb0ef41Sopenharmony_ci
3261cb0ef41Sopenharmony_ci    if tests.test_count_estimate:
3271cb0ef41Sopenharmony_ci      percentage = float(results.total) / tests.test_count_estimate * 100
3281cb0ef41Sopenharmony_ci    else:
3291cb0ef41Sopenharmony_ci      percentage = 0
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_ci    print (('>>> %d base tests produced %d (%d%s)'
3321cb0ef41Sopenharmony_ci           ' non-filtered tests') % (
3331cb0ef41Sopenharmony_ci        tests.test_count_estimate, results.total, percentage, '%'))
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ci    print('>>> %d tests ran' % (results.total - results.remaining))
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci    exit_code = utils.EXIT_CODE_PASS
3381cb0ef41Sopenharmony_ci    if results.failed:
3391cb0ef41Sopenharmony_ci      exit_code = utils.EXIT_CODE_FAILURES
3401cb0ef41Sopenharmony_ci    if not results.total:
3411cb0ef41Sopenharmony_ci      exit_code = utils.EXIT_CODE_NO_TESTS
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci    if options.time:
3441cb0ef41Sopenharmony_ci      self._print_durations(options)
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci    # Indicate if a SIGINT or SIGTERM happened.
3471cb0ef41Sopenharmony_ci    return max(exit_code, sigproc.exit_code)
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ci  def _print_durations(self, options):
3501cb0ef41Sopenharmony_ci
3511cb0ef41Sopenharmony_ci    def format_duration(duration_in_seconds):
3521cb0ef41Sopenharmony_ci      duration = datetime.timedelta(seconds=duration_in_seconds)
3531cb0ef41Sopenharmony_ci      time = (datetime.datetime.min + duration).time()
3541cb0ef41Sopenharmony_ci      return time.strftime('%M:%S:') + '%03i' % int(time.microsecond / 1000)
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci    def _duration_results_text(test):
3571cb0ef41Sopenharmony_ci      return [
3581cb0ef41Sopenharmony_ci        'Test: %s' % test['name'],
3591cb0ef41Sopenharmony_ci        'Flags: %s' % ' '.join(test['flags']),
3601cb0ef41Sopenharmony_ci        'Command: %s' % test['command'],
3611cb0ef41Sopenharmony_ci        'Duration: %s' % format_duration(test['duration']),
3621cb0ef41Sopenharmony_ci      ]
3631cb0ef41Sopenharmony_ci
3641cb0ef41Sopenharmony_ci    assert os.path.exists(options.json_test_results)
3651cb0ef41Sopenharmony_ci    with open(options.json_test_results, "r") as f:
3661cb0ef41Sopenharmony_ci      output = json.load(f)
3671cb0ef41Sopenharmony_ci    lines = []
3681cb0ef41Sopenharmony_ci    for test in output['slowest_tests']:
3691cb0ef41Sopenharmony_ci      suffix = ''
3701cb0ef41Sopenharmony_ci      if test.get('marked_slow') is False:
3711cb0ef41Sopenharmony_ci        suffix = ' *'
3721cb0ef41Sopenharmony_ci      lines.append(
3731cb0ef41Sopenharmony_ci          '%s %s%s' % (format_duration(test['duration']),
3741cb0ef41Sopenharmony_ci                       test['name'], suffix))
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ci    # Slowest tests duration details.
3771cb0ef41Sopenharmony_ci    lines.extend(['', 'Details:', ''])
3781cb0ef41Sopenharmony_ci    for test in output['slowest_tests']:
3791cb0ef41Sopenharmony_ci      lines.extend(_duration_results_text(test))
3801cb0ef41Sopenharmony_ci    print("\n".join(lines))
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci  def _create_predictable_filter(self):
3831cb0ef41Sopenharmony_ci    if not self.build_config.predictable:
3841cb0ef41Sopenharmony_ci      return None
3851cb0ef41Sopenharmony_ci    return predictable.PredictableFilterProc()
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ci  def _create_seed_proc(self, options):
3881cb0ef41Sopenharmony_ci    if options.random_seed_stress_count == 1:
3891cb0ef41Sopenharmony_ci      return None
3901cb0ef41Sopenharmony_ci    return SeedProc(options.random_seed_stress_count, options.random_seed,
3911cb0ef41Sopenharmony_ci                    options.j * 4)
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_ciif __name__ == '__main__':
3951cb0ef41Sopenharmony_ci  sys.exit(StandardTestRunner().execute())
396