summaryrefslogtreecommitdiffstats
path: root/layout/tools/reftest/reftest/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'layout/tools/reftest/reftest/__init__.py')
-rw-r--r--layout/tools/reftest/reftest/__init__.py164
1 files changed, 164 insertions, 0 deletions
diff --git a/layout/tools/reftest/reftest/__init__.py b/layout/tools/reftest/reftest/__init__.py
new file mode 100644
index 0000000000..f82a07ec44
--- /dev/null
+++ b/layout/tools/reftest/reftest/__init__.py
@@ -0,0 +1,164 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import io
+import os
+import re
+
+import six
+
+RE_COMMENT = re.compile(r"\s+#")
+RE_HTTP = re.compile(r"HTTP\((\.\.(\/\.\.)*)\)")
+RE_PROTOCOL = re.compile(r"^\w+:")
+FAILURE_TYPES = (
+ "fails",
+ "fails-if",
+ "needs-focus",
+ "random",
+ "random-if",
+ "silentfail",
+ "silentfail-if",
+ "skip",
+ "skip-if",
+ "slow",
+ "slow-if",
+ "fuzzy",
+ "fuzzy-if",
+ "require-or",
+ "asserts",
+ "asserts-if",
+)
+PREF_ITEMS = (
+ "pref",
+ "test-pref",
+ "ref-pref",
+)
+RE_ANNOTATION = re.compile(r"(.*)\((.*)\)")
+
+
+class ReftestManifest(object):
+ """Represents a parsed reftest manifest."""
+
+ def __init__(self, finder=None):
+ self.path = None
+ self.dirs = set()
+ self.files = set()
+ self.manifests = set()
+ self.tests = []
+ self.finder = finder
+
+ def load(self, path):
+ """Parse a reftest manifest file."""
+
+ def add_test(file, annotations, referenced_test=None):
+ # We can't package about:, data:, or chrome: URIs.
+ # Discarding data isn't correct for a parser. But retaining
+ # all data isn't currently a requirement.
+ if RE_PROTOCOL.match(file):
+ return
+ test = os.path.normpath(os.path.join(mdir, urlprefix + file))
+ if test in self.files:
+ # if test path has already been added, make no changes, to
+ # avoid duplicate paths in self.tests
+ return
+ self.files.add(test)
+ self.dirs.add(os.path.dirname(test))
+ test_dict = {
+ "path": test,
+ "here": os.path.dirname(test),
+ "manifest": normalized_path,
+ "name": os.path.basename(test),
+ "head": "",
+ "support-files": "",
+ "subsuite": "",
+ }
+ if referenced_test:
+ test_dict["referenced-test"] = referenced_test
+ for annotation in annotations:
+ m = RE_ANNOTATION.match(annotation)
+ if m:
+ if m.group(1) not in test_dict:
+ test_dict[m.group(1)] = m.group(2)
+ else:
+ test_dict[m.group(1)] += ";" + m.group(2)
+ else:
+ test_dict[annotation] = None
+ self.tests.append(test_dict)
+
+ normalized_path = os.path.normpath(os.path.abspath(path))
+ self.manifests.add(normalized_path)
+ if not self.path:
+ self.path = normalized_path
+
+ mdir = os.path.dirname(normalized_path)
+ self.dirs.add(mdir)
+
+ if self.finder:
+ lines = self.finder.get(path).read().splitlines()
+ else:
+ with io.open(path, "r", encoding="utf-8") as fh:
+ lines = fh.read().splitlines()
+
+ urlprefix = ""
+ defaults = []
+ for i, line in enumerate(lines):
+ lineno = i + 1
+ line = six.ensure_text(line)
+
+ # Entire line is a comment.
+ if line.startswith("#"):
+ continue
+
+ # Comments can begin mid line. Strip them.
+ m = RE_COMMENT.search(line)
+ if m:
+ line = line[: m.start()]
+ line = line.strip()
+ if not line:
+ continue
+
+ items = line.split()
+ if items[0] == "defaults":
+ defaults = items[1:]
+ continue
+
+ items = defaults + items
+ annotations = []
+ for i in range(len(items)):
+ item = items[i]
+
+ if item.startswith(FAILURE_TYPES) or item.startswith(PREF_ITEMS):
+ annotations += [item]
+ continue
+ if item == "HTTP":
+ continue
+
+ m = RE_HTTP.match(item)
+ if m:
+ # Need to package the referenced directory.
+ self.dirs.add(os.path.normpath(os.path.join(mdir, m.group(1))))
+ continue
+
+ if i < len(defaults):
+ raise ValueError(
+ "Error parsing manifest {}, line {}: "
+ "Invalid defaults token '{}'".format(path, lineno, item)
+ )
+
+ if item == "url-prefix":
+ urlprefix = items[i + 1]
+ break
+
+ if item == "include":
+ self.load(os.path.join(mdir, items[i + 1]))
+ break
+
+ if item == "load" or item == "script":
+ add_test(items[i + 1], annotations)
+ break
+
+ if item == "==" or item == "!=" or item == "print":
+ add_test(items[i + 1], annotations)
+ add_test(items[i + 2], annotations, items[i + 1])
+ break