summaryrefslogtreecommitdiffstats
path: root/js/src/tests/lib/tests.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /js/src/tests/lib/tests.py
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/lib/tests.py')
-rw-r--r--js/src/tests/lib/tests.py334
1 files changed, 334 insertions, 0 deletions
diff --git a/js/src/tests/lib/tests.py b/js/src/tests/lib/tests.py
new file mode 100644
index 0000000000..574b48b642
--- /dev/null
+++ b/js/src/tests/lib/tests.py
@@ -0,0 +1,334 @@
+# Library for JSTest tests.
+#
+# This contains classes that represent an individual test, including
+# metadata, and know how to run the tests and determine failures.
+
+import os
+import sys
+from contextlib import contextmanager
+
+# When run on tbpl, we run each test multiple times with the following
+# arguments.
+JITFLAGS = {
+ "all": [
+ [], # no flags, normal baseline and ion
+ [
+ "--ion-eager",
+ "--ion-offthread-compile=off", # implies --baseline-eager
+ "--more-compartments",
+ ],
+ [
+ "--ion-eager",
+ "--ion-offthread-compile=off",
+ "--ion-check-range-analysis",
+ "--ion-extra-checks",
+ "--no-sse3",
+ "--no-threads",
+ ],
+ ["--baseline-eager", "--write-protect-code=off"],
+ ["--no-blinterp", "--no-baseline", "--no-ion", "--more-compartments"],
+ ["--blinterp-eager"],
+ ],
+ # Like 'all' above but for jstests. This has fewer jit-specific
+ # configurations.
+ "jstests": [
+ [], # no flags, normal baseline and ion
+ [
+ "--ion-eager",
+ "--ion-offthread-compile=off", # implies --baseline-eager
+ "--more-compartments",
+ ],
+ ["--baseline-eager", "--write-protect-code=off"],
+ ["--no-blinterp", "--no-baseline", "--no-ion", "--more-compartments"],
+ ],
+ # used by jit_test.py
+ "ion": [
+ ["--baseline-eager", "--write-protect-code=off"],
+ ["--ion-eager", "--ion-offthread-compile=off", "--more-compartments"],
+ ],
+ # Run reduced variants on debug builds, since they take longer time.
+ "debug": [
+ [], # no flags, normal baseline and ion
+ [
+ "--ion-eager",
+ "--ion-offthread-compile=off", # implies --baseline-eager
+ "--more-compartments",
+ ],
+ ["--baseline-eager", "--write-protect-code=off"],
+ ],
+ # Cover cases useful for tsan. Note that we test --ion-eager without
+ # --ion-offthread-compile=off here, because it helps catch races.
+ "tsan": [
+ [],
+ [
+ "--ion-eager",
+ "--ion-check-range-analysis",
+ "--ion-extra-checks",
+ "--no-sse3",
+ ],
+ ["--no-blinterp", "--no-baseline", "--no-ion"],
+ ],
+ "baseline": [
+ ["--no-ion"],
+ ],
+ # Interpreter-only, for tools that cannot handle binary code generation.
+ "interp": [
+ [
+ "--no-blinterp",
+ "--no-baseline",
+ "--no-asmjs",
+ "--wasm-compiler=none",
+ "--no-native-regexp",
+ ]
+ ],
+ "none": [[]], # no flags, normal baseline and ion
+}
+
+
+def get_jitflags(variant, **kwargs):
+ if variant not in JITFLAGS:
+ print('Invalid jitflag: "{}"'.format(variant))
+ sys.exit(1)
+ if variant == "none" and "none" in kwargs:
+ return kwargs["none"]
+ return JITFLAGS[variant]
+
+
+def valid_jitflags():
+ return JITFLAGS.keys()
+
+
+def get_environment_overlay(js_shell, gc_zeal):
+ """
+ Build a dict of additional environment variables that must be set to run
+ tests successfully.
+ """
+
+ # When updating this also update |buildBrowserEnv| in layout/tools/reftest/runreftest.py.
+ env = {
+ # Force Pacific time zone to avoid failures in Date tests.
+ "TZ": "PST8PDT",
+ # Force date strings to English.
+ "LC_ALL": "en_US.UTF-8",
+ # Tell the shell to disable crash dialogs on windows.
+ "XRE_NO_WINDOWS_CRASH_DIALOG": "1",
+ }
+
+ # Add the binary's directory to the library search path so that we find the
+ # nspr and icu we built, instead of the platform supplied ones (or none at
+ # all on windows).
+ if sys.platform.startswith("linux"):
+ env["LD_LIBRARY_PATH"] = os.path.dirname(js_shell)
+ elif sys.platform.startswith("darwin"):
+ env["DYLD_LIBRARY_PATH"] = os.path.dirname(js_shell)
+ elif sys.platform.startswith("win"):
+ env["PATH"] = os.path.dirname(js_shell)
+
+ if gc_zeal:
+ env["JS_GC_ZEAL"] = gc_zeal
+
+ return env
+
+
+@contextmanager
+def change_env(env_overlay):
+ # Apply the overlaid environment and record the current state.
+ prior_env = {}
+ for key, val in env_overlay.items():
+ prior_env[key] = os.environ.get(key, None)
+ if "PATH" in key and key in os.environ:
+ os.environ[key] = "{}{}{}".format(val, os.pathsep, os.environ[key])
+ else:
+ os.environ[key] = val
+
+ try:
+ # Execute with the new environment.
+ yield
+
+ finally:
+ # Restore the prior environment.
+ for key, val in prior_env.items():
+ if val is not None:
+ os.environ[key] = val
+ else:
+ del os.environ[key]
+
+
+def get_cpu_count():
+ """
+ Guess at a reasonable parallelism count to set as the default for the
+ current machine and run.
+ """
+ # Python 2.6+
+ try:
+ import multiprocessing
+
+ return multiprocessing.cpu_count()
+ except (ImportError, NotImplementedError):
+ pass
+
+ # POSIX
+ try:
+ res = int(os.sysconf("SC_NPROCESSORS_ONLN"))
+ if res > 0:
+ return res
+ except (AttributeError, ValueError):
+ pass
+
+ # Windows
+ try:
+ res = int(os.environ["NUMBER_OF_PROCESSORS"])
+ if res > 0:
+ return res
+ except (KeyError, ValueError):
+ pass
+
+ return 1
+
+
+class RefTestCase(object):
+ """A test case consisting of a test and an expected result."""
+
+ def __init__(self, root, path, extra_helper_paths=None, wpt=None):
+ # str: path of the tests root dir
+ self.root = root
+ # str: path of JS file relative to tests root dir
+ self.path = path
+ # [str]: Extra options to pass to the shell
+ self.options = []
+ # [str]: JIT flags to pass to the shell
+ self.jitflags = []
+ # [str]: flags to never pass to the shell for this test
+ self.ignoredflags = []
+ # str or None: path to reflect-stringify.js file to test
+ # instead of actually running tests
+ self.test_reflect_stringify = None
+ # bool: True => test is module code
+ self.is_module = False
+ # bool: True => test is asynchronous and runs additional code after completing the first
+ # turn of the event loop.
+ self.is_async = False
+ # bool: True => run test, False => don't run
+ self.enable = True
+ # str?: Optional error type
+ self.error = None
+ # bool: expected result, True => pass
+ self.expect = True
+ # bool: True => ignore output as 'random'
+ self.random = False
+ # bool: True => test may run slowly
+ self.slow = False
+ # bool: True => test is test262 testcase with raw flag, that turns off
+ # running shell.js files inside test262
+ self.is_test262_raw = False
+
+ # Use self-hosted XDR instead of parsing the source stored in the binary.
+ # str?: Path computed when generating the command
+ self.selfhosted_xdr_path = None
+ # str: XDR mode (= "off", "encode", "decode") to use with the
+ # self-hosted code.
+ self.selfhosted_xdr_mode = "off"
+
+ # The terms parsed to produce the above properties.
+ self.terms = None
+
+ # The tag between |...| in the test header.
+ self.tag = None
+
+ # Anything occuring after -- in the test header.
+ self.comment = None
+
+ self.extra_helper_paths = extra_helper_paths or []
+ self.wpt = wpt
+
+ def prefix_command(self):
+ """Return the '-f' options needed to run a test with the given path."""
+ path = self.path
+ prefix = []
+ while path != "":
+ assert path != "/"
+ path = os.path.dirname(path)
+
+ if self.is_test262_raw and path != "":
+ # Skip running shell.js under test262 if the test has raw flag.
+ # Top-level shell.js is still necessary to define reportCompare.
+ continue
+
+ shell_path = os.path.join(self.root, path, "shell.js")
+ if os.path.exists(shell_path):
+ prefix.append(shell_path)
+ prefix.append("-f")
+ prefix.reverse()
+
+ for extra_path in self.extra_helper_paths:
+ prefix.append("-f")
+ prefix.append(extra_path)
+
+ return prefix
+
+ def abs_path(self):
+ return os.path.join(self.root, self.path)
+
+ def get_command(self, prefix, tempdir):
+ cmd = prefix + self.jitflags + self.options + self.prefix_command()
+ # Note: The tempdir provided as argument is managed by the caller
+ # should remain alive as long as the test harness. Therefore, the XDR
+ # content of the self-hosted code would be accessible to all JS Shell
+ # instances.
+ if self.selfhosted_xdr_mode != "off":
+ self.selfhosted_xdr_path = os.path.join(tempdir, "shell.xdr")
+ cmd += [
+ "--selfhosted-xdr-path",
+ self.selfhosted_xdr_path,
+ "--selfhosted-xdr-mode",
+ self.selfhosted_xdr_mode,
+ ]
+ if self.test_reflect_stringify is not None:
+ cmd += [self.test_reflect_stringify, "--check", self.abs_path()]
+ elif self.is_module:
+ cmd += ["--module", self.abs_path()]
+ else:
+ cmd += ["-f", self.abs_path()]
+ for flag in self.ignoredflags:
+ if flag in cmd:
+ cmd.remove(flag)
+ return cmd
+
+ def __str__(self):
+ ans = self.path
+ if not self.enable:
+ ans += ", skip"
+ if self.error is not None:
+ ans += ", error=" + self.error
+ if not self.expect:
+ ans += ", fails"
+ if self.random:
+ ans += ", random"
+ if self.slow:
+ ans += ", slow"
+ if "-d" in self.options:
+ ans += ", debugMode"
+ return ans
+
+ @staticmethod
+ def build_js_cmd_prefix(js_path, js_args, debugger_prefix):
+ parts = []
+ if debugger_prefix:
+ parts += debugger_prefix
+ parts.append(js_path)
+ if js_args:
+ parts += js_args
+ return parts
+
+ def __cmp__(self, other):
+ if self.path == other.path:
+ return 0
+ elif self.path < other.path:
+ return -1
+ return 1
+
+ def __hash__(self):
+ return self.path.__hash__()
+
+ def __repr__(self):
+ return "<lib.tests.RefTestCase %s>" % (self.path,)