Bug 1354232 - Add group_metadata to test group metadata and pass it through to the browser, r=ato draft
authorJames Graham <james@hoppipolla.co.uk>
Tue, 29 May 2018 18:17:40 +0100
changeset 805839 9a8af95f81a63e6252b6fc7c8fb78faf8c565dab
parent 805838 9895cd155aa15b8fcbd3083fb6d477471fcfd565
child 805840 00d0e8fa3213351c509e56c23e4fb182e5864ddf
push id112776
push userbmo:james@hoppipolla.co.uk
push dateFri, 08 Jun 2018 15:53:57 +0000
reviewersato
bugs1354232
milestone62.0a1
Bug 1354232 - Add group_metadata to test group metadata and pass it through to the browser, r=ato This initially contains a scope entry which is set to the base directory of the tests being run. Typically this is /, but with run_by_dir, it's the path to the current run_by_dir group e.g. /html/semantics/form_elements/ MozReview-Commit-ID: JEFJByKTUsH
testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/base.py
testing/web-platform/tests/tools/wptrunner/wptrunner/testloader.py
testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/base.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/base.py
@@ -82,17 +82,17 @@ class Browser(object):
     def setup(self):
         """Used for browser-specific setup that happens at the start of a test run"""
         pass
 
     def settings(self, test):
         return {}
 
     @abstractmethod
-    def start(self, **kwargs):
+    def start(self, group_metadata, **kwargs):
         """Launch the browser object and get it into a state where is is ready to run tests"""
         pass
 
     @abstractmethod
     def stop(self, force=False):
         """Stop the running browser process."""
         pass
 
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/testloader.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/testloader.py
@@ -590,16 +590,20 @@ class TestSource(object):
         self.current_metadata = None
 
     @abstractmethod
     # noqa: N805
     #@classmethod (doesn't compose with @abstractmethod)
     def make_queue(cls, tests, **kwargs):
         pass
 
+    @classmethod
+    def group_metadata(self, state):
+        return {"scope": "/"}
+
     def group(self):
         if not self.current_group or len(self.current_group) == 0:
             try:
                 self.current_group, self.current_metadata = self.test_queue.get(block=False)
             except Empty:
                 return None, None
         return self.current_group, self.current_metadata
 
@@ -613,34 +617,35 @@ class GroupedSource(TestSource):
     def make_queue(cls, tests, **kwargs):
         test_queue = Queue()
         groups = []
 
         state = {}
 
         for test in tests:
             if cls.new_group(state, test, **kwargs):
-                groups.append((deque(), {}))
+                group_metadata = cls.group_metadata(state)
+                groups.append((deque(), group_metadata))
 
             group, metadata = groups[-1]
             group.append(test)
             test.update_metadata(metadata)
 
         for item in groups:
             test_queue.put(item)
         return test_queue
 
 
 class SingleTestSource(TestSource):
     @classmethod
     def make_queue(cls, tests, **kwargs):
         test_queue = Queue()
         processes = kwargs["processes"]
         queues = [deque([]) for _ in xrange(processes)]
-        metadatas = [{} for _ in xrange(processes)]
+        metadatas = [cls.group_metadata(None) for _ in xrange(processes)]
         for test in tests:
             idx = hash(test.id) % processes
             group = queues[idx]
             metadata = metadatas[idx]
             group.append(test)
             test.update_metadata(metadata)
 
         for item in zip(queues, metadatas):
@@ -654,8 +659,12 @@ class PathGroupedSource(GroupedSource):
     def new_group(cls, state, test, **kwargs):
         depth = kwargs.get("depth")
         if depth is True:
             depth = None
         path = urlparse.urlsplit(test.url).path.split("/")[1:-1][:depth]
         rv = path != state.get("prev_path")
         state["prev_path"] = path
         return rv
+
+    @classmethod
+    def group_metadata(cls, state):
+        return {"scope": "/%s" % "/".join(state["prev_path"])}
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py
@@ -170,17 +170,17 @@ class BrowserManager(object):
         browser_settings = self.browser.settings(test)
         restart_required = ((self.browser_settings is not None and
                              self.browser_settings != browser_settings) or
                             (self.last_test != test and test.expected() == "CRASH"))
         self.browser_settings = browser_settings
         self.last_test = test
         return restart_required
 
-    def init(self):
+    def init(self, group_metadata):
         """Launch the browser that is being tested,
         and the TestRunner process that will run the tests."""
         # It seems that this lock is helpful to prevent some race that otherwise
         # sometimes stops the spawned processes initialising correctly, and
         # leaves this thread hung
         if self.init_timer is not None:
             self.init_timer.cancel()
 
@@ -188,17 +188,17 @@ class BrowserManager(object):
 
         if not self.no_timeout:
             self.init_timer = threading.Timer(self.browser.init_timeout,
                                               self.init_timeout)
         try:
             if self.init_timer is not None:
                 self.init_timer.start()
             self.logger.debug("Starting browser with settings %r" % self.browser_settings)
-            self.browser.start(**self.browser_settings)
+            self.browser.start(group_metadata=group_metadata, **self.browser_settings)
             self.browser_pid = self.browser.pid()
         except Exception:
             self.logger.warning("Failure during init %s" % traceback.format_exc())
             if self.init_timer is not None:
                 self.init_timer.cancel()
             self.logger.error(traceback.format_exc())
             succeeded = False
         else:
@@ -447,17 +447,17 @@ class TestRunnerManager(threading.Thread
     def init(self):
         assert isinstance(self.state, RunnerManagerState.initializing)
         if self.state.failure_count > self.max_restarts:
             self.logger.error("Max restarts exceeded")
             return RunnerManagerState.error()
 
         self.browser.update_settings(self.state.test)
 
-        result = self.browser.init()
+        result = self.browser.init(self.state.group_metadata)
         if result is Stop:
             return RunnerManagerState.error()
         elif not result:
             return RunnerManagerState.initializing(self.state.test,
                                                    self.state.test_group,
                                                    self.state.group_metadata,
                                                    self.state.failure_count + 1)
         else: