diff options
Diffstat (limited to 'testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py')
-rw-r--r-- | testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py | 213 |
1 files changed, 133 insertions, 80 deletions
diff --git a/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py b/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py index cf141f2f07..d7042810be 100644 --- a/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py +++ b/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py @@ -28,7 +28,7 @@ # # * Test the tests, add new ones to Git, remove deleted ones from Git, etc. -from typing import Any, List, Mapping, Optional, Set, Tuple +from typing import Any, DefaultDict, List, Mapping, Optional, Set, Tuple import re import collections @@ -184,6 +184,10 @@ def _remove_extra_newlines(text: str) -> str: return text def _expand_test_code(code: str) -> str: + code = re.sub(r' @moz-todo', '', code) + + code = re.sub(r'@moz-UniversalBrowserRead;', '', code) + code = _remove_extra_newlines(code) # Unroll expressions with a cross-product-style parameter expansion. @@ -202,11 +206,13 @@ def _expand_test_code(code: str) -> str: 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+_ERR) (.*?);$', + r'assert_throws_dom("\1", function() { \2; });', code, + flags=re.MULTILINE | re.DOTALL) - code = re.sub(r'@assert throws (\S+Error) (.*);', - r'assert_throws_js(\1, function() { \2; });', code) + code = re.sub(r'@assert throws (\S+Error) (.*?);$', + r'assert_throws_js(\1, function() { \2; });', code, + flags=re.MULTILINE | re.DOTALL) code = re.sub( r'@assert (.*) === (.*);', lambda m: '_assertSame(%s, %s, "%s", "%s");' @@ -226,10 +232,6 @@ def _expand_test_code(code: str) -> str: 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 @@ -376,45 +378,50 @@ def _write_testharness_test(jinja_env: jinja2.Environment, 'utf-8') +def _generate_expected_image(expected: str, name: str, sub_dir: str, + enabled_canvas_types: Set[CanvasType], + html_canvas_cfg: TestConfig, + offscreen_canvas_cfg: TestConfig) -> str: + """Creates a reference image using Cairo and returns the file location.""" + if expected == 'green': + return '/images/green-100x50.png' + if expected == 'clear': + return '/images/clear-100x50.png' + 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 CanvasType.HTML_CANVAS in enabled_canvas_types: + 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}) + + if {CanvasType.OFFSCREEN_CANVAS, CanvasType.WORKER} & enabled_canvas_types: + expected_offscreen = ( + expected + "\nsurface.write_to_png('%s.png')\n" % + os.path.join(offscreen_canvas_cfg.image_out_dir, sub_dir, name)) + eval(compile(expected_offscreen, '<test %s>' % name, 'exec'), {}, + {'cairo': cairo}) + + return '%s.png' % name + + def _generate_test(test: Mapping[str, Any], jinja_env: jinja2.Environment, - sub_dir: str, enabled_tests: Set[CanvasType], + name_to_sub_dir: Mapping[str, str], + used_tests: DefaultDict[str, Set[CanvasType]], html_canvas_cfg: TestConfig, offscreen_canvas_cfg: TestConfig) -> None: _validate_test(test) name = test['name'] - expected_img = None - if 'expected' in test and test['expected'] is not None: - expected = test['expected'] - 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 CanvasType.HTML_CANVAS in enabled_tests: - 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}) - - if {CanvasType.OFFSCREEN_CANVAS, CanvasType.WORKER} & enabled_tests: - expected_offscreen = ( - expected + - "\nsurface.write_to_png('%s.png')\n" % os.path.join( - offscreen_canvas_cfg.image_out_dir, sub_dir, name)) - eval(compile(expected_offscreen, '<test %s>' % name, 'exec'), - {}, {'cairo': cairo}) - - expected_img = '%s.png' % name + sub_dir = _get_test_sub_dir(name, name_to_sub_dir) + enabled_canvas_types = _get_enabled_canvas_types(test) # Defaults: params = { @@ -423,11 +430,29 @@ def _generate_test(test: Mapping[str, Any], jinja_env: jinja2.Environment, } params.update(test) + + # Render parameters used in the test name. + name = jinja_env.from_string(name).render(params) + print('\r(%s)' % name, ' ' * 32, '\t') + + expected_img = None + if 'expected' in test and test['expected'] is not None: + expected_img = _generate_expected_image(test['expected'], name, + sub_dir, enabled_canvas_types, + html_canvas_cfg, + offscreen_canvas_cfg) + params.update({ 'code': _expand_test_code(test['code']), 'expected_img': expected_img }) + 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) + 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: @@ -435,11 +460,55 @@ def _generate_test(test: Mapping[str, Any], jinja_env: jinja2.Environment, offscreen_path += '-manual' if 'reference' in test or 'html_reference' in test: - _write_reference_test(jinja_env, params, enabled_tests, + _write_reference_test(jinja_env, params, enabled_canvas_types, canvas_path, offscreen_path) else: - _write_testharness_test(jinja_env, params, enabled_tests, canvas_path, - offscreen_path) + _write_testharness_test(jinja_env, params, enabled_canvas_types, + canvas_path, offscreen_path) + + +def _recursive_expand_variant_matrix(test_list: List[Mapping[str, Any]], + variant_matrix: List[Mapping[str, Any]], + current_selection: List[Tuple[str, Any]], + original_test: Mapping[str, Any]): + if len(current_selection) == len(variant_matrix): + # Selection for each variant is done, so add a new test to test_list. + test = original_test.copy() + variant_name_list = [] + should_append_variant_names = original_test.get( + 'append_variants_to_name', True) + for variant_name, variant_params in current_selection: + variant_name_list.append(variant_name) + # Append variant name. Variant names starting with '_' are + # not appended, which is useful to create variants with the same + # name in different folders (element vs. offscreen). + if (should_append_variant_names + and not variant_name.startswith('_')): + test['name'] += '.' + variant_name + test.update(variant_params) + # Expose variant names as a list so they can be used from the yaml + # files, which helps with better naming of tests. + test.update({'variant_names': variant_name_list}) + test_list.append(test) + else: + # Continue the recursion with each possible selection for the current + # variant. + variant = variant_matrix[len(current_selection)] + for variant_options in variant.items(): + current_selection.append(variant_options) + _recursive_expand_variant_matrix(test_list, variant_matrix, + current_selection, original_test) + current_selection.pop() + + +def _expand_variant_matrix( + variant_matrix: List[Mapping[str, Any]], + original_test: Mapping[str, Any]) -> List[Mapping[str, Any]]: + current_selection = [] + matrix_tests = [] + _recursive_expand_variant_matrix(matrix_tests, variant_matrix, + current_selection, original_test) + return matrix_tests def genTestUtils_union(NAME2DIRFILE: str) -> None: @@ -495,41 +564,25 @@ def genTestUtils_union(NAME2DIRFILE: str) -> None: pass # Ignore if it already exists, used_tests = collections.defaultdict(set) - for original_test in tests: - variants = original_test.get('variants', {'': dict()}) - for variant_name, variant_params in variants.items(): - test = original_test.copy() - if variant_name or variant_params: - # Append variant name. Variant names starting with '_' are - # not appended, which is useful to create variants with the same - # name in different folders (element vs. offscreen). - if not variant_name.startswith('_'): - test['name'] += '.' + variant_name - test.update(variant_params) - - name = test['name'] - print('\r(%s)' % name, ' ' * 32, '\t') - - enabled_canvas_types = _get_enabled_canvas_types(test) - - 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) - - sub_dir = _get_test_sub_dir(name, name_to_sub_dir) - _generate_test( - test, - jinja_env, - sub_dir, - enabled_canvas_types, - html_canvas_cfg=TestConfig( - out_dir=CANVASOUTPUTDIR, - image_out_dir=CANVASIMAGEOUTPUTDIR), - offscreen_canvas_cfg=TestConfig( - out_dir=OFFSCREENCANVASOUTPUTDIR, - image_out_dir=OFFSCREENCANVASIMAGEOUTPUTDIR)) + for test in tests: + if 'variant_matrix' in test: + variants = _expand_variant_matrix(test['variant_matrix'], test) + elif 'variants' in test: + variant_matrix = [test['variants']] + variants = _expand_variant_matrix(variant_matrix, test) + else: + variants = [test] + + for variant in variants: + _generate_test(variant, + jinja_env, + name_to_sub_dir, + used_tests, + html_canvas_cfg=TestConfig( + out_dir=CANVASOUTPUTDIR, + image_out_dir=CANVASIMAGEOUTPUTDIR), + offscreen_canvas_cfg=TestConfig( + out_dir=OFFSCREENCANVASOUTPUTDIR, + image_out_dir=OFFSCREENCANVASIMAGEOUTPUTDIR)) print() |