From caac056b89fd0f91734aeb3506252a4ce2404e12 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 22 Oct 2024 21:57:39 +0000 Subject: [PATCH] Bug 1921829 [wpt PR 48382] - Add a new canvas WPT template using pycairo-generated reference images, a=testonly Automatic update from web-platform-tests Add a new canvas WPT template using pycairo-generated reference images Using the "cairo_reference:" key in the YAML config, we can now express the expected result of a test using pycairo code. Contrary to the existing "expected:" key which produces an image that is only used for "informational" purpose, "cairo_reference:" produces a reference test, meaning that the test runner automatically compares the test result with that generated image and fails the test if the result differs. Both single variant tests (non-variant or tests with a single variant per file) and variant grids are supported. For single variant, the generated reference file is an HMTL page with a single tag pointing to the PNG generated with pycairo. To cut down on the number of files generated for variant grids, all the reference images for all of the cells of the grid are packed into a single PNG file, 3d-model-texture-style. The reference HTML file is a grid of tags, each framing a different portion of the PNG image. Bug: 364549423 Change-Id: Icb3c246b22347054b7cc9b5e5cc40d21b30565bd Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5894774 Reviewed-by: Andres Ricardo Perez Commit-Queue: Jean-Philippe Gravel Cr-Commit-Position: refs/heads/main{#1369396} -- wpt-commits: 2af17a84e98cd28940d2882c68ff824d6e98f4b7 wpt-pr: 48382 UltraBlame original commit: c2e9874a21e2b6da498e387093096588f90d5a61 --- .../html/canvas/tools/gentestutilsunion.py | 863 +++++++++++++++--- .../canvas/tools/templates/reftest_img.html | 107 +++ .../tools/templates/reftest_img_grid.html | 327 +++++++ 3 files changed, 1193 insertions(+), 104 deletions(-) create mode 100644 testing/web-platform/tests/html/canvas/tools/templates/reftest_img.html create mode 100644 testing/web-platform/tests/html/canvas/tools/templates/reftest_img_grid.html diff --git a/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py b/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py index c48f5915512bf..b375ec0765bc7 100644 --- a/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py +++ b/testing/web-platform/tests/html/canvas/tools/gentestutilsunion.py @@ -345,6 +345,8 @@ import itertools import +math +import os import pathlib @@ -2510,6 +2512,12 @@ html_reference ' +CAIRO_REFERENCE += +' +cairo_reference +' + TESTHARNESS = ' @@ -4237,7 +4245,10 @@ _TemplateType : -if +reference_types += +( +( ' reference ' @@ -4245,7 +4256,10 @@ self . params -and +) ++ + +( ' html_reference ' @@ -4253,6 +4267,24 @@ self . params +) ++ + +( +' +cairo_reference +' +in +self +. +params +) +) + +if +reference_types +> +1 : raise @@ -4274,22 +4306,27 @@ } is invalid -" -reference -" -and +only +one +of ' ' " +reference +" +" html_reference " +or +" +cairo_reference +" can -\ -' -t -both be +' + +' specified at the @@ -4329,6 +4366,21 @@ . HTML_REFERENCE +if +' +cairo_reference +' +in +self +. +params +: + +return +_TemplateType +. +CAIRO_REFERENCE + return _TemplateType . @@ -4485,72 +4537,46 @@ ] ) -if -' -reference -' +for +ref_type in -self -. -_params -: - -self -. -_params -[ +{ ' reference ' -] -= -_preprocess_code -( - -jinja_env -self -. -_params -[ ' -reference +html_reference ' -] -self -. -_params -) - -if ' -html_reference +cairo_reference ' +} +: + +if +ref_type in self . _params : - + self . _params [ -' -html_reference -' +ref_type ] = _preprocess_code ( - + jinja_env self . _params [ -' -html_reference -' +ref_type ] self . @@ -4746,8 +4772,8 @@ " " Creates -a -reference +an +expected image using Cairo @@ -6156,6 +6182,10 @@ _TemplateType . HTML_REFERENCE + +_TemplateType +. +CAIRO_REFERENCE ) : @@ -6477,20 +6507,28 @@ = True -is_html_ref +templates = -self +{ + +_TemplateType . -template_type -= -= +REFERENCE +: +f +' +reftest_element +{ +grid +} +. +html +' + _TemplateType . HTML_REFERENCE - -ref_template_name -= -( +: f ' reftest @@ -6500,20 +6538,31 @@ . html ' - -if -is_html_ref -else + +_TemplateType +. +CAIRO_REFERENCE +: f ' -reftest_element +reftest_img { grid } . html ' -) + +} + +ref_template_name += +templates +[ +self +. +template_type +] if _CanvasType @@ -6823,9 +6872,10 @@ ) def -_generate_cairo_images +_generate_cairo_reference_grid ( self + output_dirs : _OutputPaths @@ -6838,22 +6888,77 @@ " " " -Generates +Generate +this +grid +' +s +expected +image +from +Cairo +code +if +needed +. + +In +order +to +cut +on the -pycairo -images -found +number +of +files +generated +the +expected +image + +of +all +the +variants in +this +grid +are +packed +into +a +single +PNG +. +The + +expected +HTML +then +contains +a +grid +of +< +img +> +tags +each +showing +a +portion + +of the -YAML -test -definition +PNG +file . " " " if +not any ( v @@ -6863,7 +6968,7 @@ get ( ' -expected +cairo_reference ' ) for @@ -6871,43 +6976,554 @@ in self . -_variants +variants ) : -if -len -( +return + +width +height += self . -variants -) -! -= -1 -: - -raise -InvalidTestDefinitionError +_unique_param ( - ' -Parameter -" -expected -" -is -not -supported -for -variant -grids -. +size ' ) - -if -self + +cairo_code += +' +' + +# +First +generate +a +function +producing +a +Cairo +surface +with +the +expected + +# +image +for +each +variant +in +the +grid +. +The +function +is +needed +to +provide + +# +a +scope +isolating +the +variant +code +from +each +other +. + +for +idx +variant +in +enumerate +( +self +. +_variants +) +: + +cairo_ref += +variant +. +params +. +get +( +' +cairo_reference +' +) + +if +not +cairo_ref +: + +raise +InvalidTestDefinitionError +( + +' +When +used +" +cairo_reference +" +must +be +specified +for +all +' + +' +test +variants +. +' +) + +cairo_code ++ += +textwrap +. +dedent +( +f +' +' +' +\ + +def +draw_ref +{ +idx +} +( +) +: + +surface += +cairo +. +ImageSurface +( + +cairo +. +FORMAT_ARGB32 +{ +width +} +{ +height +} +) + +cr += +cairo +. +Context +( +surface +) + +{ +{ +} +} + +return +surface + +' +' +' +) +. +format +( +textwrap +. +indent +( +cairo_ref +' +' +) +) + +# +Write +all +variant +images +into +the +final +surface +. + +surface_width += +width +* +self +. +_grid_width + +surface_height += +( +height +* + +math +. +ceil +( +len +( +self +. +_variants +) +/ +self +. +_grid_width +) +) + +cairo_code ++ += +textwrap +. +dedent +( +f +' +' +' +\ + +surface += +cairo +. +ImageSurface +( + +cairo +. +FORMAT_ARGB32 +{ +surface_width +} +{ +surface_height +} +) + +cr += +cairo +. +Context +( +surface +) + +' +' +' +) + +for +idx +variant +in +enumerate +( +self +. +_variants +) +: + +x_pos += +int +( +idx +% +self +. +_grid_width +) +* +width + +y_pos += +int +( +idx +/ +self +. +_grid_width +) +* +height + +cairo_code ++ += +textwrap +. +dedent +( +f +' +' +' +\ + +cr +. +set_source_surface +( +draw_ref +{ +idx +} +( +) +{ +x_pos +} +{ +y_pos +} +) + +cr +. +paint +( +) + +' +' +' +) + +img_filename += +f +' +{ +self +. +file_name +} +. +png +' + +_write_cairo_images +( +cairo_code +output_dirs +. +sub_path +( +img_filename +) + +self +. +canvas_types +) + +self +. +_params +[ +' +img_reference +' +] += +img_filename + +def +_generate_cairo_images +( +self +output_dirs +: +_OutputPaths +) +- +> +None +: + +" +" +" +Generates +the +pycairo +images +found +in +the +YAML +test +definition +. +" +" +" + +has_expected += +any +( +v +. +params +. +get +( +' +expected +' +) +for +v +in +self +. +_variants +) + +has_cairo_reference += +any +( + +v +. +params +. +get +( +' +cairo_reference +' +) +for +v +in +self +. +_variants +) + +if +has_expected +and +has_cairo_reference +: + +raise +InvalidTestDefinitionError +( + +' +Parameters +" +expected +" +and +" +cairo_reference +" +can +\ +' +t +be +both +' + +' +used +at +the +same +time +. +' +) + +if +has_expected +: + +if +len +( +self +. +variants +) +! += +1 +: + +raise +InvalidTestDefinitionError +( + +' +Parameter +" +expected +" +is +not +supported +for +variant +grids +. +' +) + +if +self . template_type ! @@ -6950,6 +7566,17 @@ ( output_dirs ) + +elif +has_cairo_reference +: + +self +. +_generate_cairo_reference_grid +( +output_dirs +) def generate_test @@ -7018,6 +7645,10 @@ _TemplateType . HTML_REFERENCE + +_TemplateType +. +CAIRO_REFERENCE ) : @@ -7383,6 +8014,30 @@ 1 ) +if +not +isinstance +( +grid_width +int +) +: + +raise +InvalidTestDefinitionError +( +' +" +grid_width +" +must +be +an +integer +. +' +) + grids = [ diff --git a/testing/web-platform/tests/html/canvas/tools/templates/reftest_img.html b/testing/web-platform/tests/html/canvas/tools/templates/reftest_img.html new file mode 100644 index 0000000000000..425f7f8a34170 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/tools/templates/reftest_img.html @@ -0,0 +1,107 @@ +< +! +DOCTYPE +html +> +< +! +- +- +DO +NOT +EDIT +! +This +test +has +been +generated +by +/ +html +/ +canvas +/ +tools +/ +gentest +. +py +. +- +- +> +< +title +> +Canvas +test +: +{ +{ +name +} +} +< +/ +title +> +< +h1 +> +{ +{ +name +} +} +< +/ +h1 +> +< +p +> +{ +{ +desc +} +} +< +/ +p +> +{ +% +if +notes +% +} +< +p +> +{ +{ +notes +} +} +< +/ +p +> +{ +% +endif +% +} +< +img +src += +" +{ +{ +img_reference +} +} +" +> diff --git a/testing/web-platform/tests/html/canvas/tools/templates/reftest_img_grid.html b/testing/web-platform/tests/html/canvas/tools/templates/reftest_img_grid.html new file mode 100644 index 0000000000000..117a21cba5934 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/tools/templates/reftest_img_grid.html @@ -0,0 +1,327 @@ +< +! +DOCTYPE +html +> +< +! +- +- +DO +NOT +EDIT +! +This +test +has +been +generated +by +/ +html +/ +canvas +/ +tools +/ +gentest +. +py +. +- +- +> +< +title +> +Canvas +test +: +{ +{ +name +} +} +< +/ +title +> +< +h1 +style += +" +font +- +size +: +20px +; +" +> +{ +{ +name +} +} +< +/ +h1 +> +< +p +> +{ +{ +desc +} +} +< +/ +p +> +{ +% +if +notes +% +} +< +p +> +{ +{ +notes +} +} +< +/ +p +> +{ +% +endif +% +} +< +div +style += +" +display +: +grid +; +grid +- +gap +: +4px +; +grid +- +template +- +columns +: +repeat +( +{ +{ +grid_width +} +} +max +- +content +) +; +font +- +size +: +13px +; +text +- +align +: +center +; +" +> +{ +% +for +variant +in +element_variants +% +} +< +span +> +{ +% +for +variant_name +in +variant +. +grid_variant_names +% +} +< +div +> +{ +{ +variant_name +} +} +< +/ +div +> +{ +% +endfor +% +} +{ +% +set +x_pos += +( +( +loop +. +index0 +% +grid_width +) +| +int +) +* +variant +. +size +[ +0 +] +% +} +{ +% +set +y_pos += +( +( +loop +. +index0 +/ +grid_width +) +| +int +) +* +variant +. +size +[ +1 +] +% +} +< +img +src += +" +{ +{ +img_reference +} +} +" +style += +" +outline +: +1px +solid +; +width +: +{ +{ +variant +. +size +[ +0 +] +} +} +px +; +height +: +{ +{ +variant +. +size +[ +1 +] +} +} +px +; +object +- +position +: +{ +{ +- +x_pos +} +} +px +{ +{ +- +y_pos +} +} +px +; +object +- +fit +: +none +; +" +> +< +/ +span +> +{ +% +endfor +% +} +< +/ +div +>