diff --git a/tests/wpt/metadata/FileAPI/url/url-with-fetch.any.js.ini b/tests/wpt/metadata/FileAPI/url/url-with-fetch.any.js.ini index 3a3d15b8406..6a3af4e2ece 100644 --- a/tests/wpt/metadata/FileAPI/url/url-with-fetch.any.js.ini +++ b/tests/wpt/metadata/FileAPI/url/url-with-fetch.any.js.ini @@ -37,6 +37,3 @@ [Revoke blob URL after creating Request, will fetch] expected: FAIL - [Revoke blob URL after calling fetch, fetch should succeed] - expected: FAIL - diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index eb12c1e43c1..7fa0a220fe8 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -303979,26 +303979,6 @@ {} ] ], - "portals/resources/portal-forward-with-broadcast.sub.html": [ - [ - {} - ] - ], - "portals/resources/portal-host-cross-origin-navigate.sub.html": [ - [ - {} - ] - ], - "portals/resources/portal-host-cross-origin.sub.html": [ - [ - {} - ] - ], - "portals/resources/portal-host.html": [ - [ - {} - ] - ], "portals/resources/portals-rendering-portal.html": [ [ {} @@ -344697,6 +344677,12 @@ {} ] ], + "css/css-logical/logical-box-border-radius.html": [ + [ + "/css/css-logical/logical-box-border-radius.html", + {} + ] + ], "css/css-logical/logical-box-border-shorthands.html": [ [ "/css/css-logical/logical-box-border-shorthands.html", @@ -345957,6 +345943,12 @@ {} ] ], + "css/css-scroll-anchoring/heuristic-with-offset-update.html": [ + [ + "/css/css-scroll-anchoring/heuristic-with-offset-update.html", + {} + ] + ], "css/css-scroll-anchoring/inheritance.html": [ [ "/css/css-scroll-anchoring/inheritance.html", @@ -382811,12 +382803,36 @@ {} ] ], + "kv-storage/cause-errors-via-idb.https.html": [ + [ + "/kv-storage/cause-errors-via-idb.https.html", + {} + ] + ], + "kv-storage/entries.https.html": [ + [ + "/kv-storage/entries.https.html", + {} + ] + ], "kv-storage/key-types.https.html": [ [ "/kv-storage/key-types.https.html", {} ] ], + "kv-storage/keys-values-entries.https.html": [ + [ + "/kv-storage/keys-values-entries.https.html", + {} + ] + ], + "kv-storage/keys.https.html": [ + [ + "/kv-storage/keys.https.html", + {} + ] + ], "kv-storage/non-secure-context-dynamic-import.html": [ [ "/kv-storage/non-secure-context-dynamic-import.html", @@ -382847,6 +382863,12 @@ {} ] ], + "kv-storage/values.https.html": [ + [ + "/kv-storage/values.https.html", + {} + ] + ], "lifecycle/freeze.html": [ [ "/lifecycle/freeze.html", @@ -397669,12 +397691,6 @@ {} ] ], - "portals/portals-host-exposure.sub.html": [ - [ - "/portals/portals-host-exposure.sub.html", - {} - ] - ], "portals/portals-host-null.html": [ [ "/portals/portals-host-null.html", @@ -457209,7 +457225,7 @@ "manual" ], "clipboard-apis/async-write-image-read-image-manual.https.html": [ - "ac7fb0863e75a1a33451033db054d2bf812d8450", + "6117e469792ff61ff30015f2d94f1ceb2e3332ac", "manual" ], "clipboard-apis/async-write-text-read-dttext-manual.https.html": [ @@ -563332,6 +563348,10 @@ "b33528d9cd16b6de169cbd03e98b867403f090a6", "testharness" ], + "css/css-logical/logical-box-border-radius.html": [ + "81b8fa0fece70e6f20f3b51ff9011e4775305a33", + "testharness" + ], "css/css-logical/logical-box-border-shorthands.html": [ "d05d864f59261bd1dd0ff2cbd9278a8535a5910e", "testharness" @@ -563445,7 +563465,7 @@ "support" ], "css/css-logical/resources/test-box-properties.js": [ - "1f17ff296ff2c3dcf81db1a112bda24ef04eb126", + "ef1854f97de4c93c3156540ed81101fcc9993578", "support" ], "css/css-logical/resources/test-logical-values.js": [ @@ -570236,6 +570256,10 @@ "cea6b61dfe8b60754f656c860fe4d6f2dfff0c18", "testharness" ], + "css/css-scroll-anchoring/heuristic-with-offset-update.html": [ + "7fcbd983ed569025e5f46fe69002ca91e86fd21a", + "testharness" + ], "css/css-scroll-anchoring/inheritance.html": [ "035d4ffd2e2c8955d4e8f80af3aff5db9285c8ae", "testharness" @@ -615229,7 +615253,7 @@ "support" ], "feature-policy/resources/featurepolicy.js": [ - "a0756e385de6534821d3c15048e922384e4610ae", + "e2577f35c3fb53abda3934274c3e6a281ba617d9", "support" ], "feature-policy/resources/picture-in-picture.js": [ @@ -638269,25 +638293,41 @@ "support" ], "kv-storage/api-surface.https.html": [ - "65452f55be044aa5ec722da26717f527ee81a4e3", + "90e705862d599f2920ebdf5fa07cc3e4ba1f6d46", + "testharness" + ], + "kv-storage/cause-errors-via-idb.https.html": [ + "21fe36b36cb1dbedca5383abb526b9b4f6c8ce3e", + "testharness" + ], + "kv-storage/entries.https.html": [ + "0d1ab849a709bc8361bca88de34aa91c1ee3e23b", "testharness" ], "kv-storage/helpers/class-assert.js": [ - "31b25cab9f2d88d8df59a0b4ecb35eef3765e380", + "89f0889c56d3a990a812be9208377090607335a2", "support" ], "kv-storage/helpers/equality-asserters.js": [ - "ad4623c179d75c8d4ce8b1fa8503f943bf6a7c77", + "448ab31348cee50be8820185d8bdfb8f626eb9dc", "support" ], "kv-storage/helpers/kvs-tests.js": [ - "0ffe71fad780f599a11d915d3b3512c95844f7bd", + "a6c4d58dfa5e928768d483df11c7d06180bac9fb", "support" ], "kv-storage/key-types.https.html": [ "0dc930258f8b554c6cae4398df3dba930dcdf03c", "testharness" ], + "kv-storage/keys-values-entries.https.html": [ + "b26323809bb3d33551ee9630bcf841fa0246262b", + "testharness" + ], + "kv-storage/keys.https.html": [ + "a6be29725bf3274f6b5bb92b370962507a29b692", + "testharness" + ], "kv-storage/non-secure-context-dynamic-import.html": [ "6ccbf84ba1dc6acd4931da279c887635b7f8a771", "testharness" @@ -638305,7 +638345,11 @@ "testharness" ], "kv-storage/undefined-value.https.html": [ - "89da5d5c44f353bc1f5f93eaeaf3acd89eee386c", + "4cb483a3d982ab150fb28c6aee3a1398c273e82c", + "testharness" + ], + "kv-storage/values.https.html": [ + "64756bf195fc3319d9dd21abad4c5d86fa266cfe", "testharness" ], "lifecycle/META.yml": [ @@ -639809,7 +639853,7 @@ "testharness" ], "mediacapture-streams/MediaStream-default-feature-policy.https.html": [ - "21e3f5b9af8567cb015604bbcb021cc04216e4c2", + "2e38b9e6864d4525d8a649a7093b9f82a30a10cd", "testharness" ], "mediacapture-streams/MediaStream-finished-add.https.html": [ @@ -640429,7 +640473,7 @@ "support" ], "mixed-content/generic/tools/generate.py": [ - "e7a315d59ceab0d56d19d409c6f82ba84592bc37", + "1e0a404a709add4a31404f874ca4fc035c9c5702", "support" ], "mixed-content/generic/tools/regenerate": [ @@ -640437,7 +640481,7 @@ "support" ], "mixed-content/generic/tools/spec_validator.py": [ - "0ae2990f4e1b3c89fbc142d0428272bbd7d462d1", + "686579ece5797abfdb5441e080db85758fe1b220", "support" ], "mixed-content/generic/worker.js": [ @@ -650876,10 +650920,6 @@ "ac1505d2a5b2fe1df083eae75893483e025a2ad7", "testharness" ], - "portals/portals-host-exposure.sub.html": [ - "83e31bd4735131d35b2a03ae82d07be364497689", - "testharness" - ], "portals/portals-host-null.html": [ "e0f1d63743c54c687d62f86abe278873fa823430", "testharness" @@ -650904,22 +650944,6 @@ "cf09caebc0ff9ac38facde84075a7af5be19fd48", "support" ], - "portals/resources/portal-forward-with-broadcast.sub.html": [ - "39bda69b0eef9b0062809507bfb91d9fc3401d95", - "support" - ], - "portals/resources/portal-host-cross-origin-navigate.sub.html": [ - "44c6c16c5771f1027c3cc82e966342bbaa80ad8d", - "support" - ], - "portals/resources/portal-host-cross-origin.sub.html": [ - "aa369d39f0bd674a5cb1a9ad8954e3106a807687", - "support" - ], - "portals/resources/portal-host.html": [ - "5043a158ea74ef173f166c0580f9c1a27242bd14", - "support" - ], "portals/resources/portals-rendering-portal.html": [ "1b6f23f512da5bb7d1c7b5b85e48277470d2e146", "support" @@ -651857,11 +651881,11 @@ "support" ], "referrer-policy/generic/tools/common_paths.py": [ - "9d73401387fe8eea101f76c241b08d2b5e9adca8", + "1066fb5bb238ed5dfd57bc5ba0e98af624bfd9b4", "support" ], "referrer-policy/generic/tools/generate.py": [ - "84aa9feab424d062a05f9a00b914760a1f788dbf", + "46314d445c15897147285a1ce9a826505014f9f5", "support" ], "referrer-policy/generic/tools/regenerate": [ @@ -651869,7 +651893,7 @@ "support" ], "referrer-policy/generic/tools/spec_validator.py": [ - "b59532060a3ef3c2f9c5f6b8b5490e5f8e968be7", + "b1749d2c39911eb90b96479042c4dc2a4ba1360e", "support" ], "referrer-policy/generic/unsupported-csp-referrer-directive.html": [ @@ -682789,11 +682813,11 @@ "testharness" ], "webrtc-quic/RTCQuicTransport-helper.js": [ - "7e28feae0937d4a28710be5f0e807c4af0f7c039", + "b8d9eaed5aad3a18a583200bc958fc375f2b24da", "support" ], "webrtc-quic/RTCQuicTransport.https.html": [ - "081f0b4d976e54301953621a9ef43d3f2c57aa8e", + "c64ed6af093c690ece59a5c68e949c4ae4f5e6af", "testharness" ], "webrtc-stats/META.yml": [ diff --git a/tests/wpt/metadata/css/cssom-view/scroll-behavior-smooth.html.ini b/tests/wpt/metadata/css/cssom-view/scroll-behavior-smooth.html.ini index bcd187f508c..e1a609649d6 100644 --- a/tests/wpt/metadata/css/cssom-view/scroll-behavior-smooth.html.ini +++ b/tests/wpt/metadata/css/cssom-view/scroll-behavior-smooth.html.ini @@ -3,6 +3,3 @@ [scroll-behavior: smooth on DIV element] expected: FAIL - [Instant scrolling while doing history navigation.] - expected: FAIL - diff --git a/tests/wpt/metadata/encoding/single-byte-decoder.html.ini b/tests/wpt/metadata/encoding/single-byte-decoder.html.ini index 71dadbb3bf7..cbded65dd2c 100644 --- a/tests/wpt/metadata/encoding/single-byte-decoder.html.ini +++ b/tests/wpt/metadata/encoding/single-byte-decoder.html.ini @@ -32,7 +32,7 @@ [single-byte-decoder.html?XMLHttpRequest] - expected: TIMEOUT + expected: CRASH [ISO-8859-2: iso_8859-2:1987 (XMLHttpRequest)] expected: FAIL diff --git a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini new file mode 100644 index 00000000000..dc2e45516de --- /dev/null +++ b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini @@ -0,0 +1,4 @@ +[traverse_the_history_5.html] + [Multiple history traversals, last would be aborted] + expected: FAIL + diff --git a/tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini b/tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini index 7725b118e9d..99a24216c88 100644 --- a/tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini +++ b/tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini @@ -12,6 +12,3 @@ [Verifies the resolution of entry.startTime is at least 5 microseconds.] expected: TIMEOUT - [Verifies the resolution of performance.now() is at least 5 microseconds.] - expected: FAIL - diff --git a/tests/wpt/metadata/workers/semantics/multiple-workers/005.html.ini b/tests/wpt/metadata/workers/semantics/multiple-workers/005.html.ini index 268949ced5c..f584fce5df1 100644 --- a/tests/wpt/metadata/workers/semantics/multiple-workers/005.html.ini +++ b/tests/wpt/metadata/workers/semantics/multiple-workers/005.html.ini @@ -1,4 +1,5 @@ [005.html] + expected: ERROR [dedicated worker in shared worker in dedicated worker] expected: FAIL diff --git a/tests/wpt/web-platform-tests/clipboard-apis/async-write-image-read-image-manual.https.html b/tests/wpt/web-platform-tests/clipboard-apis/async-write-image-read-image-manual.https.html index ac7fb0863e7..6117e469792 100644 --- a/tests/wpt/web-platform-tests/clipboard-apis/async-write-image-read-image-manual.https.html +++ b/tests/wpt/web-platform-tests/clipboard-apis/async-write-image-read-image-manual.https.html @@ -6,17 +6,20 @@ -
Original Image:
- -
Image after copy/paste:
- - - +

+

The bottom image should display the same image as the top image.

+

Original Image:

+ +

Image after copy/paste:

+ + +

-

-Note: This is a manual test because it writes/reads to the shared system -clipboard and thus cannot be run async with other tests that might interact -with the clipboard. -

-The bottom image should display the same image as the top image. +

+ Note: This is a manual test because it writes/reads to the shared system + clipboard and thus cannot be run async with other tests that might interact + with the clipboard. +

diff --git a/tests/wpt/web-platform-tests/css/css-logical/logical-box-border-radius.html b/tests/wpt/web-platform-tests/css/css-logical/logical-box-border-radius.html new file mode 100644 index 00000000000..81b8fa0fece --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-logical/logical-box-border-radius.html @@ -0,0 +1,18 @@ + + +CSS Logical Properties: flow-relative border-radius + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/css/css-logical/resources/test-box-properties.js b/tests/wpt/web-platform-tests/css/css-logical/resources/test-box-properties.js index 1f17ff296ff..ef1854f97de 100644 --- a/tests/wpt/web-platform-tests/css/css-logical/resources/test-box-properties.js +++ b/tests/wpt/web-platform-tests/css/css-logical/resources/test-box-properties.js @@ -66,6 +66,41 @@ export function createBoxPropertyGroup(property, descriptor) { return {logical, physical, shorthands, type, prerequisites, property}; } +/** + * Creates a group physical and logical box-corner properties. + * + * @param {string} property + * A string representing the property names, like "border-*-radius". + * @param {Object} descriptor + * @param {string|string[]} descriptor.type + * Describes the kind of values accepted by the property, like "length". + * Must be a key or a collection of keys from the `testValues` object. + * @param {Object={}} descriptor.prerequisites + * Represents property declarations that are needed by `property` to work. + * For example, border-width properties require a border style. + */ +export function createCornerPropertyGroup(property, descriptor) { + const logical = {}; + const physical = {}; + const shorthands = {}; + for (const logicalCorner of ["start-start", "start-end", "end-start", "end-end"]) { + const prop = property.replace("*", logicalCorner); + const [block_side, inline_side] = logicalCorner.split("-"); + const b = "block" + block_side.charAt(0).toUpperCase() + block_side.slice(1); + const i = "inline" + inline_side.charAt(0).toUpperCase() + inline_side.slice(1); + const index = b + "-" + i; // e.g. "blockStart-inlineEnd" + logical[index] = prop; + } + let prerequisites = ""; + for (const physicalCorner of ["top-left", "top-right", "bottom-left", "bottom-right"]) { + const prop = property.replace("*", physicalCorner); + physical[physicalCorner] = prop; + prerequisites += makeDeclaration(descriptor.prerequisites, physicalCorner); + } + const type = [].concat(descriptor.type); + return {logical, physical, shorthands, type, prerequisites, property}; +} + /** * Creates a group of physical and logical sizing properties. * @@ -101,6 +136,7 @@ export function runTests(group) { const logicals = Object.values(group.logical); const physicals = Object.values(group.physical); const shorthands = group.shorthands ? Object.entries(group.shorthands) : null; + const is_corner = group.property == "border-*-radius"; test(function() { const expected = []; @@ -141,7 +177,22 @@ export function runTests(group) { const associated = {}; for (const [logicalSide, logicalProp] of Object.entries(group.logical)) { - const physicalProp = group.physical[writingMode[logicalSide]]; + let physicalProp; + if (is_corner) { + const [ block_side, inline_side] = logicalSide.split("-"); + const physicalSide1 = writingMode[block_side]; + const physicalSide2 = writingMode[inline_side]; + let physicalCorner; + // mirror "left-top" to "top-left" etc + if (["top", "bottom"].includes(physicalSide1)) { + physicalCorner = physicalSide1 + "-" + physicalSide2; + } else { + physicalCorner = physicalSide2 + "-" + physicalSide1; + } + physicalProp = group.physical[physicalCorner]; + } else { + physicalProp = group.physical[writingMode[logicalSide]]; + } associated[logicalProp] = physicalProp; associated[physicalProp] = logicalProp; } diff --git a/tests/wpt/web-platform-tests/css/css-scroll-anchoring/heuristic-with-offset-update.html b/tests/wpt/web-platform-tests/css/css-scroll-anchoring/heuristic-with-offset-update.html new file mode 100644 index 00000000000..7fcbd983ed5 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-scroll-anchoring/heuristic-with-offset-update.html @@ -0,0 +1,58 @@ + + + + + + + + + + +
+
+
+
+
+
+ + + + diff --git a/tests/wpt/web-platform-tests/feature-policy/resources/featurepolicy.js b/tests/wpt/web-platform-tests/feature-policy/resources/featurepolicy.js index a0756e385de..e2577f35c3f 100644 --- a/tests/wpt/web-platform-tests/feature-policy/resources/featurepolicy.js +++ b/tests/wpt/web-platform-tests/feature-policy/resources/featurepolicy.js @@ -83,7 +83,7 @@ function test_feature_availability_with_post_message_result( // tests the feature availability and posts the result back to the parent. // Otherwise, does nothing. function test_feature_in_iframe(feature_name, feature_promise_factory) { - if (location.hash.includes(feature_name)) { + if (location.hash.endsWith(`#${feature_name}`)) { feature_promise_factory().then( () => window.parent.postMessage('#OK', '*'), (e) => window.parent.postMessage('#' + e.name, '*')); diff --git a/tests/wpt/web-platform-tests/kv-storage/api-surface.https.html b/tests/wpt/web-platform-tests/kv-storage/api-surface.https.html index 65452f55be0..90e705862d5 100644 --- a/tests/wpt/web-platform-tests/kv-storage/api-surface.https.html +++ b/tests/wpt/web-platform-tests/kv-storage/api-surface.https.html @@ -23,7 +23,9 @@ test(() => { classAssert.propertyKeys(StorageArea.prototype, [ "constructor", "set", "get", "delete", "clear", "keys", "values", "entries", "backingStore" - ], []); + ], [ + Symbol.asyncIterator + ]); classAssert.methods(StorageArea.prototype, { set: 2, @@ -40,6 +42,10 @@ test(() => { }); }, "StorageArea.prototype methods and properties"); +test(() => { + assert_equals(StorageArea.prototype[Symbol.asyncIterator], StorageArea.prototype.entries); +}, "[Symbol.asyncIterator]() and entries() must be the same function"); + testWithArea(async area => { classAssert.propertyKeys(area, [], []); }, "Instances don't have any properties"); diff --git a/tests/wpt/web-platform-tests/kv-storage/cause-errors-via-idb.https.html b/tests/wpt/web-platform-tests/kv-storage/cause-errors-via-idb.https.html new file mode 100644 index 00000000000..21fe36b36cb --- /dev/null +++ b/tests/wpt/web-platform-tests/kv-storage/cause-errors-via-idb.https.html @@ -0,0 +1,53 @@ + + +KV Storage: causing errors by directly manipulating the IDB + + + + + + diff --git a/tests/wpt/web-platform-tests/kv-storage/entries.https.html b/tests/wpt/web-platform-tests/kv-storage/entries.https.html new file mode 100644 index 00000000000..0d1ab849a70 --- /dev/null +++ b/tests/wpt/web-platform-tests/kv-storage/entries.https.html @@ -0,0 +1,290 @@ + + +KV Storage: entries() trickier tests + + + + + diff --git a/tests/wpt/web-platform-tests/kv-storage/helpers/class-assert.js b/tests/wpt/web-platform-tests/kv-storage/helpers/class-assert.js index 31b25cab9f2..89f0889c56d 100644 --- a/tests/wpt/web-platform-tests/kv-storage/helpers/class-assert.js +++ b/tests/wpt/web-platform-tests/kv-storage/helpers/class-assert.js @@ -38,6 +38,38 @@ export function propertyKeys(o, expectedNames, expectedSymbols, label) { `${label}property symbols`); } +export function iterResultCustom(o, expectedValue, expectedDone, valueAsserter, label) { + label = formatLabel(label); + + assert_equals(typeof expectedDone, "boolean", + `${label} iterResult assert usage check: expectedDone must be a boolean`); + + propertyKeys(o, ["value", "done"], [], label); + assert_equals(Object.getPrototypeOf(o), Object.prototype, `${label}prototype must be Object.prototype`); + valueAsserter(o.value, expectedValue, `${label}value`); + assert_equals(o.done, expectedDone, `${label}done`); +} + +export function iterResult(o, expectedValue, expectedDone, label) { + return iterResultCustom(o, expectedValue, expectedDone, assert_equals, label); +} + +export function iterResultsCustom(actualArray, expectedArrayOfArrays, valueAsserter, label) { + label = formatLabel(label); + + assert_equals(actualArray.length, expectedArrayOfArrays.length, + `${label} iterResults assert usage check: actual and expected must have the same length`); + + for (let i = 0; i < actualArray.length; ++i) { + const [expectedValue, expectedDone] = expectedArrayOfArrays[i]; + iterResultCustom(actualArray[i], expectedValue, expectedDone, valueAsserter, `${label}iter result ${i}`); + } +} + +export function iterResults(actualArray, expectedArrayOfArrays, label) { + return iterResultsCustom(actualArray, expectedArrayOfArrays, assert_equals, label); +} + export function methods(o, expectedMethods) { for (const [name, length] of Object.entries(expectedMethods)) { method(o, name, length); @@ -103,5 +135,5 @@ function isConstructorTest(o) { } function formatLabel(label) { - return label !== undefined ? ` ${label}` : ""; + return label !== undefined ? `${label} ` : ""; } diff --git a/tests/wpt/web-platform-tests/kv-storage/helpers/equality-asserters.js b/tests/wpt/web-platform-tests/kv-storage/helpers/equality-asserters.js index ad4623c179d..448ab31348c 100644 --- a/tests/wpt/web-platform-tests/kv-storage/helpers/equality-asserters.js +++ b/tests/wpt/web-platform-tests/kv-storage/helpers/equality-asserters.js @@ -1,37 +1,91 @@ export function assertEqualDates(actual, expected, label) { - assert_equals(expected.constructor, Date, - "assertEqualDates usage check: expected must be a Date"); + label = formatLabel(label); - const labelPart = label === undefined ? "" : `${label}: `; - assert_equals(actual.constructor, Date, `${labelPart}must be a Date`); - assert_equals(actual.valueOf(), expected.valueOf(), `${labelPart}timestamps must match`); + assert_equals(expected.constructor, Date, + `${label}assertEqualDates usage check: expected must be a Date`); + + assert_equals(actual.constructor, Date, `${label}must be a Date`); + assert_equals(actual.valueOf(), expected.valueOf(), `${label}timestamps must match`); +} + +export function assertEqualPostKeyRoundtripping(actual, expected, label) { + label = formatLabel(label); + + // Please extend this to support other types as needed! + assert_true( + typeof expected === "number" || typeof expected === "string" || expected.constructor === Date, + `${label}assertEqualPostKeyRoundtripping usage check: currently only supports numbers, strings, and dates` + ); + + if (expected.constructor === Date) { + assert_equals(actual.constructor, Date, `${label}comparing to Date(${Number(expected)}) (actual = ${actual})`); + actual = Number(actual); + expected = Number(expected); + } + + assert_equals(actual, expected, label); } export function assertEqualArrayBuffers(actual, expected, label) { - assert_equals(expected.constructor, ArrayBuffer, - "assertEqualArrayBuffers usage check: expected must be an ArrayBuffer"); + label = formatLabel(label); - const labelPart = label === undefined ? "" : `${label}: `; - assert_equals(actual.constructor, ArrayBuffer, `${labelPart}must be an ArrayBuffer`); - assert_array_equals(new Uint8Array(actual), new Uint8Array(expected), `${labelPart}must match`); + assert_equals(expected.constructor, ArrayBuffer, + `${label}assertEqualArrayBuffers usage check: expected must be an ArrayBuffer`); + + assert_equals(actual.constructor, ArrayBuffer, `${label}must be an ArrayBuffer`); + assert_array_equals(new Uint8Array(actual), new Uint8Array(expected), `${label}must match`); } export function assertArrayBufferEqualsABView(actual, expected, label) { + label = formatLabel(label); + assert_true(ArrayBuffer.isView(expected), - "assertArrayBufferEqualsABView usage check: expected must be an ArrayBuffer view"); + `${label}assertArrayBufferEqualsABView usage check: expected must be an ArrayBuffer view`); assertEqualArrayBuffers(actual, expected.buffer, label); } -export function assertArrayCustomEquals(actual, expected, equalityAsserter, label) { - assert_true(Array.isArray(expected), - "assertArrayCustomEquals usage check: expected must be an Array"); +export function assertAsyncIteratorEquals(actual, expected, label) { + return assertAsyncIteratorCustomEquals(actual, expected, Object.is, label); +} - const labelPart = label === undefined ? "" : `${label}: `; - assert_true(Array.isArray(actual), `${labelPart}must be an array`); - assert_equals(actual.length, expected.length, `${labelPart}length must be as expected`); +export function assertArrayCustomEquals(actual, expected, equalityAsserter, label) { + label = formatLabel(label); + + assert_true(Array.isArray(expected), + `${label} assertArrayCustomEquals usage check: expected must be an Array`); + + assert_true(Array.isArray(actual), `${label}must be an array`); + assert_equals(actual.length, expected.length, `${label}length must be as expected`); for (let i = 0; i < actual.length; ++i) { - equalityAsserter(actual[i], expected[i], `${labelPart}index ${i}`); + equalityAsserter(actual[i], expected[i], `${label}index ${i}`); } } + +export async function assertAsyncIteratorCustomEquals(actual, expected, equalityAsserter, label) { + label = formatLabel(label); + + assert_true(Array.isArray(expected), + `${label} assertAsyncIteratorCustomEquals usage check: expected must be an Array`); + + const collected = await collectAsyncIterator(actual); + assert_equals(collected.length, expected.length, `${label}length must be as expected`); + + for (let i = 0; i < collected.length; ++i) { + equalityAsserter(collected[i], expected[i], `${label}index ${i}`); + } +} + +async function collectAsyncIterator(asyncIterator) { + const array = []; + for await (const entry of asyncIterator) { + array.push(entry); + } + + return array; +} + +function formatLabel(label) { + return label !== undefined ? `${label} ` : ""; +} diff --git a/tests/wpt/web-platform-tests/kv-storage/helpers/kvs-tests.js b/tests/wpt/web-platform-tests/kv-storage/helpers/kvs-tests.js index 0ffe71fad78..a6c4d58dfa5 100644 --- a/tests/wpt/web-platform-tests/kv-storage/helpers/kvs-tests.js +++ b/tests/wpt/web-platform-tests/kv-storage/helpers/kvs-tests.js @@ -1,5 +1,5 @@ import { StorageArea, storage as defaultArea } from "std:kv-storage"; -import { assertArrayCustomEquals } from "./equality-asserters.js"; +import { assertAsyncIteratorEquals, assertAsyncIteratorCustomEquals } from "./equality-asserters.js"; export function testWithArea(testFn, description) { promise_test(t => { @@ -36,23 +36,24 @@ function testVariousMethodsInner(key, value, keyEqualityAsserter) { await assertPromiseEquals(area.get(key), value, "get()", "the set value"); - const keysPromise = area.keys(); - assertIsPromise(keysPromise, "keys()"); - assertArrayCustomEquals(await keysPromise, [key], keyEqualityAsserter, "keys() must have the key"); + const keysIter = area.keys(); + await assertAsyncIteratorCustomEquals(keysIter, [key], keyEqualityAsserter, "keys() must have the key"); - const valuesPromise = area.values(); - assertIsPromise(valuesPromise); - assert_array_equals(await valuesPromise, [value], "values() must have the value"); + const valuesIter = area.values(); + await assertAsyncIteratorEquals(valuesIter, [value], "values() must have the value"); - const entriesPromise = area.entries(); - assertIsPromise(entriesPromise, "entries()"); - const entries = await entriesPromise; - assert_true(Array.isArray(entries), "entries() must give an array"); - assert_equals(entries.length, 1, "entries() must have only one value"); - assert_true(Array.isArray(entries[0]), "entries() 0th element must be an array"); - assert_equals(entries[0].length, 2, "entries() 0th element must have 2 elements"); - keyEqualityAsserter(entries[0][0], key, "entries() 0th element's 0th element must be the key"); - assert_equals(entries[0][1], value, "entries() 0th element's 1st element must be the value"); + const entriesIter = area.entries(); + + const entry0 = await entriesIter.next(); + assert_false(entry0.done, "entries() 0th iter-result must not be done"); + assert_true(Array.isArray(entry0.value), "entries() 0th iter-result value must be an array"); + assert_equals(entry0.value.length, 2, "entries() 0th iter-result value must have 2 elements"); + keyEqualityAsserter(entry0.value[0], key, "entries() 0th iter-result value's 0th element must be the key"); + assert_equals(entry0.value[1], value, "entries() 0th iter-result value's 1st element must be the value"); + + const entry1 = await entriesIter.next(); + assert_true(entry1.done, "entries() 1st iter-result must be done"); + assert_equals(entry1.value, undefined, "entries() 1st iter-result must have undefined value"); await assertPromiseEquals(area.delete(key), undefined, "delete()", "undefined"); diff --git a/tests/wpt/web-platform-tests/kv-storage/keys-values-entries.https.html b/tests/wpt/web-platform-tests/kv-storage/keys-values-entries.https.html new file mode 100644 index 00000000000..b26323809bb --- /dev/null +++ b/tests/wpt/web-platform-tests/kv-storage/keys-values-entries.https.html @@ -0,0 +1,95 @@ + + +KV Storage: keys()/values()/entries() + + + + + + + diff --git a/tests/wpt/web-platform-tests/kv-storage/keys.https.html b/tests/wpt/web-platform-tests/kv-storage/keys.https.html new file mode 100644 index 00000000000..a6be29725bf --- /dev/null +++ b/tests/wpt/web-platform-tests/kv-storage/keys.https.html @@ -0,0 +1,236 @@ + + +KV Storage: keys() trickier tests + + + + + diff --git a/tests/wpt/web-platform-tests/kv-storage/undefined-value.https.html b/tests/wpt/web-platform-tests/kv-storage/undefined-value.https.html index 89da5d5c44f..4cb483a3d98 100644 --- a/tests/wpt/web-platform-tests/kv-storage/undefined-value.https.html +++ b/tests/wpt/web-platform-tests/kv-storage/undefined-value.https.html @@ -9,6 +9,7 @@ diff --git a/tests/wpt/web-platform-tests/kv-storage/values.https.html b/tests/wpt/web-platform-tests/kv-storage/values.https.html new file mode 100644 index 00000000000..64756bf195f --- /dev/null +++ b/tests/wpt/web-platform-tests/kv-storage/values.https.html @@ -0,0 +1,231 @@ + + +KV Storage: values() trickier tests + + + + + diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/MediaStream-default-feature-policy.https.html b/tests/wpt/web-platform-tests/mediacapture-streams/MediaStream-default-feature-policy.https.html index 21e3f5b9af8..2e38b9e6864 100644 --- a/tests/wpt/web-platform-tests/mediacapture-streams/MediaStream-default-feature-policy.https.html +++ b/tests/wpt/web-platform-tests/mediacapture-streams/MediaStream-default-feature-policy.https.html @@ -7,56 +7,73 @@ diff --git a/tests/wpt/web-platform-tests/mixed-content/generic/tools/generate.py b/tests/wpt/web-platform-tests/mixed-content/generic/tools/generate.py index e7a315d59ce..1e0a404a709 100755 --- a/tests/wpt/web-platform-tests/mixed-content/generic/tools/generate.py +++ b/tests/wpt/web-platform-tests/mixed-content/generic/tools/generate.py @@ -2,6 +2,7 @@ from __future__ import print_function +import copy import os, sys, json from common_paths import * import spec_validator @@ -67,10 +68,11 @@ def generate_selection(selection, spec, test_html_template_basename): test_html_template_basename) generated_disclaimer = disclaimer_template \ % {'generating_script_filename': os.path.relpath(__file__, - test_root_directory), + test_root_directory), 'html_template_filename': os.path.relpath(html_template_filename, - test_root_directory)} + test_root_directory)} + # Adjust the template for the test invoking JS. Indent it to look nice. selection['generated_disclaimer'] = generated_disclaimer.rstrip() test_description_template = \ test_description_template.rstrip().replace("\n", "\n" + " " * 33) @@ -104,6 +106,7 @@ def generate_selection(selection, spec, test_html_template_basename): # Write out the generated HTML file. write_file(test_filename, test_html_template % selection) + def generate_test_source_files(spec_json, target): test_expansion_schema = spec_json['test_expansion_schema'] specification = spec_json['specification'] @@ -116,33 +119,45 @@ def generate_test_source_files(spec_json, target): html_template = "test.%s.html.template" % target artifact_order = test_expansion_schema.keys() + ['name'] + artifact_order.remove('expansion') # Create list of excluded tests. exclusion_dict = {} for excluded_pattern in spec_json['excluded_tests']: excluded_expansion = \ - expand_pattern(excluded_pattern, - test_expansion_schema) - for excluded_selection in permute_expansion(excluded_expansion, artifact_order): + expand_pattern(excluded_pattern, test_expansion_schema) + for excluded_selection in permute_expansion(excluded_expansion, + artifact_order): excluded_selection_path = selection_pattern % excluded_selection exclusion_dict[excluded_selection_path] = True for spec in specification: + # Used to make entries with expansion="override" override preceding + # entries with the same |selection_path|. + output_dict = {} + for expansion_pattern in spec['test_expansion']: - expansion = expand_pattern(expansion_pattern, - test_expansion_schema) + expansion = expand_pattern(expansion_pattern, test_expansion_schema) for selection in permute_expansion(expansion, artifact_order): selection_path = selection_pattern % selection if not selection_path in exclusion_dict: - generate_selection(selection, - spec, - html_template) + if selection_path in output_dict: + if expansion_pattern['expansion'] != 'override': + print("Error: %s's expansion is default but overrides %s" % (selection['name'], output_dict[selection_path]['name'])) + sys.exit(1) + output_dict[selection_path] = copy.deepcopy(selection) else: print('Excluding selection:', selection_path) + for selection_path in output_dict: + selection = output_dict[selection_path] + generate_selection(selection, + spec, + html_template) + def main(target, spec_filename): - spec_json = load_spec_json(spec_filename); + spec_json = load_spec_json(spec_filename) spec_validator.assert_valid_spec_json(spec_json) generate_test_source_files(spec_json, target) diff --git a/tests/wpt/web-platform-tests/mixed-content/generic/tools/spec_validator.py b/tests/wpt/web-platform-tests/mixed-content/generic/tools/spec_validator.py index 0ae2990f4e1..686579ece57 100755 --- a/tests/wpt/web-platform-tests/mixed-content/generic/tools/spec_validator.py +++ b/tests/wpt/web-platform-tests/mixed-content/generic/tools/spec_validator.py @@ -30,17 +30,17 @@ def assert_contains(obj, field): assert field in obj, 'Must contain field "%s"' % field -def assert_string_from(obj, field, items): +def assert_value_from(obj, field, items): assert obj[field] in items, \ 'Field "%s" must be from: %s' % (field, str(items)) -def assert_string_or_list_items_from(obj, field, items): - if isinstance(obj[field], basestring): - assert_string_from(obj, field, items) +def assert_atom_or_list_items_from(obj, field, items): + if isinstance(obj[field], basestring) or isinstance(obj[field], int): + assert_value_from(obj, field, items) return - assert isinstance(obj[field], list), "%s must be a list!" % field + assert isinstance(obj[field], list), '%s must be a list' % field for allowed_value in obj[field]: assert allowed_value != '*', "Wildcard is not supported for lists!" assert allowed_value in items, \ @@ -63,8 +63,8 @@ def assert_value_unique_in(value, used_values): def assert_valid_artifact(exp_pattern, artifact_key, schema): if isinstance(schema, list): - assert_string_or_list_items_from(exp_pattern, artifact_key, - ["*"] + schema) + assert_atom_or_list_items_from(exp_pattern, artifact_key, + ["*"] + schema) return for sub_artifact_key, sub_schema in schema.iteritems(): @@ -110,7 +110,7 @@ def validate(spec_json, details): for spec_exp in spec['test_expansion']: details['object'] = spec_exp assert_non_empty_string(spec_exp, 'name') - # The name is unique in same expansion group. + # The name is unique in same expansion group. assert_value_unique_in((spec_exp['expansion'], spec_exp['name']), used_spec_names) assert_contains_only_fields(spec_exp, valid_test_expansion_fields) @@ -136,7 +136,14 @@ def validate(spec_json, details): for excluded_test_expansion in excluded_tests: assert_contains_only_fields(excluded_test_expansion, valid_test_expansion_fields) - + details['object'] = excluded_test_expansion + for artifact in test_expansion_schema: + details['test_expansion_field'] = artifact + assert_valid_artifact( + excluded_test_expansion, + artifact, + test_expansion_schema[artifact]) + del details['test_expansion_field'] del details['object'] diff --git a/tests/wpt/web-platform-tests/portals/portals-host-exposure.sub.html b/tests/wpt/web-platform-tests/portals/portals-host-exposure.sub.html deleted file mode 100644 index 83e31bd4735..00000000000 --- a/tests/wpt/web-platform-tests/portals/portals-host-exposure.sub.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - diff --git a/tests/wpt/web-platform-tests/portals/resources/portal-forward-with-broadcast.sub.html b/tests/wpt/web-platform-tests/portals/resources/portal-forward-with-broadcast.sub.html deleted file mode 100644 index 39bda69b0ee..00000000000 --- a/tests/wpt/web-platform-tests/portals/resources/portal-forward-with-broadcast.sub.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/tests/wpt/web-platform-tests/portals/resources/portal-host-cross-origin-navigate.sub.html b/tests/wpt/web-platform-tests/portals/resources/portal-host-cross-origin-navigate.sub.html deleted file mode 100644 index 44c6c16c577..00000000000 --- a/tests/wpt/web-platform-tests/portals/resources/portal-host-cross-origin-navigate.sub.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/tests/wpt/web-platform-tests/portals/resources/portal-host-cross-origin.sub.html b/tests/wpt/web-platform-tests/portals/resources/portal-host-cross-origin.sub.html deleted file mode 100644 index aa369d39f0b..00000000000 --- a/tests/wpt/web-platform-tests/portals/resources/portal-host-cross-origin.sub.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - diff --git a/tests/wpt/web-platform-tests/portals/resources/portal-host.html b/tests/wpt/web-platform-tests/portals/resources/portal-host.html deleted file mode 100644 index 5043a158ea7..00000000000 --- a/tests/wpt/web-platform-tests/portals/resources/portal-host.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/tools/common_paths.py b/tests/wpt/web-platform-tests/referrer-policy/generic/tools/common_paths.py index 9d73401387f..1066fb5bb23 100644 --- a/tests/wpt/web-platform-tests/referrer-policy/generic/tools/common_paths.py +++ b/tests/wpt/web-platform-tests/referrer-policy/generic/tools/common_paths.py @@ -30,6 +30,11 @@ def get_template(basename): return f.read() +def write_file(filename, contents): + with open(filename, "w") as f: + f.write(contents) + + def read_nth_line(fp, line_number): fp.seek(0) for i, line in enumerate(fp): @@ -37,11 +42,14 @@ def read_nth_line(fp, line_number): return line -def load_spec_json(): +def load_spec_json(path_to_spec = None): + if path_to_spec is None: + path_to_spec = spec_filename + re_error_location = re.compile('line ([0-9]+) column ([0-9]+)') - with open(spec_filename, "r") as f: + with open(path_to_spec, "r") as f: try: - spec_json = json.load(f) + return json.load(f) except ValueError as ex: print(ex.message) match = re_error_location.search(ex.message) @@ -49,7 +57,4 @@ def load_spec_json(): line_number, column = int(match.group(1)), int(match.group(2)) print(read_nth_line(f, line_number).rstrip()) print(" " * (column - 1) + "^") - sys.exit(1) - - return spec_json diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/tools/generate.py b/tests/wpt/web-platform-tests/referrer-policy/generic/tools/generate.py index 84aa9feab42..46314d445c1 100755 --- a/tests/wpt/web-platform-tests/referrer-policy/generic/tools/generate.py +++ b/tests/wpt/web-platform-tests/referrer-policy/generic/tools/generate.py @@ -9,24 +9,29 @@ import spec_validator import argparse -def expand_test_expansion_pattern(spec_test_expansion, test_expansion_schema): +def expand_pattern(expansion_pattern, test_expansion_schema): expansion = {} - for artifact in spec_test_expansion: - artifact_value = spec_test_expansion[artifact] + for artifact_key in expansion_pattern: + artifact_value = expansion_pattern[artifact_key] if artifact_value == '*': - expansion[artifact] = test_expansion_schema[artifact] + expansion[artifact_key] = test_expansion_schema[artifact_key] elif isinstance(artifact_value, list): - expansion[artifact] = artifact_value + expansion[artifact_key] = artifact_value + elif isinstance(artifact_value, dict): + # Flattened expansion. + expansion[artifact_key] = [] + values_dict = expand_pattern(artifact_value, + test_expansion_schema[artifact_key]) + for sub_key in values_dict.keys(): + expansion[artifact_key] += values_dict[sub_key] else: - expansion[artifact] = [artifact_value] + expansion[artifact_key] = [artifact_value] return expansion -def permute_expansion(expansion, selection = {}, artifact_index = 0): - artifact_order = ['delivery_method', 'redirection', 'origin', - 'source_protocol', 'target_protocol', 'subresource', - 'referrer_url', 'name'] +def permute_expansion(expansion, artifact_order, selection = {}, artifact_index = 0): + assert isinstance(artifact_order, list), "artifact_order should be a list" if artifact_index >= len(artifact_order): yield selection @@ -37,6 +42,7 @@ def permute_expansion(expansion, selection = {}, artifact_index = 0): for artifact_value in expansion[artifact_key]: selection[artifact_key] = artifact_value for next_selection in permute_expansion(expansion, + artifact_order, selection, artifact_index + 1): yield next_selection @@ -116,8 +122,8 @@ def generate_selection(selection, spec, subresource_path, selection['meta_delivery_method'] = "\n " + \ selection['meta_delivery_method'] - with open(test_filename, 'w') as f: - f.write(test_html_template % selection) + # Write out the generated HTML file. + write_file(test_filename, test_html_template % selection) def generate_test_source_files(spec_json, target): @@ -125,20 +131,22 @@ def generate_test_source_files(spec_json, target): specification = spec_json['specification'] spec_json_js_template = get_template('spec_json.js.template') - with open(generated_spec_json_filename, 'w') as f: - f.write(spec_json_js_template - % {'spec_json': json.dumps(spec_json)}) + write_file(generated_spec_json_filename, + spec_json_js_template % {'spec_json': json.dumps(spec_json)}) # Choose a debug/release template depending on the target. html_template = "test.%s.html.template" % target + artifact_order = test_expansion_schema.keys() + ['name'] + artifact_order.remove('expansion') + # Create list of excluded tests. exclusion_dict = {} for excluded_pattern in spec_json['excluded_tests']: excluded_expansion = \ - expand_test_expansion_pattern(excluded_pattern, - test_expansion_schema) - for excluded_selection in permute_expansion(excluded_expansion): + expand_pattern(excluded_pattern, test_expansion_schema) + for excluded_selection in permute_expansion(excluded_expansion, + artifact_order): excluded_selection_path = selection_pattern % excluded_selection exclusion_dict[excluded_selection_path] = True @@ -147,14 +155,13 @@ def generate_test_source_files(spec_json, target): # entries with the same |selection_path|. output_dict = {} - for spec_test_expansion in spec['test_expansion']: - expansion = expand_test_expansion_pattern(spec_test_expansion, - test_expansion_schema) - for selection in permute_expansion(expansion): + for expansion_pattern in spec['test_expansion']: + expansion = expand_pattern(expansion_pattern, test_expansion_schema) + for selection in permute_expansion(expansion, artifact_order): selection_path = selection_pattern % selection if not selection_path in exclusion_dict: if selection_path in output_dict: - if spec_test_expansion['expansion'] != 'override': + if expansion_pattern['expansion'] != 'override': print("Error: %s's expansion is default but overrides %s" % (selection['name'], output_dict[selection_path]['name'])) sys.exit(1) output_dict[selection_path] = copy.deepcopy(selection) @@ -166,13 +173,13 @@ def generate_test_source_files(spec_json, target): subresource_path = \ spec_json["subresource_path"][selection["subresource"]] generate_selection(selection, - spec, - subresource_path, - html_template) + spec, + subresource_path, + html_template) -def main(target): - spec_json = load_spec_json(); +def main(target, spec_filename): + spec_json = load_spec_json(spec_filename) spec_validator.assert_valid_spec_json(spec_json) generate_test_source_files(spec_json, target) @@ -182,6 +189,8 @@ if __name__ == '__main__': parser.add_argument('-t', '--target', type = str, choices = ("release", "debug"), default = "release", help = 'Sets the appropriate template for generating tests') + parser.add_argument('-s', '--spec', type = str, default = None, + help = 'Specify a file used for describing and generating the tests') # TODO(kristijanburnik): Add option for the spec_json file. args = parser.parse_args() - main(args.target) + main(args.target, args.spec) diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/tools/spec_validator.py b/tests/wpt/web-platform-tests/referrer-policy/generic/tools/spec_validator.py index b59532060a3..b1749d2c399 100755 --- a/tests/wpt/web-platform-tests/referrer-policy/generic/tools/spec_validator.py +++ b/tests/wpt/web-platform-tests/referrer-policy/generic/tools/spec_validator.py @@ -11,36 +11,42 @@ def assert_non_empty_string(obj, field): 'Field "%s" must be a string' % field assert len(obj[field]) > 0, 'Field "%s" must not be empty' % field + def assert_non_empty_list(obj, field): assert isinstance(obj[field], list), \ '%s must be a list' % field assert len(obj[field]) > 0, \ '%s list must not be empty' % field + def assert_non_empty_dict(obj, field): assert isinstance(obj[field], dict), \ '%s must be a dict' % field assert len(obj[field]) > 0, \ '%s dict must not be empty' % field + def assert_contains(obj, field): assert field in obj, 'Must contain field "%s"' % field + def assert_value_from(obj, field, items): assert obj[field] in items, \ 'Field "%s" must be from: %s' % (field, str(items)) + def assert_atom_or_list_items_from(obj, field, items): if isinstance(obj[field], basestring) or isinstance(obj[field], int): assert_value_from(obj, field, items) return - assert_non_empty_list(obj, field) + assert isinstance(obj[field], list), '%s must be a list' % field for allowed_value in obj[field]: assert allowed_value != '*', "Wildcard is not supported for lists!" assert allowed_value in items, \ 'Field "%s" must be from: %s' % (field, str(items)) + def assert_contains_only_fields(obj, expected_fields): for expected_field in expected_fields: assert_contains(obj, expected_field) @@ -49,11 +55,22 @@ def assert_contains_only_fields(obj, expected_fields): assert actual_field in expected_fields, \ 'Unexpected field "%s".' % actual_field + def assert_value_unique_in(value, used_values): assert value not in used_values, 'Duplicate value "%s"!' % str(value) used_values[value] = True +def assert_valid_artifact(exp_pattern, artifact_key, schema): + if isinstance(schema, list): + assert_atom_or_list_items_from(exp_pattern, artifact_key, + ["*"] + schema) + return + + for sub_artifact_key, sub_schema in schema.iteritems(): + assert_valid_artifact(exp_pattern[artifact_key], sub_artifact_key, + sub_schema) + def validate(spec_json, details): """ Validates the json specification for generating tests. """ @@ -102,13 +119,13 @@ def validate(spec_json, details): assert_non_empty_string(spec_exp, 'name') # The name is unique in same expansion group. assert_value_unique_in((spec_exp['expansion'], spec_exp['name']), - used_spec_names) + used_spec_names) assert_contains_only_fields(spec_exp, valid_test_expansion_fields) for artifact in test_expansion_schema: details['test_expansion_field'] = artifact - assert_atom_or_list_items_from( - spec_exp, artifact, ['*'] + test_expansion_schema[artifact]) + assert_valid_artifact(spec_exp, artifact, + test_expansion_schema[artifact]) del details['test_expansion_field'] # Validate the test_expansion schema members. @@ -129,10 +146,10 @@ def validate(spec_json, details): details['object'] = excluded_test_expansion for artifact in test_expansion_schema: details['test_expansion_field'] = artifact - assert_atom_or_list_items_from( + assert_valid_artifact( excluded_test_expansion, artifact, - ['*'] + test_expansion_schema[artifact]) + test_expansion_schema[artifact]) del details['test_expansion_field'] # Validate subresource paths. diff --git a/tests/wpt/web-platform-tests/webrtc-quic/RTCQuicTransport-helper.js b/tests/wpt/web-platform-tests/webrtc-quic/RTCQuicTransport-helper.js index 7e28feae093..b8d9eaed5aa 100644 --- a/tests/wpt/web-platform-tests/webrtc-quic/RTCQuicTransport-helper.js +++ b/tests/wpt/web-platform-tests/webrtc-quic/RTCQuicTransport-helper.js @@ -7,21 +7,11 @@ // makeIceTransport // makeGatherAndStartTwoIceTransports -// Return a promise to generate an RTCCertificate with the given keygen -// algorithm or a default one if none provided. -function generateCertificate(keygenAlgorithm) { - return RTCPeerConnection.generateCertificate({ - name: 'ECDSA', - namedCurve: 'P-256', - ...keygenAlgorithm, - }); -} - // Construct an RTCQuicTransport instance with the given RTCIceTransport // instance and the given certificates. The RTCQuicTransport instance will be // automatically cleaned up when the test finishes. -function makeQuicTransport(t, iceTransport, certificates) { - const quicTransport = new RTCQuicTransport(iceTransport, certificates); +function makeQuicTransport(t, iceTransport) { + const quicTransport = new RTCQuicTransport(iceTransport); t.add_cleanup(() => quicTransport.stop()); return quicTransport; } @@ -30,9 +20,8 @@ function makeQuicTransport(t, iceTransport, certificates) { // and a single, newly-generated certificate. The RTCQuicTransport and // RTCIceTransport instances will be automatically cleaned up when the test // finishes. -async function makeStandaloneQuicTransport(t) { - const certificate = await generateCertificate(); - return makeQuicTransport(t, makeIceTransport(t), [ certificate ]); +function makeStandaloneQuicTransport(t) { + return makeQuicTransport(t, makeIceTransport(t)); } // Construct two RTCQuicTransport instances and each call start() with the other @@ -40,17 +29,16 @@ async function makeStandaloneQuicTransport(t) { // Returns a 2-list: // [ server RTCQuicTransport, // client RTCQuicTransport ] -async function makeAndStartTwoQuicTransports(t) { - const [ localCertificate, remoteCertificate ] = - await Promise.all([ generateCertificate(), generateCertificate() ]); +function makeAndStartTwoQuicTransports(t) { const [ localIceTransport, remoteIceTransport ] = makeGatherAndStartTwoIceTransports(t); const localQuicTransport = - makeQuicTransport(t, localIceTransport, [ localCertificate ]); + makeQuicTransport(t, localIceTransport); const remoteQuicTransport = - makeQuicTransport(t, remoteIceTransport, [ remoteCertificate ]); - localQuicTransport.start(remoteQuicTransport.getLocalParameters()); - remoteQuicTransport.start(localQuicTransport.getLocalParameters()); + makeQuicTransport(t, remoteIceTransport); + const remote_key = remoteQuicTransport.getKey(); + localQuicTransport.listen(remote_key); + remoteQuicTransport.connect(); return [ localQuicTransport, remoteQuicTransport ]; } diff --git a/tests/wpt/web-platform-tests/webrtc-quic/RTCQuicTransport.https.html b/tests/wpt/web-platform-tests/webrtc-quic/RTCQuicTransport.https.html index 081f0b4d976..c64ed6af093 100644 --- a/tests/wpt/web-platform-tests/webrtc-quic/RTCQuicTransport.https.html +++ b/tests/wpt/web-platform-tests/webrtc-quic/RTCQuicTransport.https.html @@ -17,153 +17,50 @@ // makeAndGatherTwoIceTransports // The following helper functions are called from RTCQuicTransport-helper.js: -// generateCertificate // makeQuicTransport // makeStandaloneQuicTransport // makeAndStartTwoQuicTransports // makeTwoConnectedQuicTransports -promise_test(async t => { - const certificate = await generateCertificate(); +test(t => { const iceTransport = makeIceTransport(t); - const quicTransport = makeQuicTransport(t, iceTransport, [ certificate ]); + const quicTransport = makeQuicTransport(t, iceTransport); assert_equals(quicTransport.transport, iceTransport, 'Expect transport to be the same as the one passed in the constructor.'); assert_equals(quicTransport.state, 'new', `Expect state to be 'new'.`); - assert_object_equals(quicTransport.getLocalParameters(), - { role: 'auto', fingerprints: certificate.getFingerprints() }, - 'Expect local parameters to be initialized.'); - assert_equals(quicTransport.getRemoteParameters(), null, - 'Expect no remote parameters.'); - assert_array_equals(quicTransport.getCertificates(), [ certificate ], - 'Expect one certificate.'); - assert_array_equals(quicTransport.getRemoteCertificates(), [], - 'Expect no remote certificates.'); }, 'RTCQuicTransport initial properties are set.'); -promise_test(async t => { - const [ firstCertificate, secondCertificate ] = - await Promise.all([ generateCertificate(), generateCertificate() ]); - const quicTransport = - makeQuicTransport(t, makeIceTransport(t), - [ firstCertificate, secondCertificate ]); - assert_array_equals(quicTransport.getCertificates(), - [ firstCertificate, secondCertificate ]); -}, 'getCertificates() returns the certificates passed in the constructor.'); - -promise_test(async t => { - const [ firstCertificate, secondCertificate ] = - await Promise.all([ generateCertificate(), generateCertificate() ]); - const quicTransport = - makeQuicTransport(t, makeIceTransport(t), - [ firstCertificate, secondCertificate ]); - assert_object_equals(quicTransport.getLocalParameters(), { - role: 'auto', - fingerprints: - [ firstCertificate.getFingerprints()[0], - secondCertificate.getFingerprints()[0] ], - }); - assert_array_equals(quicTransport.getCertificates(), - [ firstCertificate, secondCertificate ]); -}, 'getLocalParameters() has fingerprints for all certificates passed in the ' + - 'constructor.'); - -promise_test(async t => { - const expiredCertificate = await generateCertificate({ expires: 0 }); - assert_throws(new TypeError(), - () => makeQuicTransport(t, makeIceTransport(t), [ expiredCertificate ])); -}, 'RTCQuicTransport constructor throws if passed an expired certificate.'); - -promise_test(async t => { - const certificate = await generateCertificate(); +test(t => { const iceTransport = makeIceTransport(t); iceTransport.stop(); assert_throws('InvalidStateError', - () => makeQuicTransport(t, iceTransport, [ certificate ])); + () => makeQuicTransport(t, iceTransport)); }, 'RTCQuicTransport constructor throws if passed a closed RTCIceTransport.'); -promise_test(async t => { - const certificate = await generateCertificate(); +test(t => { const iceTransport = makeIceTransport(t); const firstQuicTransport = - makeQuicTransport(t, iceTransport, [ certificate ]); + makeQuicTransport(t, iceTransport); assert_throws('InvalidStateError', - () => makeQuicTransport(t, iceTransport, [ certificate ])); + () => makeQuicTransport(t, iceTransport)); }, 'RTCQuicTransport constructor throws if passed an RTCIceTransport that ' + 'already has an active RTCQuicTransport.'); -promise_test(async t => { - const quicTransport = await makeStandaloneQuicTransport(t); +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); quicTransport.stop(); assert_equals(quicTransport.state, 'closed'); }, `stop() changes state to 'closed'.`); -promise_test(async t => { - const quicTransport = await makeStandaloneQuicTransport(t); +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); quicTransport.transport.stop(); assert_equals(quicTransport.state, 'closed'); }, `RTCIceTransport.stop() changes RTCQuicTransport.state to 'closed'.`); -promise_test(async t => { - const quicTransport = await makeStandaloneQuicTransport(t); - quicTransport.start(quicTransport.getLocalParameters()); - assert_equals(quicTransport.state, 'new'); -}, 'start() with a non-started RTCIceTransport does not change state.'); - -promise_test(async t => { - const certificate = await generateCertificate(); - const [ localIceTransport, remoteIceTransport ] = - makeAndGatherTwoIceTransports(t); - const quicTransport = - makeQuicTransport(t, localIceTransport, [ certificate ]); - quicTransport.start(quicTransport.getLocalParameters()); - const iceTransportWatcher = - new EventWatcher(t, remoteIceTransport, 'icecandidate'); - await iceTransportWatcher.wait_for('icecandidate'); - localIceTransport.start(remoteIceTransport.getLocalParameters(), - 'controlling'); - assert_equals(quicTransport.state, 'connecting'); -}, 'start() with a non-started RTCIceTransport later changes state to ' + - `'connecting' once the RTCIceTransport.start() is called.`); - -promise_test(async t => { - const certificate = await generateCertificate(); - const [ localIceTransport, remoteIceTransport ] = - makeAndGatherTwoIceTransports(t); - const quicTransport = - makeQuicTransport(t, localIceTransport, [ certificate ]); - const iceTransportWatcher = - new EventWatcher(t, remoteIceTransport, 'icecandidate'); - await iceTransportWatcher.wait_for('icecandidate'); - localIceTransport.start(remoteIceTransport.getLocalParameters()); - quicTransport.start(quicTransport.getLocalParameters()); - assert_equals(quicTransport.state, 'connecting'); -}, `start() with a started RTCIceTransport changes state to 'connecting'.`); - -promise_test(async t => { - const quicTransport = await makeStandaloneQuicTransport(t); - quicTransport.stop(); - assert_throws('InvalidStateError', - () => quicTransport.start(quicTransport.getLocalParameters())); -}, 'start() throws if called after stop().'); - -promise_test(async t => { - const quicTransport = await makeStandaloneQuicTransport(t); - quicTransport.transport.stop(); - assert_throws('InvalidStateError', - () => quicTransport.start(quicTransport.getLocalParameters())); -}, 'start() throws if called after the RTCIceTransport has stopped.'); - -promise_test(async t => { - const quicTransport = await makeStandaloneQuicTransport(t); - quicTransport.start(quicTransport.getLocalParameters()); - assert_throws('InvalidStateError', - () => quicTransport.start(quicTransport.getLocalParameters())); -}, 'start() throws if called twice.'); - promise_test(async t => { const [ localQuicTransport, remoteQuicTransport ] = - await makeAndStartTwoQuicTransports(t); + makeAndStartTwoQuicTransports(t); const localWatcher = new EventWatcher(t, localQuicTransport, 'statechange'); const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'statechange'); await Promise.all([ @@ -185,5 +82,97 @@ promise_test(async t => { assert_equals(remoteQuicTransport.state, 'closed'); }, `stop() fires a statechange event to 'closed' on the remote transport`); +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + quicTransport.connect(); + assert_equals(quicTransport.state, 'connecting'); +}, `connect() changes state to 'connecting'.`); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + quicTransport.connect(); + assert_throws('InvalidStateError', + () => quicTransport.connect()); +}, 'connect() throws if already called connect().'); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + quicTransport.listen(new Uint8Array([12345])); + assert_throws('InvalidStateError', + () => quicTransport.connect()); +}, 'connect() throws if already called listen().'); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + quicTransport.stop(); + assert_throws('InvalidStateError', + () => quicTransport.connect()); +}, 'connect() throws after stop().'); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + quicTransport.transport.stop(); + assert_throws('InvalidStateError', + () => quicTransport.connect()); +}, 'connect() throws if called after RTCIceTransport has stopped.'); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + quicTransport.listen(new Uint8Array([12345])); + assert_equals(quicTransport.state, 'connecting'); +}, `listen() changes state to 'connecting'.`); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + quicTransport.connect(); + assert_throws('InvalidStateError', + () => quicTransport.listen(new Uint8Array([12345]))); +}, 'listen() throws if already called connect().'); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + quicTransport.listen(new Uint8Array([12345])); + assert_throws('InvalidStateError', + () => quicTransport.listen(new Uint8Array([12345]))); +}, 'listen() throws if already called listen().'); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + quicTransport.stop(); + assert_throws('InvalidStateError', + () => quicTransport.listen(new Uint8Array([12345]))); +}, 'listen() throws after stop().'); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + quicTransport.transport.stop(); + assert_throws('InvalidStateError', + () => quicTransport.listen(new Uint8Array([12345]))); +}, 'listen() throws if called after RTCIceTransport has stopped.'); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + const key = quicTransport.getKey(); + assert_equals(key.byteLength, 16); +}, 'RTCQuicTransport.getKey() attribute is 16 bytes.'); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + const key = new Uint8Array(); + assert_throws('NotSupportedError', + () => quicTransport.listen(key)); +}, 'listen() throws if given an empty key.'); + +test(t => { + const quicTransport = makeStandaloneQuicTransport(t); + const key = quicTransport.getKey(); + let update_key = new Uint8Array(key); + for (let i = 0; i < update_key.length; i++) { + update_key[i] = 0; + } + const new_key = quicTransport.getKey(); + assert_not_equals(update_key, new Uint8Array(new_key)); +}, 'Cannot mutate key retrieved from getKey().'); +