Bug 1496297 - Implement skip-if in jit-tests. (r=jorendorff)
authorEric Faust <efausbmo@gmail.com>
Tue, 09 Oct 2018 15:41:50 -0700
changeset 496115 2a7a0b6b2bbf60b5be511cffec9a56e8650d18d5
parent 496114 f464268350266bad55c84d23f3b352b752679cad
child 496116 012e94d3d96c5513af221778411d331b308ee537
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1496297
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1496297 - Implement skip-if in jit-tests. (r=jorendorff)
js/src/tests/lib/jittests.py
--- a/js/src/tests/lib/jittests.py
+++ b/js/src/tests/lib/jittests.py
@@ -145,16 +145,20 @@ class JitTest:
         self.expect_status = 0
         # Exit status or error output.
         self.expect_crash = False
         self.is_module = False
         self.is_binast = False
         # Reflect.stringify implementation to test
         self.test_reflect_stringify = None
 
+        # Skip-if condition. We don't have a xulrunner, but we can ask the shell
+        # directly.
+        self.skip_if_cond = ''
+
         # Expected by the test runner. Always true for jit-tests.
         self.enable = True
 
     def copy(self):
         t = JitTest(self.path)
         t.jitflags = self.jitflags[:]
         t.slow = self.slow
         t.allow_oom = self.allow_oom
@@ -169,16 +173,17 @@ class JitTest:
         t.test_join = self.test_join
         t.expect_error = self.expect_error
         t.expect_status = self.expect_status
         t.expect_crash = self.expect_crash
         t.test_reflect_stringify = self.test_reflect_stringify
         t.enable = True
         t.is_module = self.is_module
         t.is_binast = self.is_binast
+        t.skip_if_cond = self.skip_if_cond
         return t
 
     def copy_and_extend_jitflags(self, variant):
         t = self.copy()
         t.jitflags.extend(variant)
         return t
 
     def copy_variants(self, variants):
@@ -190,16 +195,19 @@ class JitTest:
         # options.
         for join_opts in self.test_join:
             variants = variants + [opts + join_opts for opts in variants]
 
         # For each list of jit flags, make a copy of the test.
         return [self.copy_and_extend_jitflags(v) for v in variants]
 
     COOKIE = '|jit-test|'
+
+    # We would use 500019 (5k19), but quit() only accepts values up to 127, due to fuzzers
+    SKIPPED_EXIT_STATUS = 59
     CacheDir = JS_CACHE_DIR
     Directives = {}
 
     @classmethod
     def find_directives(cls, file_name):
         meta = ''
         line = open(file_name).readline()
         i = line.find(cls.COOKIE)
@@ -250,29 +258,39 @@ class JitTest:
                     continue
                 name, _, value = part.partition(':')
                 if value:
                     value = value.strip()
                     if name == 'error':
                         test.expect_error = value
                     elif name == 'exitstatus':
                         try:
-                            test.expect_status = int(value, 0)
+                            status = int(value, 0)
+                            if status == test.SKIPPED_EXIT_STATUS:
+                                print("warning: jit-tests uses {} as a sentinel"
+                                      " return value {}", test.SKIPPED_EXIT_STATUS, path)
+                            else:
+                                test.expect_status = status
                         except ValueError:
                             print("warning: couldn't parse exit status"
                                   " {}".format(value))
                     elif name == 'thread-count':
                         try:
                             test.jitflags.append('--thread-count={}'.format(
                                 int(value, 0)))
                         except ValueError:
                             print("warning: couldn't parse thread-count"
                                   " {}".format(value))
                     elif name == 'include':
                         test.other_includes.append(value)
+                    elif name == 'skip-if':
+                        # Ensure that skip-ifs are composable
+                        if test.skip_if_cond:
+                            test.skip_if_cond += " || "
+                        test.skip_if_cond += "({})".format(value)
                     else:
                         print('{}: warning: unrecognized |jit-test| attribute'
                               ' {}'.format(path, part))
                 else:
                     if name == 'slow':
                         test.slow = True
                     elif name == 'allow-oom':
                         test.allow_oom = True
@@ -347,16 +365,18 @@ class JitTest:
         # We may have specified '-a' or '-d' twice: once via --jitflags, once
         # via the "|jit-test|" line.  Remove dups because they are toggles.
         cmd = prefix + ['--js-cache', JitTest.CacheDir]
         cmd += list(set(self.jitflags))
         for expr in exprs:
             cmd += ['-e', expr]
         for inc in self.other_includes:
             cmd += ['-f', libdir + inc]
+        if self.skip_if_cond:
+            cmd += ['-e', "if ({}) quit({})".format(self.skip_if_cond, self.SKIPPED_EXIT_STATUS)]
         if self.is_module:
             cmd += ['--module-load-path', moduledir]
             cmd += ['--module', path]
         elif self.is_binast:
             # In builds with BinAST, this will run the test file. In builds without,
             # It's a no-op and the tests will silently pass.
             cmd += ['-B', path]
         elif self.test_reflect_stringify is None:
@@ -434,16 +454,21 @@ def run_test_remote(test, device, prefix
     elapsed = (datetime.now() - start).total_seconds()
 
     # We can't distinguish between stdout and stderr so we pass
     # the same buffer to both.
     return TestOutput(test, cmd, out, out, returncode, elapsed, False)
 
 
 def check_output(out, err, rc, timed_out, test, options):
+    # Allow skipping to compose with other expected results
+    if test.skip_if_cond:
+        if rc == test.SKIPPED_EXIT_STATUS:
+            return True
+
     if timed_out:
         if os.path.normpath(test.relpath_tests).replace(os.sep, '/') \
                 in options.ignore_timeouts:
             return True
 
         # The shell sometimes hangs on shutdown on Windows 7 and Windows
         # Server 2008. See bug 970063 comment 7 for a description of the
         # problem. Until bug 956899 is fixed, ignore timeouts on these