Skip to content

Instantly share code, notes, and snippets.

@gsnedders
Created March 9, 2020 02:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gsnedders/38df4e1b40011c9a910d7aa1a8230f4f to your computer and use it in GitHub Desktop.
Save gsnedders/38df4e1b40011c9a910d7aa1a8230f4f to your computer and use it in GitHub Desktop.
# 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/.
from __future__ import unicode_literals
import os
import re
import sys
from collections import defaultdict
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(type, file, annotations, referenced_test=None, trailer=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))
self.files.add(test)
self.dirs.add(os.path.dirname(test))
test_dict = {
'type': type,
'path': test,
'here': os.path.dirname(test),
'manifest': normalized_path,
'name': os.path.basename(test),
'head': '',
'support-files': '',
'subsuite': '',
'trailer': trailer
}
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 open(path, 'r') as fh:
lines = fh.read().splitlines()
urlprefix = ''
for line in lines:
line = line.decode('utf-8')
# Entire line is a comment.
if line.startswith('#'):
continue
# Comments can begin mid line. Strip them.
m = RE_COMMENT.search(line)
trailer = None
if m:
trailer = line[m.end():].strip()
line = line[:m.start()]
line = line.strip()
if not line:
continue
items = line.split()
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 item == 'url-prefix':
urlprefix = items[i+1]
break
if item == 'default-preferences':
break
if item == 'include':
self.load(os.path.join(mdir, items[i+1]))
break
if item == 'load' or item == 'script':
add_test(item, items[i+1], annotations, trailer=trailer)
break
if item == '==' or item == '!=' or item == 'print':
add_test(item, items[i+1], annotations, items[i+2], trailer=trailer)
break
class LostException(Exception):
pass
def rewrite_s(s, tests):
"""rewrite a string s to be a WPT reftest"""
s = s.replace("MozReftestInvalidate", "TestRendered")
search = s.find("<title")
if search == -1:
try:
search = s.index("<head")
search = s.index("<", search+1)
while s[search+1] == "!":
search = s.index("<", search+1)
except ValueError:
raise LostException
nl = s.rfind("\n", 0, search) + 1
ws = s[nl:search]
new_links = []
for comparison, ref in tests:
wpt_cmp = "match" if comparison == "==" else "mismatch"
new_links.append('<link rel="%s" href="%s">\n' % (wpt_cmp, ref))
s = s[:nl] + "".join(new_links) + s[nl:]
return s
def main(path):
wpt_tests = os.path.normpath(os.path.abspath("testing/web-platform/tests/"))
m = ReftestManifest()
m.load(path)
tests_by_path = defaultdict(list)
for test in m.tests:
if test['type'] not in ("==", "!="):
continue
tests_by_path[test['path']].append(test)
for path, tests in tests_by_path.items():
if any("fails" in test for test in tests) and path.startswith(wpt_tests):
wpt_path = os.path.relpath(path, wpt_tests)
test_meta = "testing/web-platform/meta/" + wpt_path + ".ini"
test_meta_dir = os.path.dirname(test_meta)
if not os.path.exists(test_meta_dir):
os.makedirs(test_meta_dir, 0755)
trailers = {test["trailer"] for test in tests}
trailers.discard(None)
trailers.discard("")
with open(test_meta, "wb") as f:
f.write("[" + os.path.basename(path) + "]\n")
f.write(" expected: FAIL")
if trailers:
f.write(" # ")
f.write(", ".join(trailers))
f.write("\n")
with open(path, "rb") as f:
s = f.read()
try:
new_s = rewrite_s(s, [(test['type'], test['referenced-test']) for test in tests])
except LostException:
print test['path']
continue
with open(path, "wb") as f:
f.write(new_s)
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment