11cb0ef41Sopenharmony_ci# Copyright 2012 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci# Redistribution and use in source and binary forms, with or without
31cb0ef41Sopenharmony_ci# modification, are permitted provided that the following conditions are
41cb0ef41Sopenharmony_ci# met:
51cb0ef41Sopenharmony_ci#
61cb0ef41Sopenharmony_ci#     * Redistributions of source code must retain the above copyright
71cb0ef41Sopenharmony_ci#       notice, this list of conditions and the following disclaimer.
81cb0ef41Sopenharmony_ci#     * Redistributions in binary form must reproduce the above
91cb0ef41Sopenharmony_ci#       copyright notice, this list of conditions and the following
101cb0ef41Sopenharmony_ci#       disclaimer in the documentation and/or other materials provided
111cb0ef41Sopenharmony_ci#       with the distribution.
121cb0ef41Sopenharmony_ci#     * Neither the name of Google Inc. nor the names of its
131cb0ef41Sopenharmony_ci#       contributors may be used to endorse or promote products derived
141cb0ef41Sopenharmony_ci#       from this software without specific prior written permission.
151cb0ef41Sopenharmony_ci#
161cb0ef41Sopenharmony_ci# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171cb0ef41Sopenharmony_ci# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181cb0ef41Sopenharmony_ci# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191cb0ef41Sopenharmony_ci# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201cb0ef41Sopenharmony_ci# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211cb0ef41Sopenharmony_ci# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221cb0ef41Sopenharmony_ci# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231cb0ef41Sopenharmony_ci# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241cb0ef41Sopenharmony_ci# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251cb0ef41Sopenharmony_ci# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261cb0ef41Sopenharmony_ci# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciimport copy
291cb0ef41Sopenharmony_ciimport os
301cb0ef41Sopenharmony_ciimport re
311cb0ef41Sopenharmony_ciimport shlex
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_cifrom testrunner.outproc import base as outproc
341cb0ef41Sopenharmony_cifrom testrunner.local import command
351cb0ef41Sopenharmony_cifrom testrunner.local import statusfile
361cb0ef41Sopenharmony_cifrom testrunner.local import utils
371cb0ef41Sopenharmony_cifrom testrunner.local.variants import ALL_VARIANT_FLAGS
381cb0ef41Sopenharmony_cifrom testrunner.local.variants import INCOMPATIBLE_FLAGS_PER_VARIANT
391cb0ef41Sopenharmony_cifrom testrunner.local.variants import INCOMPATIBLE_FLAGS_PER_BUILD_VARIABLE
401cb0ef41Sopenharmony_cifrom testrunner.local.variants import INCOMPATIBLE_FLAGS_PER_EXTRA_FLAG
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ciFLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci# Patterns for additional resource files on Android. Files that are not covered
461cb0ef41Sopenharmony_ci# by one of the other patterns below will be specified in the resources section.
471cb0ef41Sopenharmony_ciRESOURCES_PATTERN = re.compile(r"//\s+Resources:(.*)")
481cb0ef41Sopenharmony_ci# Pattern to auto-detect files to push on Android for statements like:
491cb0ef41Sopenharmony_ci# load("path/to/file.js")
501cb0ef41Sopenharmony_ci# d8.file.execute("path/to/file.js")
511cb0ef41Sopenharmony_ciLOAD_PATTERN = re.compile(
521cb0ef41Sopenharmony_ci    r"(?:execute|load|readbuffer|read)\((?:'|\")([^'\"]+)(?:'|\")\)")
531cb0ef41Sopenharmony_ci# Pattern to auto-detect files to push on Android for statements like:
541cb0ef41Sopenharmony_ci# import foobar from "path/to/file.js"
551cb0ef41Sopenharmony_ci# import {foo, bar} from "path/to/file.js"
561cb0ef41Sopenharmony_ci# export {"foo" as "bar"} from "path/to/file.js"
571cb0ef41Sopenharmony_ciMODULE_FROM_RESOURCES_PATTERN = re.compile(
581cb0ef41Sopenharmony_ci    r"(?:import|export).*?from\s*\(?['\"]([^'\"]+)['\"]",
591cb0ef41Sopenharmony_ci    re.MULTILINE | re.DOTALL)
601cb0ef41Sopenharmony_ci# Pattern to detect files to push on Android for statements like:
611cb0ef41Sopenharmony_ci# import "path/to/file.js"
621cb0ef41Sopenharmony_ci# import("module.mjs").catch()...
631cb0ef41Sopenharmony_ciMODULE_IMPORT_RESOURCES_PATTERN = re.compile(
641cb0ef41Sopenharmony_ci    r"import\s*\(?['\"]([^'\"]+)['\"]",
651cb0ef41Sopenharmony_ci    re.MULTILINE | re.DOTALL)
661cb0ef41Sopenharmony_ci# Pattern to detect and strip test262 frontmatter from tests to prevent false
671cb0ef41Sopenharmony_ci# positives for MODULE_RESOURCES_PATTERN above.
681cb0ef41Sopenharmony_ciTEST262_FRONTMATTER_PATTERN = re.compile(r"/\*---.*?---\*/", re.DOTALL)
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ciTIMEOUT_LONG = "long"
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_cidef read_file(file):
731cb0ef41Sopenharmony_ci  with open(file, encoding='ISO-8859-1') as f:
741cb0ef41Sopenharmony_ci    return f.read()
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ciclass TestCase(object):
771cb0ef41Sopenharmony_ci  def __init__(self, suite, path, name, test_config):
781cb0ef41Sopenharmony_ci    self.suite = suite        # TestSuite object
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci    self.path = path          # string, e.g. 'div-mod', 'test-api/foo'
811cb0ef41Sopenharmony_ci    self.name = name          # string that identifies test in the status file
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci    self.variant = None       # name of the used testing variant
841cb0ef41Sopenharmony_ci    self.variant_flags = []   # list of strings, flags specific to this test
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci    # Fields used by the test processors.
871cb0ef41Sopenharmony_ci    self.origin = None # Test that this test is subtest of.
881cb0ef41Sopenharmony_ci    self.processor = None # Processor that created this subtest.
891cb0ef41Sopenharmony_ci    self.procid = '%s/%s' % (self.suite.name, self.name) # unique id
901cb0ef41Sopenharmony_ci    self.keep_output = False # Can output of this test be dropped
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci    # Test config contains information needed to build the command.
931cb0ef41Sopenharmony_ci    self._test_config = test_config
941cb0ef41Sopenharmony_ci    self._random_seed = None # Overrides test config value if not None
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci    # Outcomes
971cb0ef41Sopenharmony_ci    self._statusfile_outcomes = None
981cb0ef41Sopenharmony_ci    self._expected_outcomes = None
991cb0ef41Sopenharmony_ci    self._checked_flag_contradictions = False
1001cb0ef41Sopenharmony_ci    self._statusfile_flags = None
1011cb0ef41Sopenharmony_ci    self.expected_failure_reason = None
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci    self._prepare_outcomes()
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  def create_subtest(self, processor, subtest_id, variant=None, flags=None,
1061cb0ef41Sopenharmony_ci                     keep_output=False, random_seed=None):
1071cb0ef41Sopenharmony_ci    subtest = copy.copy(self)
1081cb0ef41Sopenharmony_ci    subtest.origin = self
1091cb0ef41Sopenharmony_ci    subtest.processor = processor
1101cb0ef41Sopenharmony_ci    subtest.procid += '.%s' % subtest_id
1111cb0ef41Sopenharmony_ci    subtest.keep_output |= keep_output
1121cb0ef41Sopenharmony_ci    if random_seed:
1131cb0ef41Sopenharmony_ci      subtest._random_seed = random_seed
1141cb0ef41Sopenharmony_ci    if flags:
1151cb0ef41Sopenharmony_ci      subtest.variant_flags = subtest.variant_flags + flags
1161cb0ef41Sopenharmony_ci    if variant is not None:
1171cb0ef41Sopenharmony_ci      assert self.variant is None
1181cb0ef41Sopenharmony_ci      subtest.variant = variant
1191cb0ef41Sopenharmony_ci      subtest._prepare_outcomes()
1201cb0ef41Sopenharmony_ci    return subtest
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci  def _prepare_outcomes(self, force_update=True):
1231cb0ef41Sopenharmony_ci    if force_update or self._statusfile_outcomes is None:
1241cb0ef41Sopenharmony_ci      def is_flag(outcome):
1251cb0ef41Sopenharmony_ci        return outcome.startswith('--')
1261cb0ef41Sopenharmony_ci      def not_flag(outcome):
1271cb0ef41Sopenharmony_ci        return not is_flag(outcome)
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci      outcomes = self.suite.statusfile.get_outcomes(self.name, self.variant)
1301cb0ef41Sopenharmony_ci      self._statusfile_outcomes = list(filter(not_flag, outcomes))
1311cb0ef41Sopenharmony_ci      self._statusfile_flags = list(filter(is_flag, outcomes))
1321cb0ef41Sopenharmony_ci    self._expected_outcomes = (
1331cb0ef41Sopenharmony_ci      self._parse_status_file_outcomes(self._statusfile_outcomes))
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci  def _parse_status_file_outcomes(self, outcomes):
1361cb0ef41Sopenharmony_ci    if (statusfile.FAIL_SLOPPY in outcomes and
1371cb0ef41Sopenharmony_ci        '--use-strict' not in self.variant_flags):
1381cb0ef41Sopenharmony_ci      return outproc.OUTCOMES_FAIL
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci    expected_outcomes = []
1411cb0ef41Sopenharmony_ci    if (statusfile.FAIL in outcomes or
1421cb0ef41Sopenharmony_ci        statusfile.FAIL_OK in outcomes):
1431cb0ef41Sopenharmony_ci      expected_outcomes.append(statusfile.FAIL)
1441cb0ef41Sopenharmony_ci    if statusfile.CRASH in outcomes:
1451cb0ef41Sopenharmony_ci      expected_outcomes.append(statusfile.CRASH)
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci    # Do not add PASS if there is nothing else. Empty outcomes are converted to
1481cb0ef41Sopenharmony_ci    # the global [PASS].
1491cb0ef41Sopenharmony_ci    if expected_outcomes and statusfile.PASS in outcomes:
1501cb0ef41Sopenharmony_ci      expected_outcomes.append(statusfile.PASS)
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci    # Avoid creating multiple instances of a list with a single FAIL.
1531cb0ef41Sopenharmony_ci    if expected_outcomes == outproc.OUTCOMES_FAIL:
1541cb0ef41Sopenharmony_ci      return outproc.OUTCOMES_FAIL
1551cb0ef41Sopenharmony_ci    return expected_outcomes or outproc.OUTCOMES_PASS
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  def allow_timeouts(self):
1581cb0ef41Sopenharmony_ci    if self.expected_outcomes == outproc.OUTCOMES_PASS:
1591cb0ef41Sopenharmony_ci      self._expected_outcomes = outproc.OUTCOMES_PASS_OR_TIMEOUT
1601cb0ef41Sopenharmony_ci    elif self.expected_outcomes == outproc.OUTCOMES_FAIL:
1611cb0ef41Sopenharmony_ci      self._expected_outcomes = outproc.OUTCOMES_FAIL_OR_TIMEOUT
1621cb0ef41Sopenharmony_ci    elif statusfile.TIMEOUT not in self.expected_outcomes:
1631cb0ef41Sopenharmony_ci      self._expected_outcomes = (
1641cb0ef41Sopenharmony_ci          self.expected_outcomes + [statusfile.TIMEOUT])
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  def allow_pass(self):
1671cb0ef41Sopenharmony_ci    if self.expected_outcomes == outproc.OUTCOMES_TIMEOUT:
1681cb0ef41Sopenharmony_ci      self._expected_outcomes = outproc.OUTCOMES_PASS_OR_TIMEOUT
1691cb0ef41Sopenharmony_ci    elif self.expected_outcomes == outproc.OUTCOMES_FAIL:
1701cb0ef41Sopenharmony_ci      self._expected_outcomes = outproc.OUTCOMES_FAIL_OR_PASS
1711cb0ef41Sopenharmony_ci    elif statusfile.PASS not in self.expected_outcomes:
1721cb0ef41Sopenharmony_ci      self._expected_outcomes = (
1731cb0ef41Sopenharmony_ci          self.expected_outcomes + [statusfile.PASS])
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  @property
1761cb0ef41Sopenharmony_ci  def expected_outcomes(self):
1771cb0ef41Sopenharmony_ci    def is_flag(maybe_flag):
1781cb0ef41Sopenharmony_ci      return maybe_flag.startswith("--")  # Best-effort heuristic.
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci    # Filter to flags, e.g.: ["--foo", "3", "--bar"] -> ["--foo", "--bar"].
1811cb0ef41Sopenharmony_ci    def filter_flags(normalized_flags):
1821cb0ef41Sopenharmony_ci      return [f for f in normalized_flags if is_flag(f)];
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci    def normalize_flag(flag):
1851cb0ef41Sopenharmony_ci      return flag.replace("_", "-").replace("--no-", "--no")
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci    def normalize_flags(flags):
1881cb0ef41Sopenharmony_ci      return [normalize_flag(flag) for flag in filter_flags(flags)]
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci    # Note this can get it wrong if the flag name starts with the characters
1911cb0ef41Sopenharmony_ci    # "--no" where "no" is part of the flag name, e.g. "--nobodys-perfect".
1921cb0ef41Sopenharmony_ci    # In that case the negation "--bodys-perfect" would be returned. This is
1931cb0ef41Sopenharmony_ci    # a weakness we accept and hope to never run into.
1941cb0ef41Sopenharmony_ci    def negate_flag(normalized_flag):
1951cb0ef41Sopenharmony_ci      return ("--" + normalized_flag[4:] if normalized_flag.startswith("--no")
1961cb0ef41Sopenharmony_ci              else "--no" + normalized_flag[2:])
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci    def negate_flags(normalized_flags):
1991cb0ef41Sopenharmony_ci      return [negate_flag(flag) for flag in normalized_flags]
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci    def has_flag(conflicting_flag, flags):
2021cb0ef41Sopenharmony_ci      conflicting_flag = normalize_flag(conflicting_flag)
2031cb0ef41Sopenharmony_ci      if conflicting_flag in flags:
2041cb0ef41Sopenharmony_ci        return True
2051cb0ef41Sopenharmony_ci      if conflicting_flag.endswith("*"):
2061cb0ef41Sopenharmony_ci        return any(flag.startswith(conflicting_flag[:-1]) for flag in flags)
2071cb0ef41Sopenharmony_ci      return False
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci    def check_flags(incompatible_flags, actual_flags, rule):
2101cb0ef41Sopenharmony_ci      for incompatible_flag in incompatible_flags:
2111cb0ef41Sopenharmony_ci          if has_flag(incompatible_flag, actual_flags):
2121cb0ef41Sopenharmony_ci            self._statusfile_outcomes = outproc.OUTCOMES_FAIL
2131cb0ef41Sopenharmony_ci            self._expected_outcomes = outproc.OUTCOMES_FAIL
2141cb0ef41Sopenharmony_ci            self.expected_failure_reason = ("Rule " + rule + " in " +
2151cb0ef41Sopenharmony_ci                "tools/testrunner/local/variants.py expected a flag " +
2161cb0ef41Sopenharmony_ci                "contradiction error with " + incompatible_flag + ".")
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci    if not self._checked_flag_contradictions:
2191cb0ef41Sopenharmony_ci      self._checked_flag_contradictions = True
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci      file_specific_flags = (self._get_source_flags() + self._get_suite_flags()
2221cb0ef41Sopenharmony_ci                             + self._get_statusfile_flags())
2231cb0ef41Sopenharmony_ci      file_specific_flags = normalize_flags(file_specific_flags)
2241cb0ef41Sopenharmony_ci      extra_flags = normalize_flags(self._get_extra_flags())
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci      # Contradiction: flags contains both a flag --foo and its negation
2271cb0ef41Sopenharmony_ci      # --no-foo.
2281cb0ef41Sopenharmony_ci      if self.variant in ALL_VARIANT_FLAGS:
2291cb0ef41Sopenharmony_ci        for flags in ALL_VARIANT_FLAGS[self.variant]:
2301cb0ef41Sopenharmony_ci          all_flags = (file_specific_flags + extra_flags
2311cb0ef41Sopenharmony_ci                       + normalize_flags(flags))
2321cb0ef41Sopenharmony_ci          check_flags(negate_flags(all_flags), all_flags, "Flag negations")
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci      # Contradiction: flags specified through the "Flags:" annotation are
2351cb0ef41Sopenharmony_ci      # incompatible with the variant.
2361cb0ef41Sopenharmony_ci      if self.variant in INCOMPATIBLE_FLAGS_PER_VARIANT:
2371cb0ef41Sopenharmony_ci        check_flags(INCOMPATIBLE_FLAGS_PER_VARIANT[self.variant], file_specific_flags,
2381cb0ef41Sopenharmony_ci                    "INCOMPATIBLE_FLAGS_PER_VARIANT[\""+self.variant+"\"]")
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci      # Contradiction: flags specified through the "Flags:" annotation are
2411cb0ef41Sopenharmony_ci      # incompatible with the build.
2421cb0ef41Sopenharmony_ci      for variable, incompatible_flags in INCOMPATIBLE_FLAGS_PER_BUILD_VARIABLE.items():
2431cb0ef41Sopenharmony_ci        if self.suite.statusfile.variables[variable]:
2441cb0ef41Sopenharmony_ci            check_flags(incompatible_flags, file_specific_flags,
2451cb0ef41Sopenharmony_ci              "INCOMPATIBLE_FLAGS_PER_BUILD_VARIABLE[\""+variable+"\"]")
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci      # Contradiction: flags passed through --extra-flags are incompatible.
2481cb0ef41Sopenharmony_ci      for extra_flag, incompatible_flags in INCOMPATIBLE_FLAGS_PER_EXTRA_FLAG.items():
2491cb0ef41Sopenharmony_ci        if has_flag(extra_flag, extra_flags):
2501cb0ef41Sopenharmony_ci            check_flags(incompatible_flags, file_specific_flags,
2511cb0ef41Sopenharmony_ci              "INCOMPATIBLE_FLAGS_PER_EXTRA_FLAG[\""+extra_flag+"\"]")
2521cb0ef41Sopenharmony_ci    return self._expected_outcomes
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  @property
2551cb0ef41Sopenharmony_ci  def do_skip(self):
2561cb0ef41Sopenharmony_ci    return (statusfile.SKIP in self._statusfile_outcomes and
2571cb0ef41Sopenharmony_ci            not self.suite.test_config.run_skipped)
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci  @property
2601cb0ef41Sopenharmony_ci  def is_heavy(self):
2611cb0ef41Sopenharmony_ci    return statusfile.HEAVY in self._statusfile_outcomes
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci  @property
2641cb0ef41Sopenharmony_ci  def is_slow(self):
2651cb0ef41Sopenharmony_ci    return self.is_heavy or statusfile.SLOW in self._statusfile_outcomes
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci  @property
2681cb0ef41Sopenharmony_ci  def is_fail_ok(self):
2691cb0ef41Sopenharmony_ci    return statusfile.FAIL_OK in self._statusfile_outcomes
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci  @property
2721cb0ef41Sopenharmony_ci  def is_pass_or_fail(self):
2731cb0ef41Sopenharmony_ci    return (statusfile.PASS in self._statusfile_outcomes and
2741cb0ef41Sopenharmony_ci            statusfile.FAIL in self._statusfile_outcomes and
2751cb0ef41Sopenharmony_ci            statusfile.CRASH not in self._statusfile_outcomes)
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci  @property
2781cb0ef41Sopenharmony_ci  def is_fail(self):
2791cb0ef41Sopenharmony_ci     return (statusfile.FAIL in self._statusfile_outcomes and
2801cb0ef41Sopenharmony_ci             statusfile.PASS not in self._statusfile_outcomes)
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci  @property
2831cb0ef41Sopenharmony_ci  def only_standard_variant(self):
2841cb0ef41Sopenharmony_ci    return statusfile.NO_VARIANTS in self._statusfile_outcomes
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ci  def get_command(self):
2871cb0ef41Sopenharmony_ci    params = self._get_cmd_params()
2881cb0ef41Sopenharmony_ci    env = self._get_cmd_env()
2891cb0ef41Sopenharmony_ci    shell = self.get_shell()
2901cb0ef41Sopenharmony_ci    if utils.IsWindows():
2911cb0ef41Sopenharmony_ci      shell += '.exe'
2921cb0ef41Sopenharmony_ci    shell_flags = self._get_shell_flags()
2931cb0ef41Sopenharmony_ci    timeout = self._get_timeout(params)
2941cb0ef41Sopenharmony_ci    return self._create_cmd(shell, shell_flags + params, env, timeout)
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci  def _get_cmd_params(self):
2971cb0ef41Sopenharmony_ci    """Gets command parameters and combines them in the following order:
2981cb0ef41Sopenharmony_ci      - files [empty by default]
2991cb0ef41Sopenharmony_ci      - random seed
3001cb0ef41Sopenharmony_ci      - mode flags (based on chosen mode)
3011cb0ef41Sopenharmony_ci      - extra flags (from command line)
3021cb0ef41Sopenharmony_ci      - user flags (variant/fuzzer flags)
3031cb0ef41Sopenharmony_ci      - source flags (from source code) [empty by default]
3041cb0ef41Sopenharmony_ci      - test-suite flags
3051cb0ef41Sopenharmony_ci      - statusfile flags
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci    The best way to modify how parameters are created is to only override
3081cb0ef41Sopenharmony_ci    methods for getting partial parameters.
3091cb0ef41Sopenharmony_ci    """
3101cb0ef41Sopenharmony_ci    return (
3111cb0ef41Sopenharmony_ci        self._get_files_params() +
3121cb0ef41Sopenharmony_ci        self._get_random_seed_flags() +
3131cb0ef41Sopenharmony_ci        self._get_mode_flags() +
3141cb0ef41Sopenharmony_ci        self._get_extra_flags() +
3151cb0ef41Sopenharmony_ci        self._get_variant_flags() +
3161cb0ef41Sopenharmony_ci        self._get_source_flags() +
3171cb0ef41Sopenharmony_ci        self._get_suite_flags() +
3181cb0ef41Sopenharmony_ci        self._get_statusfile_flags()
3191cb0ef41Sopenharmony_ci    )
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci  def _get_cmd_env(self):
3221cb0ef41Sopenharmony_ci    return {}
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci  def _get_files_params(self):
3251cb0ef41Sopenharmony_ci    return []
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci  def _get_timeout_param(self):
3281cb0ef41Sopenharmony_ci    return None
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci  def _get_random_seed_flags(self):
3311cb0ef41Sopenharmony_ci    return ['--random-seed=%d' % self.random_seed]
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci  @property
3341cb0ef41Sopenharmony_ci  def random_seed(self):
3351cb0ef41Sopenharmony_ci    return self._random_seed or self._test_config.random_seed
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci  def _get_extra_flags(self):
3381cb0ef41Sopenharmony_ci    return self._test_config.extra_flags
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci  def _get_variant_flags(self):
3411cb0ef41Sopenharmony_ci    return self.variant_flags
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci  def _get_statusfile_flags(self):
3441cb0ef41Sopenharmony_ci    """Gets runtime flags from a status file.
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci    Every outcome that starts with "--" is a flag.
3471cb0ef41Sopenharmony_ci    """
3481cb0ef41Sopenharmony_ci    return self._statusfile_flags
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_ci  def _get_mode_flags(self):
3511cb0ef41Sopenharmony_ci    return self._test_config.mode_flags
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci  def _get_source_flags(self):
3541cb0ef41Sopenharmony_ci    return []
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci  def _get_suite_flags(self):
3571cb0ef41Sopenharmony_ci    return []
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ci  def _get_shell_flags(self):
3601cb0ef41Sopenharmony_ci    return []
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci  def _get_timeout(self, params):
3631cb0ef41Sopenharmony_ci    timeout = self._test_config.timeout
3641cb0ef41Sopenharmony_ci    if "--stress-opt" in params:
3651cb0ef41Sopenharmony_ci      timeout *= 4
3661cb0ef41Sopenharmony_ci    if "--jitless" in params:
3671cb0ef41Sopenharmony_ci      timeout *= 2
3681cb0ef41Sopenharmony_ci    if "--no-opt" in params:
3691cb0ef41Sopenharmony_ci      timeout *= 2
3701cb0ef41Sopenharmony_ci    if "--noenable-vfp3" in params:
3711cb0ef41Sopenharmony_ci      timeout *= 2
3721cb0ef41Sopenharmony_ci    if self._get_timeout_param() == TIMEOUT_LONG:
3731cb0ef41Sopenharmony_ci      timeout *= 10
3741cb0ef41Sopenharmony_ci    if self.is_slow:
3751cb0ef41Sopenharmony_ci      timeout *= 4
3761cb0ef41Sopenharmony_ci    return timeout
3771cb0ef41Sopenharmony_ci
3781cb0ef41Sopenharmony_ci  def get_shell(self):
3791cb0ef41Sopenharmony_ci    raise NotImplementedError()
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ci  def _get_suffix(self):
3821cb0ef41Sopenharmony_ci    return '.js'
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci  def _create_cmd(self, shell, params, env, timeout):
3851cb0ef41Sopenharmony_ci    return command.Command(
3861cb0ef41Sopenharmony_ci      cmd_prefix=self._test_config.command_prefix,
3871cb0ef41Sopenharmony_ci      shell=os.path.abspath(os.path.join(self._test_config.shell_dir, shell)),
3881cb0ef41Sopenharmony_ci      args=params,
3891cb0ef41Sopenharmony_ci      env=env,
3901cb0ef41Sopenharmony_ci      timeout=timeout,
3911cb0ef41Sopenharmony_ci      verbose=self._test_config.verbose,
3921cb0ef41Sopenharmony_ci      resources_func=self._get_resources,
3931cb0ef41Sopenharmony_ci      handle_sigterm=True,
3941cb0ef41Sopenharmony_ci    )
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ci  def _parse_source_flags(self, source=None):
3971cb0ef41Sopenharmony_ci    source = source or self.get_source()
3981cb0ef41Sopenharmony_ci    flags = []
3991cb0ef41Sopenharmony_ci    for match in re.findall(FLAGS_PATTERN, source):
4001cb0ef41Sopenharmony_ci      flags += shlex.split(match.strip())
4011cb0ef41Sopenharmony_ci    return flags
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ci  def is_source_available(self):
4041cb0ef41Sopenharmony_ci    return self._get_source_path() is not None
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci  def get_source(self):
4071cb0ef41Sopenharmony_ci    return read_file(self._get_source_path())
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci  def _get_source_path(self):
4101cb0ef41Sopenharmony_ci    return None
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci  def _get_resources(self):
4131cb0ef41Sopenharmony_ci    """Returns a list of absolute paths with additional files needed by the
4141cb0ef41Sopenharmony_ci    test case.
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci    Used to push additional files to Android devices.
4171cb0ef41Sopenharmony_ci    """
4181cb0ef41Sopenharmony_ci    return []
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_ci  def skip_predictable(self):
4211cb0ef41Sopenharmony_ci    """Returns True if the test case is not suitable for predictable testing."""
4221cb0ef41Sopenharmony_ci    return True
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ci  @property
4251cb0ef41Sopenharmony_ci  def output_proc(self):
4261cb0ef41Sopenharmony_ci    if self.expected_outcomes is outproc.OUTCOMES_PASS:
4271cb0ef41Sopenharmony_ci      return outproc.DEFAULT
4281cb0ef41Sopenharmony_ci    return outproc.OutProc(self.expected_outcomes)
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci  def __cmp__(self, other):
4311cb0ef41Sopenharmony_ci    # Make sure that test cases are sorted correctly if sorted without
4321cb0ef41Sopenharmony_ci    # key function. But using a key function is preferred for speed.
4331cb0ef41Sopenharmony_ci    def cmp(x, y):
4341cb0ef41Sopenharmony_ci      return (x > y) - (x < y)
4351cb0ef41Sopenharmony_ci    return cmp(
4361cb0ef41Sopenharmony_ci        (self.suite.name, self.name, self.variant),
4371cb0ef41Sopenharmony_ci        (other.suite.name, other.name, other.variant)
4381cb0ef41Sopenharmony_ci    )
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ci  def __str__(self):
4411cb0ef41Sopenharmony_ci    return self.suite.name + '/' + self.name
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_ciclass D8TestCase(TestCase):
4451cb0ef41Sopenharmony_ci  def get_shell(self):
4461cb0ef41Sopenharmony_ci    return "d8"
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci  def _get_shell_flags(self):
4491cb0ef41Sopenharmony_ci    return ['--test']
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_ci  def _get_resources_for_file(self, file):
4521cb0ef41Sopenharmony_ci    """Returns for a given file a list of absolute paths of files needed by the
4531cb0ef41Sopenharmony_ci    given file.
4541cb0ef41Sopenharmony_ci    """
4551cb0ef41Sopenharmony_ci    source = read_file(file)
4561cb0ef41Sopenharmony_ci    result = []
4571cb0ef41Sopenharmony_ci    def add_path(path):
4581cb0ef41Sopenharmony_ci      result.append(os.path.abspath(path.replace('/', os.path.sep)))
4591cb0ef41Sopenharmony_ci    def add_import_path(import_path):
4601cb0ef41Sopenharmony_ci      add_path(os.path.normpath(
4611cb0ef41Sopenharmony_ci        os.path.join(os.path.dirname(file), import_path)))
4621cb0ef41Sopenharmony_ci    def strip_test262_frontmatter(input):
4631cb0ef41Sopenharmony_ci      return TEST262_FRONTMATTER_PATTERN.sub('', input)
4641cb0ef41Sopenharmony_ci    for match in RESOURCES_PATTERN.finditer(source):
4651cb0ef41Sopenharmony_ci      # There are several resources per line. Relative to base dir.
4661cb0ef41Sopenharmony_ci      for path in match.group(1).strip().split():
4671cb0ef41Sopenharmony_ci        add_path(path)
4681cb0ef41Sopenharmony_ci    # Strip test262 frontmatter before looking for load() and import/export
4691cb0ef41Sopenharmony_ci    # statements.
4701cb0ef41Sopenharmony_ci    source = strip_test262_frontmatter(source)
4711cb0ef41Sopenharmony_ci    for match in LOAD_PATTERN.finditer(source):
4721cb0ef41Sopenharmony_ci      # Files in load statements are relative to base dir.
4731cb0ef41Sopenharmony_ci      add_path(match.group(1))
4741cb0ef41Sopenharmony_ci    # Imported files are relative to the file importing them.
4751cb0ef41Sopenharmony_ci    for match in MODULE_FROM_RESOURCES_PATTERN.finditer(source):
4761cb0ef41Sopenharmony_ci      add_import_path(match.group(1))
4771cb0ef41Sopenharmony_ci    for match in MODULE_IMPORT_RESOURCES_PATTERN.finditer(source):
4781cb0ef41Sopenharmony_ci      add_import_path(match.group(1))
4791cb0ef41Sopenharmony_ci    return result
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_ci  def _get_resources(self):
4821cb0ef41Sopenharmony_ci    """Returns the list of files needed by a test case."""
4831cb0ef41Sopenharmony_ci    if not self._get_source_path():
4841cb0ef41Sopenharmony_ci      return []
4851cb0ef41Sopenharmony_ci    result = set()
4861cb0ef41Sopenharmony_ci    to_check = [self._get_source_path()]
4871cb0ef41Sopenharmony_ci    # Recurse over all files until reaching a fixpoint.
4881cb0ef41Sopenharmony_ci    while to_check:
4891cb0ef41Sopenharmony_ci      next_resource = to_check.pop()
4901cb0ef41Sopenharmony_ci      result.add(next_resource)
4911cb0ef41Sopenharmony_ci      for resource in self._get_resources_for_file(next_resource):
4921cb0ef41Sopenharmony_ci        # Only add files that exist on disc. The pattens we check for give some
4931cb0ef41Sopenharmony_ci        # false positives otherwise.
4941cb0ef41Sopenharmony_ci        if resource not in result and os.path.exists(resource):
4951cb0ef41Sopenharmony_ci          to_check.append(resource)
4961cb0ef41Sopenharmony_ci    return sorted(list(result))
4971cb0ef41Sopenharmony_ci
4981cb0ef41Sopenharmony_ci  def skip_predictable(self):
4991cb0ef41Sopenharmony_ci    """Returns True if the test case is not suitable for predictable testing."""
5001cb0ef41Sopenharmony_ci    return (statusfile.FAIL in self.expected_outcomes or
5011cb0ef41Sopenharmony_ci            self.output_proc.negative)
502