mirror of
https://github.com/servo/servo.git
synced 2025-10-14 15:30:27 +01:00
Update web-platform-tests to revision b'544363de4568baf9ae90d71e4822661edc546650'
This commit is contained in:
parent
4d5a804d03
commit
32cc2e03c4
197 changed files with 3539 additions and 2824 deletions
|
@ -28,10 +28,13 @@
|
|||
#
|
||||
# * Test the tests, add new ones to Git, remove deleted ones from Git, etc.
|
||||
|
||||
from typing import List
|
||||
from typing import List, Mapping
|
||||
|
||||
import re
|
||||
import codecs
|
||||
import collections
|
||||
import dataclasses
|
||||
import enum
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
|
@ -56,74 +59,291 @@ class InvalidTestDefinitionError(Error):
|
|||
"""Raised on invalid test definition."""
|
||||
|
||||
|
||||
def _simpleEscapeJS(string: str) -> str:
|
||||
return string.replace('\\', '\\\\').replace('"', '\\"')
|
||||
|
||||
|
||||
def _escapeJS(string: str) -> str:
|
||||
string = _simpleEscapeJS(string)
|
||||
# Kind of an ugly hack, for nicer failure-message output.
|
||||
string = re.sub(r'\[(\w+)\]', r'[\\""+(\1)+"\\"]', string)
|
||||
return string
|
||||
|
||||
|
||||
def _expand_nonfinite(method: str, argstr: str, tail: str) -> str:
|
||||
"""
|
||||
>>> print _expand_nonfinite('f', '<0 a>, <0 b>', ';')
|
||||
f(a, 0);
|
||||
f(0, b);
|
||||
f(a, b);
|
||||
>>> print _expand_nonfinite('f', '<0 a>, <0 b c>, <0 d>', ';')
|
||||
f(a, 0, 0);
|
||||
f(0, b, 0);
|
||||
f(0, c, 0);
|
||||
f(0, 0, d);
|
||||
f(a, b, 0);
|
||||
f(a, b, d);
|
||||
f(a, 0, d);
|
||||
f(0, b, d);
|
||||
"""
|
||||
# argstr is "<valid-1 invalid1-1 invalid2-1 ...>, ..." (where usually
|
||||
# 'invalid' is Infinity/-Infinity/NaN).
|
||||
args = []
|
||||
for arg in argstr.split(', '):
|
||||
match = re.match('<(.*)>', arg)
|
||||
if match is None:
|
||||
raise InvalidTestDefinitionError(
|
||||
f"Expected arg to match format '<(.*)>', but was: {arg}")
|
||||
a = match.group(1)
|
||||
args.append(a.split(' '))
|
||||
calls = []
|
||||
# Start with the valid argument list.
|
||||
call = [args[j][0] for j in range(len(args))]
|
||||
# For each argument alone, try setting it to all its invalid values:
|
||||
for i in range(len(args)):
|
||||
for a in args[i][1:]:
|
||||
c2 = call[:]
|
||||
c2[i] = a
|
||||
calls.append(c2)
|
||||
# For all combinations of >= 2 arguments, try setting them to their
|
||||
# first invalid values. (Don't do all invalid values, because the
|
||||
# number of combinations explodes.)
|
||||
def f(c: List[str], start: int, depth: int) -> None:
|
||||
for i in range(start, len(args)):
|
||||
if len(args[i]) > 1:
|
||||
a = args[i][1]
|
||||
c2 = c[:]
|
||||
c2[i] = a
|
||||
if depth > 0:
|
||||
calls.append(c2)
|
||||
f(c2, i + 1, depth + 1)
|
||||
|
||||
f(call, 0, 0)
|
||||
|
||||
return '\n'.join('%s(%s)%s' % (method, ', '.join(c), tail) for c in calls)
|
||||
|
||||
|
||||
def _get_test_sub_dir(name: str, name_to_sub_dir: Mapping[str, str]) -> str:
|
||||
for prefix in sorted(name_to_sub_dir.keys(), key=len, reverse=True):
|
||||
if name.startswith(prefix):
|
||||
return name_to_sub_dir[prefix]
|
||||
raise InvalidTestDefinitionError(
|
||||
'Test "%s" has no defined target directory mapping' % name)
|
||||
|
||||
|
||||
def _expand_test_code(code: str) -> str:
|
||||
code = re.sub(r'@nonfinite ([^(]+)\(([^)]+)\)(.*)', lambda m:
|
||||
_expand_nonfinite(m.group(1), m.group(2), m.group(3)),
|
||||
code) # Must come before '@assert throws'.
|
||||
|
||||
code = re.sub(r'@assert pixel (\d+,\d+) == (\d+,\d+,\d+,\d+);',
|
||||
r'_assertPixel(canvas, \1, \2);', code)
|
||||
|
||||
code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+);',
|
||||
r'_assertPixelApprox(canvas, \1, \2, 2);', code)
|
||||
|
||||
code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+) \+/- (\d+);',
|
||||
r'_assertPixelApprox(canvas, \1, \2, \3);', code)
|
||||
|
||||
code = re.sub(r'@assert throws (\S+_ERR) (.*);',
|
||||
r'assert_throws_dom("\1", function() { \2; });', code)
|
||||
|
||||
code = re.sub(r'@assert throws (\S+Error) (.*);',
|
||||
r'assert_throws_js(\1, function() { \2; });', code)
|
||||
|
||||
code = re.sub(
|
||||
r'@assert (.*) === (.*);', lambda m: '_assertSame(%s, %s, "%s", "%s");'
|
||||
% (m.group(1), m.group(2), _escapeJS(m.group(1)), _escapeJS(m.group(2))
|
||||
), code)
|
||||
|
||||
code = re.sub(
|
||||
r'@assert (.*) !== (.*);', lambda m:
|
||||
'_assertDifferent(%s, %s, "%s", "%s");' % (m.group(1), m.group(
|
||||
2), _escapeJS(m.group(1)), _escapeJS(m.group(2))), code)
|
||||
|
||||
code = re.sub(
|
||||
r'@assert (.*) =~ (.*);', lambda m: 'assert_regexp_match(%s, %s);' % (
|
||||
m.group(1), m.group(2)), code)
|
||||
|
||||
code = re.sub(
|
||||
r'@assert (.*);', lambda m: '_assert(%s, "%s");' % (m.group(
|
||||
1), _escapeJS(m.group(1))), code)
|
||||
|
||||
code = re.sub(r' @moz-todo', '', code)
|
||||
|
||||
code = re.sub(r'@moz-UniversalBrowserRead;', '', code)
|
||||
|
||||
assert ('@' not in code)
|
||||
|
||||
return code
|
||||
|
||||
|
||||
class CanvasType(str, enum.Enum):
|
||||
HTML_CANVAS = 'htmlcanvas'
|
||||
OFFSCREEN_CANVAS = 'offscreencanvas'
|
||||
|
||||
|
||||
def _get_enabled_canvas_types(test: Mapping[str, str]) -> List[CanvasType]:
|
||||
return [CanvasType(t.lower()) for t in test.get('canvasType', CanvasType)]
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class TestConfig:
|
||||
out_dir: str
|
||||
image_out_dir: str
|
||||
enabled: bool
|
||||
|
||||
|
||||
def _generate_test(test: Mapping[str, str], templates: Mapping[str, str],
|
||||
sub_dir: str, html_canvas_cfg: TestConfig,
|
||||
offscreen_canvas_cfg: TestConfig) -> None:
|
||||
name = test['name']
|
||||
|
||||
if test.get('expected', '') == 'green' and re.search(
|
||||
r'@assert pixel .* 0,0,0,0;', test['code']):
|
||||
print('Probable incorrect pixel test in %s' % name)
|
||||
|
||||
code_canvas = _expand_test_code(test['code']).strip()
|
||||
|
||||
expectation_html = ''
|
||||
if 'expected' in test and test['expected'] is not None:
|
||||
expected = test['expected']
|
||||
expected_img = None
|
||||
if expected == 'green':
|
||||
expected_img = '/images/green-100x50.png'
|
||||
elif expected == 'clear':
|
||||
expected_img = '/images/clear-100x50.png'
|
||||
else:
|
||||
if ';' in expected:
|
||||
print('Found semicolon in %s' % name)
|
||||
expected = re.sub(
|
||||
r'^size (\d+) (\d+)',
|
||||
r'surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \1, \2)'
|
||||
r'\ncr = cairo.Context(surface)', expected)
|
||||
|
||||
expected_canvas = (
|
||||
expected + "\nsurface.write_to_png('%s.png')\n" %
|
||||
os.path.join(html_canvas_cfg.image_out_dir, sub_dir, name))
|
||||
eval(compile(expected_canvas, '<test %s>' % name, 'exec'), {},
|
||||
{'cairo': cairo})
|
||||
|
||||
expected_offscreencanvas = (
|
||||
expected + "\nsurface.write_to_png('%s.png')\n" % os.path.join(
|
||||
offscreen_canvas_cfg.image_out_dir, sub_dir, name))
|
||||
eval(compile(expected_offscreencanvas, '<test %s>' % name, 'exec'),
|
||||
{}, {'cairo': cairo})
|
||||
|
||||
expected_img = '%s.png' % name
|
||||
|
||||
if expected_img:
|
||||
expectation_html = (
|
||||
'<p class="output expectedtext">Expected output:<p>'
|
||||
'<img src="%s" class="output expected" id="expected" '
|
||||
'alt="">' % expected_img)
|
||||
|
||||
canvas = test.get('canvas', 'width="100" height="50"')
|
||||
|
||||
notes = '<p class="notes">%s' % test['notes'] if 'notes' in test else ''
|
||||
|
||||
timeout = ('\n<meta name="timeout" content="%s">' %
|
||||
test['timeout'] if 'timeout' in test else '')
|
||||
|
||||
scripts = ''
|
||||
for s in test.get('scripts', []):
|
||||
scripts += '<script src="%s"></script>\n' % (s)
|
||||
|
||||
images = ''
|
||||
for src in test.get('images', []):
|
||||
img_id = src.split('/')[-1]
|
||||
if '/' not in src:
|
||||
src = '../images/%s' % src
|
||||
images += '<img src="%s" id="%s" class="resource">\n' % (src, img_id)
|
||||
for src in test.get('svgimages', []):
|
||||
img_id = src.split('/')[-1]
|
||||
if '/' not in src:
|
||||
src = '../images/%s' % src
|
||||
images += ('<svg><image xlink:href="%s" id="%s" class="resource">'
|
||||
'</svg>\n' % (src, img_id))
|
||||
images = images.replace('../images/', '/images/')
|
||||
|
||||
fonts = ''
|
||||
fonthack = ''
|
||||
for font in test.get('fonts', []):
|
||||
fonts += ('@font-face {\n font-family: %s;\n'
|
||||
' src: url("/fonts/%s.ttf");\n}\n' % (font, font))
|
||||
# Browsers require the font to actually be used in the page.
|
||||
if test.get('fonthack', 1):
|
||||
fonthack += ('<span style="font-family: %s; position: '
|
||||
'absolute; visibility: hidden">A</span>\n' % font)
|
||||
if fonts:
|
||||
fonts = '<style>\n%s</style>\n' % fonts
|
||||
|
||||
fallback = test.get('fallback',
|
||||
'<p class="fallback">FAIL (fallback content)</p>')
|
||||
|
||||
desc = test.get('desc', '')
|
||||
escaped_desc = _simpleEscapeJS(desc)
|
||||
|
||||
attributes = test.get('attributes', '')
|
||||
if attributes:
|
||||
context_args = "'2d', %s" % attributes.strip()
|
||||
attributes = ', ' + attributes.strip()
|
||||
else:
|
||||
context_args = "'2d'"
|
||||
|
||||
template_params = {
|
||||
'name': name,
|
||||
'desc': desc,
|
||||
'escaped_desc': escaped_desc,
|
||||
'notes': notes,
|
||||
'images': images,
|
||||
'fonts': fonts,
|
||||
'fonthack': fonthack,
|
||||
'timeout': timeout,
|
||||
'canvas': canvas,
|
||||
'expected': expectation_html,
|
||||
'code': code_canvas,
|
||||
'scripts': scripts,
|
||||
'fallback': fallback,
|
||||
'attributes': attributes,
|
||||
'context_args': context_args
|
||||
}
|
||||
|
||||
canvas_path = os.path.join(html_canvas_cfg.out_dir, sub_dir, name)
|
||||
offscreen_path = os.path.join(offscreen_canvas_cfg.out_dir, sub_dir, name)
|
||||
if 'manual' in test:
|
||||
canvas_path += '-manual'
|
||||
offscreen_path += '-manual'
|
||||
|
||||
# Create test cases for canvas and offscreencanvas.
|
||||
if html_canvas_cfg.enabled:
|
||||
f = codecs.open(f'{canvas_path}.html', 'w', 'utf-8')
|
||||
f.write(templates['w3ccanvas'] % template_params)
|
||||
if offscreen_canvas_cfg.enabled:
|
||||
f_html = codecs.open(f'{offscreen_path}.html', 'w', 'utf-8')
|
||||
f_worker = codecs.open(f'{offscreen_path}.worker.js', 'w', 'utf-8')
|
||||
if ('then(t_pass, t_fail);' in code_canvas):
|
||||
temp_offscreen = templates['w3coffscreencanvas'].replace(
|
||||
't.done();\n', '')
|
||||
temp_worker = templates['w3cworker'].replace('t.done();\n', '')
|
||||
f_html.write(temp_offscreen % template_params)
|
||||
timeout = ('// META: timeout=%s\n' %
|
||||
test['timeout'] if 'timeout' in test else '')
|
||||
template_params['timeout'] = timeout
|
||||
f_worker.write(temp_worker % template_params)
|
||||
else:
|
||||
f_html.write(templates['w3coffscreencanvas'] % template_params)
|
||||
timeout = ('// META: timeout=%s\n' %
|
||||
test['timeout'] if 'timeout' in test else '')
|
||||
template_params['timeout'] = timeout
|
||||
f_worker.write(templates['w3cworker'] % template_params)
|
||||
|
||||
|
||||
def genTestUtils_union(TEMPLATEFILE: str, NAME2DIRFILE: str) -> None:
|
||||
CANVASOUTPUTDIR = '../element'
|
||||
CANVASIMAGEOUTPUTDIR = '../element'
|
||||
OFFSCREENCANVASOUTPUTDIR = '../offscreen'
|
||||
OFFSCREENCANVASIMAGEOUTPUTDIR = '../offscreen'
|
||||
MISCOUTPUTDIR = './output'
|
||||
|
||||
def simpleEscapeJS(string: str) -> str:
|
||||
return string.replace('\\', '\\\\').replace('"', '\\"')
|
||||
|
||||
def escapeJS(string: str) -> str:
|
||||
string = simpleEscapeJS(string)
|
||||
# Kind of an ugly hack, for nicer failure-message output.
|
||||
string = re.sub(r'\[(\w+)\]', r'[\\""+(\1)+"\\"]', string)
|
||||
return string
|
||||
|
||||
def expand_nonfinite(method: str, argstr: str, tail: str) -> str:
|
||||
"""
|
||||
>>> print expand_nonfinite('f', '<0 a>, <0 b>', ';')
|
||||
f(a, 0);
|
||||
f(0, b);
|
||||
f(a, b);
|
||||
>>> print expand_nonfinite('f', '<0 a>, <0 b c>, <0 d>', ';')
|
||||
f(a, 0, 0);
|
||||
f(0, b, 0);
|
||||
f(0, c, 0);
|
||||
f(0, 0, d);
|
||||
f(a, b, 0);
|
||||
f(a, b, d);
|
||||
f(a, 0, d);
|
||||
f(0, b, d);
|
||||
"""
|
||||
# argstr is "<valid-1 invalid1-1 invalid2-1 ...>, ..." (where usually
|
||||
# 'invalid' is Infinity/-Infinity/NaN).
|
||||
args = []
|
||||
for arg in argstr.split(', '):
|
||||
match = re.match('<(.*)>', arg)
|
||||
if match is None:
|
||||
raise InvalidTestDefinitionError(
|
||||
f"Expected arg to match format '<(.*)>', but was: {arg}")
|
||||
a = match.group(1)
|
||||
args.append(a.split(' '))
|
||||
calls = []
|
||||
# Start with the valid argument list.
|
||||
call = [args[j][0] for j in range(len(args))]
|
||||
# For each argument alone, try setting it to all its invalid values:
|
||||
for i in range(len(args)):
|
||||
for a in args[i][1:]:
|
||||
c2 = call[:]
|
||||
c2[i] = a
|
||||
calls.append(c2)
|
||||
# For all combinations of >= 2 arguments, try setting them to their
|
||||
# first invalid values. (Don't do all invalid values, because the
|
||||
# number of combinations explodes.)
|
||||
def f(c: List[str], start: int, depth: int) -> None:
|
||||
for i in range(start, len(args)):
|
||||
if len(args[i]) > 1:
|
||||
a = args[i][1]
|
||||
c2 = c[:]
|
||||
c2[i] = a
|
||||
if depth > 0:
|
||||
calls.append(c2)
|
||||
f(c2, i + 1, depth + 1)
|
||||
|
||||
f(call, 0, 0)
|
||||
|
||||
return '\n'.join('%s(%s)%s' % (method, ', '.join(c), tail)
|
||||
for c in calls)
|
||||
|
||||
# Run with --test argument to run unit tests.
|
||||
if len(sys.argv) > 1 and sys.argv[1] == '--test':
|
||||
|
@ -132,7 +352,7 @@ def genTestUtils_union(TEMPLATEFILE: str, NAME2DIRFILE: str) -> None:
|
|||
sys.exit()
|
||||
|
||||
templates = yaml.safe_load(open(TEMPLATEFILE, 'r').read())
|
||||
name_mapping = yaml.safe_load(open(NAME2DIRFILE, 'r').read())
|
||||
name_to_sub_dir = yaml.safe_load(open(NAME2DIRFILE, 'r').read())
|
||||
|
||||
tests = []
|
||||
test_yaml_directory = 'yaml-new'
|
||||
|
@ -150,296 +370,45 @@ def genTestUtils_union(TEMPLATEFILE: str, NAME2DIRFILE: str) -> None:
|
|||
else:
|
||||
tests.append(t)
|
||||
|
||||
category_names = []
|
||||
category_contents_direct = {}
|
||||
category_contents_all = {}
|
||||
|
||||
def backref_html(name: str) -> str:
|
||||
backrefs = []
|
||||
c = ''
|
||||
for p in name.split('.')[:-1]:
|
||||
c += '.' + p
|
||||
backrefs.append('<a href="index%s.html">%s</a>.' % (c, p))
|
||||
backrefs.append(name.split('.')[-1])
|
||||
return ''.join(backrefs)
|
||||
|
||||
# Ensure the test output directories exist.
|
||||
testdirs = [
|
||||
CANVASOUTPUTDIR, OFFSCREENCANVASOUTPUTDIR, CANVASIMAGEOUTPUTDIR,
|
||||
OFFSCREENCANVASIMAGEOUTPUTDIR, MISCOUTPUTDIR
|
||||
OFFSCREENCANVASIMAGEOUTPUTDIR
|
||||
]
|
||||
for map_dir in set(name_mapping.values()):
|
||||
testdirs.append('%s/%s' % (CANVASOUTPUTDIR, map_dir))
|
||||
testdirs.append('%s/%s' % (OFFSCREENCANVASOUTPUTDIR, map_dir))
|
||||
for sub_dir in set(name_to_sub_dir.values()):
|
||||
testdirs.append('%s/%s' % (CANVASOUTPUTDIR, sub_dir))
|
||||
testdirs.append('%s/%s' % (OFFSCREENCANVASOUTPUTDIR, sub_dir))
|
||||
for d in testdirs:
|
||||
try:
|
||||
os.mkdir(d)
|
||||
except FileExistsError:
|
||||
pass # Ignore if it already exists,
|
||||
|
||||
used_images = {}
|
||||
|
||||
def map_name(name: str) -> str:
|
||||
mapped_name = None
|
||||
for mn in sorted(name_mapping.keys(), key=len, reverse=True):
|
||||
if name.startswith(mn):
|
||||
mapped_name = '%s/%s' % (name_mapping[mn], name)
|
||||
break
|
||||
if not mapped_name:
|
||||
print('LIKELY ERROR: %s has no defined target directory mapping' %
|
||||
name)
|
||||
return name
|
||||
if 'manual' in test:
|
||||
mapped_name += '-manual'
|
||||
return mapped_name
|
||||
|
||||
def expand_test_code(code: str) -> str:
|
||||
code = re.sub(r'@nonfinite ([^(]+)\(([^)]+)\)(.*)', lambda m:
|
||||
expand_nonfinite(m.group(1), m.group(2), m.group(3)),
|
||||
code) # Must come before '@assert throws'.
|
||||
|
||||
code = re.sub(r'@assert pixel (\d+,\d+) == (\d+,\d+,\d+,\d+);',
|
||||
r'_assertPixel(canvas, \1, \2);', code)
|
||||
|
||||
code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+);',
|
||||
r'_assertPixelApprox(canvas, \1, \2, 2);', code)
|
||||
|
||||
code = re.sub(
|
||||
r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+) \+/- (\d+);',
|
||||
r'_assertPixelApprox(canvas, \1, \2, \3);', code)
|
||||
|
||||
code = re.sub(r'@assert throws (\S+_ERR) (.*);',
|
||||
r'assert_throws_dom("\1", function() { \2; });', code)
|
||||
|
||||
code = re.sub(r'@assert throws (\S+Error) (.*);',
|
||||
r'assert_throws_js(\1, function() { \2; });', code)
|
||||
|
||||
code = re.sub(
|
||||
r'@assert (.*) === (.*);', lambda m:
|
||||
'_assertSame(%s, %s, "%s", "%s");' % (m.group(1), m.group(
|
||||
2), escapeJS(m.group(1)), escapeJS(m.group(2))), code)
|
||||
|
||||
code = re.sub(
|
||||
r'@assert (.*) !== (.*);', lambda m:
|
||||
'_assertDifferent(%s, %s, "%s", "%s");' % (m.group(1), m.group(
|
||||
2), escapeJS(m.group(1)), escapeJS(m.group(2))), code)
|
||||
|
||||
code = re.sub(
|
||||
r'@assert (.*) =~ (.*);', lambda m: 'assert_regexp_match(%s, %s);'
|
||||
% (m.group(1), m.group(2)), code)
|
||||
|
||||
code = re.sub(
|
||||
r'@assert (.*);', lambda m: '_assert(%s, "%s");' % (m.group(
|
||||
1), escapeJS(m.group(1))), code)
|
||||
|
||||
code = re.sub(r' @moz-todo', '', code)
|
||||
|
||||
code = re.sub(r'@moz-UniversalBrowserRead;', '', code)
|
||||
|
||||
assert ('@' not in code)
|
||||
|
||||
return code
|
||||
|
||||
used_tests = {}
|
||||
for i in range(len(tests)):
|
||||
test = tests[i]
|
||||
HTMLCanvas_test = True
|
||||
OffscreenCanvas_test = True
|
||||
if test.get('canvasType', []):
|
||||
HTMLCanvas_test = False
|
||||
OffscreenCanvas_test = False
|
||||
for canvas_type in test.get('canvasType'):
|
||||
if canvas_type.lower() == 'htmlcanvas':
|
||||
HTMLCanvas_test = True
|
||||
elif canvas_type.lower() == 'offscreencanvas':
|
||||
OffscreenCanvas_test = True
|
||||
|
||||
used_tests = collections.defaultdict(set)
|
||||
for test in tests:
|
||||
name = test['name']
|
||||
print('\r(%s)' % name, ' ' * 32, '\t')
|
||||
|
||||
if name in used_tests:
|
||||
print('Test %s is defined twice' % name)
|
||||
used_tests[name] = 1
|
||||
enabled_canvas_types = _get_enabled_canvas_types(test)
|
||||
|
||||
mapped_name = map_name(name)
|
||||
already_tested = used_tests[name].intersection(enabled_canvas_types)
|
||||
if already_tested:
|
||||
raise InvalidTestDefinitionError(
|
||||
f'Test {name} is defined twice for types {already_tested}')
|
||||
used_tests[name].update(enabled_canvas_types)
|
||||
|
||||
cat_total = ''
|
||||
for cat_part in [''] + name.split('.')[:-1]:
|
||||
cat_total += cat_part + '.'
|
||||
if not cat_total in category_names:
|
||||
category_names.append(cat_total)
|
||||
category_contents_all.setdefault(cat_total, []).append(name)
|
||||
category_contents_direct.setdefault(cat_total, []).append(name)
|
||||
sub_dir = _get_test_sub_dir(name, name_to_sub_dir)
|
||||
_generate_test(
|
||||
test,
|
||||
templates,
|
||||
sub_dir,
|
||||
html_canvas_cfg=TestConfig(
|
||||
out_dir=CANVASOUTPUTDIR,
|
||||
image_out_dir=CANVASIMAGEOUTPUTDIR,
|
||||
enabled=CanvasType.HTML_CANVAS in enabled_canvas_types),
|
||||
offscreen_canvas_cfg=TestConfig(
|
||||
out_dir=OFFSCREENCANVASOUTPUTDIR,
|
||||
image_out_dir=OFFSCREENCANVASIMAGEOUTPUTDIR,
|
||||
enabled=CanvasType.OFFSCREEN_CANVAS in enabled_canvas_types))
|
||||
|
||||
if test.get('expected', '') == 'green' and re.search(
|
||||
r'@assert pixel .* 0,0,0,0;', test['code']):
|
||||
print('Probable incorrect pixel test in %s' % name)
|
||||
|
||||
code_canvas = expand_test_code(test['code']).strip()
|
||||
|
||||
expectation_html = ''
|
||||
if 'expected' in test and test['expected'] is not None:
|
||||
expected = test['expected']
|
||||
expected_img = None
|
||||
if expected == 'green':
|
||||
expected_img = '/images/green-100x50.png'
|
||||
elif expected == 'clear':
|
||||
expected_img = '/images/clear-100x50.png'
|
||||
else:
|
||||
if ';' in expected:
|
||||
print('Found semicolon in %s' % name)
|
||||
expected = re.sub(
|
||||
r'^size (\d+) (\d+)',
|
||||
r'surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \1, \2)'
|
||||
r'\ncr = cairo.Context(surface)', expected)
|
||||
|
||||
if mapped_name.endswith('-manual'):
|
||||
png_name = mapped_name[:-len('-manual')]
|
||||
else:
|
||||
png_name = mapped_name
|
||||
expected_canvas = (expected +
|
||||
"\nsurface.write_to_png('%s/%s.png')\n" %
|
||||
(CANVASIMAGEOUTPUTDIR, png_name))
|
||||
eval(
|
||||
compile(expected_canvas, '<test %s>' % test['name'],
|
||||
'exec'), {}, {'cairo': cairo})
|
||||
|
||||
expected_offscreencanvas = (
|
||||
expected + "\nsurface.write_to_png('%s/%s.png')\n" %
|
||||
(OFFSCREENCANVASIMAGEOUTPUTDIR, png_name))
|
||||
eval(
|
||||
compile(expected_offscreencanvas,
|
||||
'<test %s>' % test['name'], 'exec'), {},
|
||||
{'cairo': cairo})
|
||||
|
||||
expected_img = '%s.png' % name
|
||||
|
||||
if expected_img:
|
||||
expectation_html = (
|
||||
'<p class="output expectedtext">Expected output:<p>'
|
||||
'<img src="%s" class="output expected" id="expected" '
|
||||
'alt="">' % expected_img)
|
||||
|
||||
canvas = test.get('canvas', 'width="100" height="50"')
|
||||
|
||||
prev_test = tests[i - 1]['name'] if i != 0 else 'index'
|
||||
next_test = tests[i + 1]['name'] if i != len(tests) - 1 else 'index'
|
||||
|
||||
name_wrapped = name.replace('.', '.​')
|
||||
|
||||
notes = '<p class="notes">%s' % test['notes'] if 'notes' in test else ''
|
||||
|
||||
timeout = ('\n<meta name="timeout" content="%s">' %
|
||||
test['timeout'] if 'timeout' in test else '')
|
||||
|
||||
scripts = ''
|
||||
for s in test.get('scripts', []):
|
||||
scripts += '<script src="%s"></script>\n' % (s)
|
||||
|
||||
variants = test.get('script-variants', {})
|
||||
script_variants = [(v, '<script src="%s"></script>\n' % (s))
|
||||
for (v, s) in variants.items()]
|
||||
if not script_variants:
|
||||
script_variants = [('', '')]
|
||||
|
||||
images = ''
|
||||
for src in test.get('images', []):
|
||||
img_id = src.split('/')[-1]
|
||||
if '/' not in src:
|
||||
used_images[src] = 1
|
||||
src = '../images/%s' % src
|
||||
images += '<img src="%s" id="%s" class="resource">\n' % (src,
|
||||
img_id)
|
||||
for src in test.get('svgimages', []):
|
||||
img_id = src.split('/')[-1]
|
||||
if '/' not in src:
|
||||
used_images[src] = 1
|
||||
src = '../images/%s' % src
|
||||
images += ('<svg><image xlink:href="%s" id="%s" class="resource">'
|
||||
'</svg>\n' % (src, img_id))
|
||||
images = images.replace('../images/', '/images/')
|
||||
|
||||
fonts = ''
|
||||
fonthack = ''
|
||||
for font in test.get('fonts', []):
|
||||
fonts += ('@font-face {\n font-family: %s;\n'
|
||||
' src: url("/fonts/%s.ttf");\n}\n' % (font, font))
|
||||
# Browsers require the font to actually be used in the page.
|
||||
if test.get('fonthack', 1):
|
||||
fonthack += ('<span style="font-family: %s; position: '
|
||||
'absolute; visibility: hidden">A</span>\n' % font)
|
||||
if fonts:
|
||||
fonts = '<style>\n%s</style>\n' % fonts
|
||||
|
||||
fallback = test.get('fallback',
|
||||
'<p class="fallback">FAIL (fallback content)</p>')
|
||||
|
||||
desc = test.get('desc', '')
|
||||
escaped_desc = simpleEscapeJS(desc)
|
||||
|
||||
attributes = test.get('attributes', '')
|
||||
if attributes:
|
||||
context_args = "'2d', %s" % attributes.strip()
|
||||
attributes = ', ' + attributes.strip()
|
||||
else:
|
||||
context_args = "'2d'"
|
||||
|
||||
for (variant, extra_script) in script_variants:
|
||||
name_variant = '' if not variant else '.' + variant
|
||||
|
||||
template_params = {
|
||||
'name': name + name_variant,
|
||||
'name_wrapped': name_wrapped,
|
||||
'backrefs': backref_html(name),
|
||||
'mapped_name': mapped_name,
|
||||
'desc': desc,
|
||||
'escaped_desc': escaped_desc,
|
||||
'prev': prev_test,
|
||||
'next': next_test,
|
||||
'notes': notes,
|
||||
'images': images,
|
||||
'fonts': fonts,
|
||||
'fonthack': fonthack,
|
||||
'timeout': timeout,
|
||||
'canvas': canvas,
|
||||
'expected': expectation_html,
|
||||
'code': code_canvas,
|
||||
'scripts': scripts + extra_script,
|
||||
'fallback': fallback,
|
||||
'attributes': attributes,
|
||||
'context_args': context_args
|
||||
}
|
||||
|
||||
# Create test cases for canvas and offscreencanvas.
|
||||
if HTMLCanvas_test:
|
||||
f = codecs.open(
|
||||
'%s/%s%s.html' %
|
||||
(CANVASOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8')
|
||||
f.write(templates['w3ccanvas'] % template_params)
|
||||
if OffscreenCanvas_test:
|
||||
f_html = codecs.open(
|
||||
'%s/%s%s.html' %
|
||||
(OFFSCREENCANVASOUTPUTDIR, mapped_name, name_variant), 'w',
|
||||
'utf-8')
|
||||
f_worker = codecs.open(
|
||||
'%s/%s%s.worker.js' %
|
||||
(OFFSCREENCANVASOUTPUTDIR, mapped_name, name_variant), 'w',
|
||||
'utf-8')
|
||||
if ('then(t_pass, t_fail);' in code_canvas):
|
||||
temp_offscreen = templates['w3coffscreencanvas'].replace(
|
||||
't.done();\n', '')
|
||||
temp_worker = templates['w3cworker'].replace(
|
||||
't.done();\n', '')
|
||||
f_html.write(temp_offscreen % template_params)
|
||||
timeout = ('// META: timeout=%s\n' %
|
||||
test['timeout'] if 'timeout' in test else '')
|
||||
template_params['timeout'] = timeout
|
||||
f_worker.write(temp_worker % template_params)
|
||||
else:
|
||||
f_html.write(templates['w3coffscreencanvas'] %
|
||||
template_params)
|
||||
timeout = ('// META: timeout=%s\n' %
|
||||
test['timeout'] if 'timeout' in test else '')
|
||||
template_params['timeout'] = timeout
|
||||
f_worker.write(templates['w3cworker'] % template_params)
|
||||
print()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue