diff options
Diffstat (limited to 'layout/tools/reftest/reftest/__init__.py')
-rw-r--r-- | layout/tools/reftest/reftest/__init__.py | 164 |
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 |