Bug 1354232 - Allow wpt manifest files to specify LSAN errors to ignore, r=maja_zf draft
authorJames Graham <james@hoppipolla.co.uk>
Mon, 21 May 2018 13:49:21 +0100
changeset 805836 ed0c132aae56b98cae6965a2acc2adff0954665e
parent 805835 392fa83fce2af5237f98b8d4231596d0ced311b8
child 805837 aa11253963ca407aec3c1de18d28f05be2bba017
push id112776
push userbmo:james@hoppipolla.co.uk
push dateFri, 08 Jun 2018 15:53:57 +0000
reviewersmaja_zf
bugs1354232
milestone62.0a1
Bug 1354232 - Allow wpt manifest files to specify LSAN errors to ignore, r=maja_zf This adds a property lsan-allowed to the expectation manifest files that takes a list of strings. Any entry in the list that matches a frame in an LSAN stack will cause that stack to be regarded as an expected failure. MozReview-Commit-ID: 2oUw0joThha
testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py
testing/web-platform/tests/tools/wptrunner/wptrunner/manifestexpected.py
testing/web-platform/tests/tools/wptrunner/wptrunner/wpttest.py
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py
@@ -182,16 +182,18 @@ class FirefoxBrowser(Browser):
         self.leak_report_file = None
         self.lsan_handler = None
         if self.asan:
             self.lsan_handler = mozleak.LSANLeaks(logger)
         self.stylo_threads = stylo_threads
         self.chaos_mode_flags = chaos_mode_flags
 
     def settings(self, test):
+        if self.asan:
+            self.lsan_handler.set_allowed(test.lsan_allowed)
         return {"check_leaks": self.leak_check and not test.leaks}
 
     def start(self, **kwargs):
         if self.marionette_port is None:
             self.marionette_port = get_free_port(2828, exclude=self.used_ports)
             self.used_ports.add(self.marionette_port)
 
         env = test_environment(xrePath=os.path.dirname(self.binary),
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestexpected.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestexpected.py
@@ -56,22 +56,37 @@ def prefs(node):
     def value(ini_value):
         if isinstance(ini_value, (str, unicode)):
             return tuple(ini_value.split(":", 1))
         else:
             return (ini_value, None)
 
     try:
         node_prefs = node.get("prefs")
-        rv = dict(value(item) for item in node_prefs)
+        if type(node_prefs) in (str, unicode):
+            rv = dict(value(node_prefs))
+        else:
+            rv = dict(value(item) for item in node_prefs)
     except KeyError:
         rv = {}
     return rv
 
 
+def lsan_allowed(node):
+    try:
+        node_items = node.get("lsan-allowed")
+        if isinstance(node_items, (str, unicode)):
+            rv = {node_items}
+        else:
+            rv = set(node_items)
+    except KeyError:
+        rv = set()
+    return rv
+
+
 class ExpectedManifest(ManifestItem):
     def __init__(self, name, test_path, url_base):
         """Object representing all the tests in a particular manifest
 
         :param name: Name of the AST Node associated with this object.
                      Should always be None since this should always be associated with
                      the root node of the AST.
         :param test_path: Path of the test file associated with this manifest.
@@ -132,16 +147,20 @@ class ExpectedManifest(ManifestItem):
     @property
     def tags(self):
         return tags(self)
 
     @property
     def prefs(self):
         return prefs(self)
 
+    @property
+    def lsan_allowed(self):
+        return lsan_allowed(self)
+
 
 class DirectoryManifest(ManifestItem):
     @property
     def disabled(self):
         return bool_prop("disabled", self)
 
     @property
     def restart_after(self):
@@ -162,16 +181,20 @@ class DirectoryManifest(ManifestItem):
     @property
     def tags(self):
         return tags(self)
 
     @property
     def prefs(self):
         return prefs(self)
 
+    @property
+    def lsan_allowed(self):
+        return lsan_allowed(self)
+
 
 class TestNode(ManifestItem):
     def __init__(self, name):
         """Tree node associated with a particular test in a manifest
 
         :param name: name of the test"""
         assert name is not None
         ManifestItem.__init__(self, name)
@@ -219,16 +242,20 @@ class TestNode(ManifestItem):
     @property
     def tags(self):
         return tags(self)
 
     @property
     def prefs(self):
         return prefs(self)
 
+    @property
+    def lsan_allowed(self):
+        return lsan_allowed(self)
+
     def append(self, node):
         """Add a subtest to the current test
 
         :param node: AST Node associated with the subtest"""
         child = ManifestItem.append(self, node)
         self.subtests[child.name] = child
 
     def get_subtest(self, name):
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/wpttest.py
+++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wpttest.py
@@ -210,16 +210,26 @@ class Test(object):
     def max_assertion_count(self):
         for meta in self.itermeta(None):
             count = meta.max_assertion_count
             if count is not None:
                 return count
         return 0
 
     @property
+    def lsan_allowed(self):
+        lsan_allowed = set()
+        for meta in self.itermeta():
+            lsan_allowed |= meta.lsan_allowed
+            if atom_reset in lsan_allowed:
+                lsan_allowed.remove(atom_reset)
+                break
+        return lsan_allowed
+
+    @property
     def tags(self):
         tags = set()
         for meta in self.itermeta():
             meta_tags = meta.tags
             tags |= meta_tags
             if atom_reset in meta_tags:
                 tags.remove(atom_reset)
                 break