Bug 1489280 [wpt PR 12881] - Improve test coverage of registered properties in paint worklets., a=testonly
authorAnders Hartvoll Ruud <andruud@chromium.org>
Mon, 10 Sep 2018 18:14:47 +0000
changeset 435987 406d478bdc5f5fdb3896c1e77deac1e8d57c014a
parent 435986 33923f08e61b1836a62ee69b8df09c9b131b4df7
child 435988 d12098f3d90c245e219e5b66dc5c0502fd48d766
push id34625
push userdvarga@mozilla.com
push dateThu, 13 Sep 2018 02:31:40 +0000
treeherdermozilla-central@51e9e9660b3e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1489280, 12881, 641877, 1209711, 589461
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1489280 [wpt PR 12881] - Improve test coverage of registered properties in paint worklets., a=testonly Automatic update from web-platform-testsImprove test coverage of registered properties in paint worklets. The most important use case for css-properties-values-api is having typed (and possibly interpolated) custom properties in paint worklets. So naturally, this is the *least* well tested use case in WPT. This CL improves that by adding tests for most of the syntax types. The test works as a kind of "ref" test, which compares the output of CSSStyleValue.parse /parseAll with the value observed inside the worklet. <transform-function> and <transform-list> are not supported yet, so they will come later. Interpolations should also be tested, but that belongs in a separate test. Bug: 641877 Change-Id: I4bd310ecd61a2a8989df9c4a5c818cdc7c179b3a Reviewed-on: https://chromium-review.googlesource.com/1209711 Commit-Queue: Anders Ruud <andruud@chromium.org> Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org> Cr-Commit-Position: refs/heads/master@{#589461} -- wpt-commits: e5f7af549a9fe9c35191ad3f1ffaa3b02ed47795 wpt-pr: 12881
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/css/css-paint-api/registered-properties-in-custom-paint.https.html
testing/web-platform/tests/css/css-paint-api/registered-property-type.https.html
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -128386,19 +128386,19 @@
       [
        "/css/css-paint-api/parse-input-arguments-ref.html",
        "=="
       ]
      ],
      {}
     ]
    ],
-   "css/css-paint-api/registered-properties-in-custom-paint.https.html": [
-    [
-     "/css/css-paint-api/registered-properties-in-custom-paint.https.html",
+   "css/css-paint-api/registered-property-type.https.html": [
+    [
+     "/css/css-paint-api/registered-property-type.https.html",
      [
       [
        "/css/css-paint-api/parse-input-arguments-ref.html",
        "=="
       ]
      ],
      {}
     ]
@@ -547692,18 +547692,18 @@
   "css/css-paint-api/parse-input-arguments-022.https.html": [
    "50aaa6b3c9420f1220d38c407aec84be46afaafe",
    "reftest"
   ],
   "css/css-paint-api/parse-input-arguments-ref.html": [
    "086bc7b27ee79caab2c2e433da4ff00ba1bace9b",
    "support"
   ],
-  "css/css-paint-api/registered-properties-in-custom-paint.https.html": [
-   "d9a63da144d9c08b3912064b78b86a16d44f6918",
+  "css/css-paint-api/registered-property-type.https.html": [
+   "6ff7ce4e0af6b290ea269573c596caa364a5c1c8",
    "reftest"
   ],
   "css/css-paint-api/resources/html5.png": [
    "e34419263f954e010b3eeb419820d40bdf7b71c5",
    "support"
   ],
   "css/css-paint-api/style-background-image-ref.html": [
    "2fe4d0c9c024c22002f77e9e320624483f0086b7",
deleted file mode 100644
--- a/testing/web-platform/tests/css/css-paint-api/registered-properties-in-custom-paint.https.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<link rel="match" href="parse-input-arguments-ref.html">
-<style>
-.container {
-  width: 100px;
-  height: 100px;
-  --length: 10px;
-  --number: 10;
-}
-
-#canvas-geometry {
-  background-image: paint(geometry);
-}
-</style>
-<script src="/common/reftest-wait.js"></script>
-<script src="/common/worklet-reftest.js"></script>
-<body>
-<div id="canvas-geometry" class="container"></div>
-
-<script id="code" type="text/worklet">
-registerPaint('geometry', class {
-    static get inputProperties() {
-        return [
-            '--length',
-            '--length-initial',
-            '--number',
-        ];
-    }
-    paint(ctx, geom, styleMap) {
-        const properties = [...styleMap.keys()].sort();
-        var serializedStrings = [];
-        for (let i = 0; i < properties.length; i++) {
-            const value = styleMap.get(properties[i]);
-            let serialized;
-            if (value)
-                serialized = properties[i].toString() + ': [' + value.constructor.name + '=' + value.toString() + ']';
-            else
-                serialized = properties[i].toString() + ': [null]';
-            serializedStrings.push(serialized);
-        }
-        ctx.strokeStyle = 'green';
-        if (serializedStrings[0] != "--length: [CSSUnitValue=10px]")
-            ctx.strokeStyle = 'red';
-        if (serializedStrings[1] != "--length-initial: [CSSUnitValue=20px]")
-            ctx.strokeStyle = 'blue';
-        if (serializedStrings[2] != "--number: [CSSUnitValue=10]")
-            ctx.strokeStyle = 'yellow';
-        ctx.lineWidth = 4;
-        ctx.strokeRect(0, 0, geom.width, geom.height);
-    }
-});
-</script>
-
-<script>
-    try {
-      CSS.registerProperty({name: '--length', syntax: '<length>', initialValue: '0px', inherits: false});
-      CSS.registerProperty({name: '--length-initial', syntax: '<length>', initialValue: '20px', inherits: false});
-      CSS.registerProperty({name: '--number', syntax: '<number>', initialValue: '0', inherits: false});
-      importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
-    } catch(e) {
-      document.body.textContent = e;
-      takeScreenshot();
-    }
-</script>
-</body>
-</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/registered-property-type.https.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://www.w3.org/TR/css-paint-api-1/#examples">
+<link rel="match" href="parse-input-arguments-ref.html">
+<style>
+.container {
+  width: 100px;
+  height: 100px;
+}
+
+#canvas-geometry {
+  background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+<script id="code" type="text/worklet">
+  // Globals that must be prepended to this script:
+  // - debugLog: A function that logs errors.
+  // - props: Test data.
+
+  registerPaint('geometry', class {
+    static get inputProperties() { return props.map(p => p.name); }
+
+    paint(ctx, geom, styleMap) {
+      ctx.strokeStyle = 'green';
+      for (let prop of props) {
+        let first = styleMap.get(prop.name);
+        let all = styleMap.getAll(prop.name);
+        let serialize = v => v.constructor.name + '=' + v.toString()
+        let actual = all.map(serialize).join(',');
+        let expected = prop.expected.join(',');
+        let pass = actual === expected
+            && serialize(first) === prop.expected[0];
+        if (!pass)
+          ctx.strokeStyle = 'red';
+        debugLog(pass ? 'PASS' : 'FAIL', prop.syntax, actual, expected);
+      }
+      ctx.lineWidth = 4;
+      ctx.strokeRect(0, 0, geom.width, geom.height);
+    }
+  });
+</script>
+<script>
+    // A copy of this array (automatically enriched with 'name' and 'expected')
+    // is also available in the worklet.
+    let props = [
+      // Initial values.
+      { syntax: '*', initialValue: 'if(){}' },
+      { syntax: '<angle>', initialValue: '42deg' },
+      { syntax: '<color>', initialValue: '#fefefe' },
+      { syntax: '<custom-ident>', initialValue: 'none' },
+      { syntax: '<image>', initialValue: 'linear-gradient(red, red)' },
+      { syntax: '<image>', initialValue: 'url(http://a.com/a)' },
+      { syntax: '<integer>', initialValue: '42' },
+      { syntax: '<length-percentage>', initialValue: '10%' },
+      { syntax: '<length-percentage>', initialValue: '10px' },
+      { syntax: '<length-percentage>', initialValue: 'calc(10px + 10%)' },
+      { syntax: '<length>', initialValue: '1337px' },
+      { syntax: '<number>', initialValue: '42.5' },
+      { syntax: '<percentage>', initialValue: '42%' },
+      { syntax: '<resolution>', initialValue: '300dpi' },
+      { syntax: '<time>', initialValue: '3600s' },
+      { syntax: '<url>', initialValue: 'url(http://a.com/a)' },
+      { syntax: 'thing', initialValue: 'thing' },
+      { syntax: '<length> | <angle>', initialValue: '1337px' },
+      { syntax: '<angle> | <image>', initialValue: '1turn' },
+      { syntax: '<length>+', initialValue: '1337px' },
+      { syntax: '<length>+', initialValue: '1337px 1338px', count: 2 },
+      { syntax: '<length>#', initialValue: '1337px' },
+      { syntax: '<length>#', initialValue: '1337px, 1338px', count: 2 },
+
+      // Non-initial values:
+      { syntax: '*', initialValue: 'fail', value: 'if(){}' },
+      { syntax: '<angle> | fail', initialValue: 'fail', value: '42deg' },
+      { syntax: '<color> | fail', initialValue: 'fail', value: '#fefefe' },
+      { syntax: '<custom-ident> | fail', initialValue: 'fail', value: 'none' },
+      { syntax: '<image> | fail', initialValue: 'fail', value: 'linear-gradient(red, red)' },
+      { syntax: '<image> | fail', initialValue: 'fail', value: 'url(http://a.com/a)' },
+      { syntax: '<integer> | fail', initialValue: 'fail', value: '42' },
+      { syntax: '<length-percentage> | fail', initialValue: 'fail', value: '10%' },
+      { syntax: '<length-percentage> | fail', initialValue: 'fail', value: '10px' },
+      { syntax: '<length-percentage> | fail', initialValue: 'fail', value: 'calc(10px + 10%)' },
+      { syntax: '<length> | fail', initialValue: 'fail', value: '1337px' },
+      { syntax: '<number> | fail', initialValue: 'fail', value: '42.5' },
+      { syntax: '<percentage> | fail', initialValue: 'fail', value: '42%' },
+      { syntax: '<resolution> | fail', initialValue: 'fail', value: '300dpi' },
+      { syntax: '<time> | fail', initialValue: 'fail', value: '3600s' },
+      { syntax: '<url> | fail', initialValue: 'fail', value: 'url(http://a.com/a)' },
+      { syntax: 'thing | fail', initialValue: 'fail', value: 'thing' },
+      { syntax: '<length>+ | fail', initialValue: 'fail', value: '1337px' },
+      { syntax: '<length>+ | fail', initialValue: 'fail', value: '1337px 1338px', count: 2 },
+      { syntax: '<length># | fail', initialValue: 'fail', value: '1337px' },
+      { syntax: '<length># | fail', initialValue: 'fail', value: '1337px, 1338px', count: 2 },
+    ];
+
+    try {
+      let target = document.getElementById('canvas-geometry');
+      let pid = 1;
+
+      for (let p of props) {
+        p.name = `--prop-${++pid}`;
+
+        CSS.registerProperty({
+          name: p.name,
+          syntax: p.syntax,
+          initialValue: p.initialValue,
+          inherits: (typeof p.inherits !== 'undefined') ? p.inherits : false
+        });
+
+        if (typeof p.value !== 'undefined')
+          target.style.setProperty(p.name, p.value);
+        if (typeof p.count === 'undefined')
+          p.count = 1;
+
+        let getValue = p => (typeof p.value !== 'undefined') ? p.value : p.initialValue;
+        let serialize = v => v.constructor.name + '=' + v.toString();
+
+        let parse = function (p) {
+          if (p.count == 1)
+            return [CSSStyleValue.parse(p.name, getValue(p))];
+          return CSSStyleValue.parseAll(p.name, getValue(p));
+        };
+
+        // Generate expected value. We assume that CSSStyleValue.parse/All
+        // returns the correct CSSStyleValue subclass and value.
+        p.expected = parse(p).map(serialize);
+      }
+
+      // Adding '?debug' to the URL will cause this test to emit
+      // test results to console.log.
+      let debugMode = document.location.href.endsWith('?debug');
+      let code = [
+        `const props = ${JSON.stringify(props)};`,
+        `const debugLog = ${debugMode ? 'console.log' : 'function(){}'};`,
+        document.getElementById('code').textContent
+      ].join('\n');
+
+      importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, code);
+    } catch(e) {
+      document.body.textContent = e;
+      takeScreenshot();
+    }
+</script>
+</body>
+</html>