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_ciimport random
81cb0ef41Sopenharmony_ciimport sys
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci# Adds testrunner to the path hence it has to be imported at the beggining.
111cb0ef41Sopenharmony_cifrom . import base_runner
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cifrom testrunner.local import utils
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cifrom testrunner.testproc import fuzzer
161cb0ef41Sopenharmony_cifrom testrunner.testproc.base import TestProcProducer
171cb0ef41Sopenharmony_cifrom testrunner.testproc.combiner import CombinerProc
181cb0ef41Sopenharmony_cifrom testrunner.testproc.execution import ExecutionProc
191cb0ef41Sopenharmony_cifrom testrunner.testproc.expectation import ExpectationProc
201cb0ef41Sopenharmony_cifrom testrunner.testproc.filter import StatusFileFilterProc, NameFilterProc
211cb0ef41Sopenharmony_cifrom testrunner.testproc.loader import LoadProc
221cb0ef41Sopenharmony_cifrom testrunner.testproc.progress import ResultsTracker
231cb0ef41Sopenharmony_cifrom testrunner.utils import random_utils
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciDEFAULT_SUITES = ["mjsunit", "webkit", "benchmarks"]
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ciclass NumFuzzer(base_runner.BaseTestRunner):
301cb0ef41Sopenharmony_ci  def __init__(self, *args, **kwargs):
311cb0ef41Sopenharmony_ci    super(NumFuzzer, self).__init__(*args, **kwargs)
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  @property
341cb0ef41Sopenharmony_ci  def framework_name(self):
351cb0ef41Sopenharmony_ci    return 'num_fuzzer'
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  def _add_parser_options(self, parser):
381cb0ef41Sopenharmony_ci    parser.add_option("--fuzzer-random-seed", default=0,
391cb0ef41Sopenharmony_ci                      help="Default seed for initializing fuzzer random "
401cb0ef41Sopenharmony_ci                      "generator")
411cb0ef41Sopenharmony_ci    parser.add_option("--tests-count", default=5, type="int",
421cb0ef41Sopenharmony_ci                      help="Number of tests to generate from each base test. "
431cb0ef41Sopenharmony_ci                           "Can be combined with --total-timeout-sec with "
441cb0ef41Sopenharmony_ci                           "value 0 to provide infinite number of subtests. "
451cb0ef41Sopenharmony_ci                           "When --combine-tests is set it indicates how many "
461cb0ef41Sopenharmony_ci                           "tests to create in total")
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci    # Stress gc
491cb0ef41Sopenharmony_ci    parser.add_option("--stress-marking", default=0, type="int",
501cb0ef41Sopenharmony_ci                      help="probability [0-10] of adding --stress-marking "
511cb0ef41Sopenharmony_ci                           "flag to the test")
521cb0ef41Sopenharmony_ci    parser.add_option("--stress-scavenge", default=0, type="int",
531cb0ef41Sopenharmony_ci                      help="probability [0-10] of adding --stress-scavenge "
541cb0ef41Sopenharmony_ci                           "flag to the test")
551cb0ef41Sopenharmony_ci    parser.add_option("--stress-compaction", default=0, type="int",
561cb0ef41Sopenharmony_ci                      help="probability [0-10] of adding --stress-compaction "
571cb0ef41Sopenharmony_ci                           "flag to the test")
581cb0ef41Sopenharmony_ci    parser.add_option("--stress-gc", default=0, type="int",
591cb0ef41Sopenharmony_ci                      help="probability [0-10] of adding --random-gc-interval "
601cb0ef41Sopenharmony_ci                           "flag to the test")
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci    # Stress stack size
631cb0ef41Sopenharmony_ci    parser.add_option("--stress-stack-size", default=0, type="int",
641cb0ef41Sopenharmony_ci                      help="probability [0-10] of adding --stack-size "
651cb0ef41Sopenharmony_ci                           "flag to the test")
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci    # Stress tasks
681cb0ef41Sopenharmony_ci    parser.add_option("--stress-delay-tasks", default=0, type="int",
691cb0ef41Sopenharmony_ci                      help="probability [0-10] of adding --stress-delay-tasks "
701cb0ef41Sopenharmony_ci                           "flag to the test")
711cb0ef41Sopenharmony_ci    parser.add_option("--stress-thread-pool-size", default=0, type="int",
721cb0ef41Sopenharmony_ci                      help="probability [0-10] of adding --thread-pool-size "
731cb0ef41Sopenharmony_ci                           "flag to the test")
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci    # Stress compiler
761cb0ef41Sopenharmony_ci    parser.add_option("--stress-deopt", default=0, type="int",
771cb0ef41Sopenharmony_ci                      help="probability [0-10] of adding --deopt-every-n-times "
781cb0ef41Sopenharmony_ci                           "flag to the test")
791cb0ef41Sopenharmony_ci    parser.add_option("--stress-deopt-min", default=1, type="int",
801cb0ef41Sopenharmony_ci                      help="extends --stress-deopt to have minimum interval "
811cb0ef41Sopenharmony_ci                           "between deopt points")
821cb0ef41Sopenharmony_ci    parser.add_option("--stress-interrupt-budget", default=0, type="int",
831cb0ef41Sopenharmony_ci                      help="probability [0-10] of adding the --interrupt-budget "
841cb0ef41Sopenharmony_ci                           "flag to the test")
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci    # Combine multiple tests
871cb0ef41Sopenharmony_ci    parser.add_option("--combine-tests", default=False, action="store_true",
881cb0ef41Sopenharmony_ci                      help="Combine multiple tests as one and run with "
891cb0ef41Sopenharmony_ci                           "try-catch wrapper")
901cb0ef41Sopenharmony_ci    parser.add_option("--combine-max", default=100, type="int",
911cb0ef41Sopenharmony_ci                      help="Maximum number of tests to combine")
921cb0ef41Sopenharmony_ci    parser.add_option("--combine-min", default=2, type="int",
931cb0ef41Sopenharmony_ci                      help="Minimum number of tests to combine")
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci    # Miscellaneous
961cb0ef41Sopenharmony_ci    parser.add_option("--variants", default='default',
971cb0ef41Sopenharmony_ci                      help="Comma-separated list of testing variants")
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci    return parser
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  def _process_options(self, options):
1031cb0ef41Sopenharmony_ci    if not options.fuzzer_random_seed:
1041cb0ef41Sopenharmony_ci      options.fuzzer_random_seed = random_utils.random_seed()
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci    if options.total_timeout_sec:
1071cb0ef41Sopenharmony_ci      options.tests_count = 0
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci    if options.combine_tests:
1101cb0ef41Sopenharmony_ci      if options.combine_min > options.combine_max:
1111cb0ef41Sopenharmony_ci        print(('min_group_size (%d) cannot be larger than max_group_size (%d)' %
1121cb0ef41Sopenharmony_ci               options.min_group_size, options.max_group_size))
1131cb0ef41Sopenharmony_ci        raise base_runner.TestRunnerError()
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci    if options.variants != 'default':
1161cb0ef41Sopenharmony_ci      print ('Only default testing variant is supported with numfuzz')
1171cb0ef41Sopenharmony_ci      raise base_runner.TestRunnerError()
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci    return True
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci  def _get_default_suite_names(self):
1221cb0ef41Sopenharmony_ci    return DEFAULT_SUITES
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  def _runner_flags(self):
1251cb0ef41Sopenharmony_ci    """Extra default flags specific to the test runner implementation."""
1261cb0ef41Sopenharmony_ci    return [
1271cb0ef41Sopenharmony_ci      '--no-abort-on-contradictory-flags',
1281cb0ef41Sopenharmony_ci      '--testing-d8-test-runner',
1291cb0ef41Sopenharmony_ci      '--no-fail'
1301cb0ef41Sopenharmony_ci    ]
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  def _get_statusfile_variables(self, options):
1331cb0ef41Sopenharmony_ci    variables = (
1341cb0ef41Sopenharmony_ci        super(NumFuzzer, self)._get_statusfile_variables(options))
1351cb0ef41Sopenharmony_ci    variables.update({
1361cb0ef41Sopenharmony_ci      'deopt_fuzzer': bool(options.stress_deopt),
1371cb0ef41Sopenharmony_ci      'endurance_fuzzer': bool(options.combine_tests),
1381cb0ef41Sopenharmony_ci      'gc_stress': bool(options.stress_gc),
1391cb0ef41Sopenharmony_ci      'gc_fuzzer': bool(max([options.stress_marking,
1401cb0ef41Sopenharmony_ci                             options.stress_scavenge,
1411cb0ef41Sopenharmony_ci                             options.stress_compaction,
1421cb0ef41Sopenharmony_ci                             options.stress_gc,
1431cb0ef41Sopenharmony_ci                             options.stress_delay_tasks,
1441cb0ef41Sopenharmony_ci                             options.stress_stack_size,
1451cb0ef41Sopenharmony_ci                             options.stress_thread_pool_size])),
1461cb0ef41Sopenharmony_ci    })
1471cb0ef41Sopenharmony_ci    return variables
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci  def _do_execute(self, tests, args, options):
1501cb0ef41Sopenharmony_ci    loader = LoadProc(tests)
1511cb0ef41Sopenharmony_ci    fuzzer_rng = random.Random(options.fuzzer_random_seed)
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci    combiner = self._create_combiner(fuzzer_rng, options)
1541cb0ef41Sopenharmony_ci    results = self._create_result_tracker(options)
1551cb0ef41Sopenharmony_ci    execproc = ExecutionProc(options.j)
1561cb0ef41Sopenharmony_ci    sigproc = self._create_signal_proc()
1571cb0ef41Sopenharmony_ci    indicators = self._create_progress_indicators(
1581cb0ef41Sopenharmony_ci      tests.test_count_estimate, options)
1591cb0ef41Sopenharmony_ci    procs = [
1601cb0ef41Sopenharmony_ci      loader,
1611cb0ef41Sopenharmony_ci      NameFilterProc(args) if args else None,
1621cb0ef41Sopenharmony_ci      StatusFileFilterProc(None, None),
1631cb0ef41Sopenharmony_ci      # TODO(majeski): Improve sharding when combiner is present. Maybe select
1641cb0ef41Sopenharmony_ci      # different random seeds for shards instead of splitting tests.
1651cb0ef41Sopenharmony_ci      self._create_shard_proc(options),
1661cb0ef41Sopenharmony_ci      ExpectationProc(),
1671cb0ef41Sopenharmony_ci      combiner,
1681cb0ef41Sopenharmony_ci      self._create_fuzzer(fuzzer_rng, options),
1691cb0ef41Sopenharmony_ci      sigproc,
1701cb0ef41Sopenharmony_ci    ] + indicators + [
1711cb0ef41Sopenharmony_ci      results,
1721cb0ef41Sopenharmony_ci      self._create_timeout_proc(options),
1731cb0ef41Sopenharmony_ci      self._create_rerun_proc(options),
1741cb0ef41Sopenharmony_ci      execproc,
1751cb0ef41Sopenharmony_ci    ]
1761cb0ef41Sopenharmony_ci    self._prepare_procs(procs)
1771cb0ef41Sopenharmony_ci    loader.load_initial_tests(initial_batch_size=float('inf'))
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci    # TODO(majeski): maybe some notification from loader would be better?
1801cb0ef41Sopenharmony_ci    if combiner:
1811cb0ef41Sopenharmony_ci      combiner.generate_initial_tests(options.j * 4)
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci    # This starts up worker processes and blocks until all tests are
1841cb0ef41Sopenharmony_ci    # processed.
1851cb0ef41Sopenharmony_ci    execproc.run()
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci    for indicator in indicators:
1881cb0ef41Sopenharmony_ci      indicator.finished()
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci    print('>>> %d tests ran' % results.total)
1911cb0ef41Sopenharmony_ci    if results.failed:
1921cb0ef41Sopenharmony_ci      return utils.EXIT_CODE_FAILURES
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci    # Indicate if a SIGINT or SIGTERM happened.
1951cb0ef41Sopenharmony_ci    return sigproc.exit_code
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  def _is_testsuite_supported(self, suite, options):
1981cb0ef41Sopenharmony_ci    return not options.combine_tests or suite.test_combiner_available()
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  def _create_combiner(self, rng, options):
2011cb0ef41Sopenharmony_ci    if not options.combine_tests:
2021cb0ef41Sopenharmony_ci      return None
2031cb0ef41Sopenharmony_ci    return CombinerProc(rng, options.combine_min, options.combine_max,
2041cb0ef41Sopenharmony_ci                        options.tests_count)
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci  def _create_fuzzer(self, rng, options):
2071cb0ef41Sopenharmony_ci    return fuzzer.FuzzerProc(
2081cb0ef41Sopenharmony_ci        rng,
2091cb0ef41Sopenharmony_ci        self._tests_count(options),
2101cb0ef41Sopenharmony_ci        self._create_fuzzer_configs(options),
2111cb0ef41Sopenharmony_ci        self._disable_analysis(options),
2121cb0ef41Sopenharmony_ci    )
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci  def _tests_count(self, options):
2151cb0ef41Sopenharmony_ci    if options.combine_tests:
2161cb0ef41Sopenharmony_ci      return 1
2171cb0ef41Sopenharmony_ci    return options.tests_count
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci  def _disable_analysis(self, options):
2201cb0ef41Sopenharmony_ci    """Disable analysis phase when options are used that don't support it."""
2211cb0ef41Sopenharmony_ci    return options.combine_tests
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci  def _create_fuzzer_configs(self, options):
2241cb0ef41Sopenharmony_ci    fuzzers = []
2251cb0ef41Sopenharmony_ci    def add(name, prob, *args):
2261cb0ef41Sopenharmony_ci      if prob:
2271cb0ef41Sopenharmony_ci        fuzzers.append(fuzzer.create_fuzzer_config(name, prob, *args))
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci    add('compaction', options.stress_compaction)
2301cb0ef41Sopenharmony_ci    add('marking', options.stress_marking)
2311cb0ef41Sopenharmony_ci    add('scavenge', options.stress_scavenge)
2321cb0ef41Sopenharmony_ci    add('gc_interval', options.stress_gc)
2331cb0ef41Sopenharmony_ci    add('stack', options.stress_stack_size)
2341cb0ef41Sopenharmony_ci    add('threads', options.stress_thread_pool_size)
2351cb0ef41Sopenharmony_ci    add('delay', options.stress_delay_tasks)
2361cb0ef41Sopenharmony_ci    add('deopt', options.stress_deopt, options.stress_deopt_min)
2371cb0ef41Sopenharmony_ci    return fuzzers
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ciif __name__ == '__main__':
2411cb0ef41Sopenharmony_ci  sys.exit(NumFuzzer().execute())
242