diff options
author | WPT Sync Bot <josh+wptsync@joshmatthews.net> | 2019-01-19 20:34:46 -0500 |
---|---|---|
committer | WPT Sync Bot <josh+wptsync@joshmatthews.net> | 2019-01-19 22:33:07 -0500 |
commit | e17a773b4e78b0fe666fba2b1a73cba72f1bf2cc (patch) | |
tree | ac13f2d876fd8e8201fe962786dc4dcf837337f0 | |
parent | 7256d123ff9620ff1acc494888989c43b176ecee (diff) | |
download | servo-e17a773b4e78b0fe666fba2b1a73cba72f1bf2cc.tar.gz servo-e17a773b4e78b0fe666fba2b1a73cba72f1bf2cc.zip |
Update web-platform-tests to revision bf71b1f245ce34e447b7bde8ed46694574a63da7
35 files changed, 1564 insertions, 464 deletions
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 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<div>Original Image:</div> -<image id='image-to-copy' src="resources/greenbox.png"></image> -<div>Image after copy/paste:</div> -<image id='image-on-clipboard'></image> - -<canvas id="canvas" width="30" height="30"></canvas> +<p> + <p>The bottom image should display the same image as the top image.</p> + <p>Original Image:</p> + <image id='image-to-copy' width='20' height='20' + src="resources/greenbox.png"></image> + <p>Image after copy/paste:</p> + <image id='image-on-clipboard'></image> + <canvas id='canvas' width='20' height='20'></canvas> +</p> <script> // Must compare a bitmap as opposed to simply blob data, because an encoded // image may have different contents depending on encoder. -const getBitmapString = async blob => { +async function getBitmapString(blob) { const imageBitmap = await createImageBitmap(blob); const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); @@ -28,14 +31,13 @@ const getBitmapString = async blob => { return imageData.data.toString(); }; -const loadBlob = async fileName => { +async function loadBlob(fileName) { const fetched = await fetch(fileName); return await fetched.blob(); } promise_test(async t => { - const input = await loadBlob( - 'http://localhost:8001/clipboard-apis/resources/greenbox.png'); + const input = await loadBlob('resources/greenbox.png'); await navigator.clipboard.writeImageExperimental(input); const output = await navigator.clipboard.readImageExperimental(); @@ -49,9 +51,8 @@ promise_test(async t => { assert_equals(comparableOutput, comparableInput); }, "Verify write and read clipboard (DOMString)"); </script> -<br/><br/> -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. -<br/><br/> -The bottom image should display the same image as the top image. +<p> + 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. +</p> 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 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>CSS Logical Properties: flow-relative border-radius</title> +<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com" /> +<link rel="help" href="https://drafts.csswg.org/css-logical-1/#border-radius-properties"> +<meta name="assert" content="This test checks the interaction of the flow-relative border-*-radius properties with the physical ones in different writing modes." /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id="log"></div> + +<script type="module"> +import {runTests, createCornerPropertyGroup} from "./resources/test-box-properties.js"; +runTests(createCornerPropertyGroup("border-*-radius", { + type: "length", + prerequisites: {"border-style": "solid"}, +})); +</script> 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 @@ -67,6 +67,41 @@ export function createBoxPropertyGroup(property, descriptor) { } /** + * 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. * * @param {string} prefix @@ -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 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="help" href="https://drafts.csswg.org/css-scroll-anchoring-1/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<html> +<head> + <style type="text/css"> + #scroller { + overflow: scroll; + height: 500px; + height: 500px; + } + #before { + height: 200px; + } + #anchor { + position: relative; + width: 200px; + height: 200px; + margin-bottom: 500px; + background-color: blue; + /* + * To trigger the Gecko bug that's being regression-tested here, we + * need 'top' to start out at a non-'auto' value, so that the + * dynamic change can trigger Gecko's "RecomputePosition" fast path + */ + top: 0px; + } + </style> +</head> +<body> + <div id="scroller"> + <div id="before"> + </div> + <div id="anchor"> + </div> + </div> + + <script type="text/javascript"> + test(() => { + let scroller = document.querySelector('#scroller'); + let before = document.querySelector('#before'); + let anchor = document.querySelector('#anchor'); + + // Scroll down to select #anchor as a scroll anchor + scroller.scrollTop = 200; + + // Adjust the 'top' of #anchor, which should trigger a suppression + anchor.style.top = '10px'; + + // Expand #before and make sure we don't apply an adjustment + before.style.height = '300px'; + assert_equals(scroller.scrollTop, 200); + }, 'Positioned ancestors with dynamic changes to offsets trigger scroll suppressions.'); + </script> +</body> +</html> 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 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>KV Storage: causing errors by directly manipulating the IDB</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/IndexedDB/support-promises.js"></script> + +<script type="module"> +import { testWithArea } from "./helpers/kvs-tests.js"; + +const mustFail = { + "set()": area => area.set(1, "value 1"), + "get()": area => area.get(1), + "delete()": area => area.delete(1), + "keys()": area => { + const iter = area.keys(); + return iter.next(); + }, + "values()": area => { + const iter = area.values(); + return iter.next(); + }, + "entries()": area => { + const iter = area.entries(); + return iter.next(); + } +}; + +for (const [method, testFn] of Object.entries(mustFail)) { + testWithArea(async (area, t) => { + const { database, store, version } = area.backingStore; + const db = await migrateNamedDatabase(t, database, version + 1, () => {}); + + const result = testFn(area); + + await promise_rejects(t, "VersionError", result); + }, `${method}: upgrading the database must cause a "VersionError" DOMException`); + + testWithArea(async (area, t) => { + const { database, store } = area.backingStore; + + // Set up a new database with that name, but with no object stores! + // NB: this depends on the fact that createNameDatabase sets the initial version to 1, which is + // the same as the database version used/expected by KV Storage. + const db = await createNamedDatabase(t, database, () => {}); + + const result = testFn(area); + + await promise_rejects(t, "NotFoundError", result); + }, `${method}: creating a same-named database with no object store must cause a "NotFoundError" DOMException`); +} +</script> 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 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>KV Storage: entries() trickier tests</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script type="module"> +import { testWithArea } from "./helpers/kvs-tests.js"; +import * as classAssert from "./helpers/class-assert.js"; +import { + assertAsyncIteratorEquals, + assertAsyncIteratorCustomEquals, + assertArrayCustomEquals, + assertEqualPostKeyRoundtripping +} from "./helpers/equality-asserters.js"; + +function assertEqualsArrayOrUndefined(actual, expected, label) { + if (expected === undefined) { + return assert_equals(actual, expected, label); + } + return assert_array_equals(actual, expected, label); +} + +testWithArea(async area => { + await area.set(1, "value 1"); + await area.set(2, "value 2"); + await area.set(3, "value 3"); + + await assertAsyncIteratorCustomEquals( + area.entries(), + [[1, "value 1"], [2, "value 2"], [3, "value 3"]], + assert_array_equals + ); +}, "Using for-await-of to collect the results works"); + +testWithArea(async area => { + // We're not testing every key type since this isn't a test of IndexedDB. + await area.set(1, "value 1"); + await area.set(new Date(500), "value date 500"); + await area.set(-1, "value -1"); + await area.set(new Date(-20), "value date -20"); + await area.set("aaa", "value aaa"); + await area.set("a", "value a"); + await area.set(-Infinity, "value -Infinity"); + + await assertAsyncIteratorCustomEquals( + area.entries(), + [ + [-Infinity, "value -Infinity"], + [-1, "value -1"], + [1, "value 1"], + [new Date(-20), "value date -20"], + [new Date(500), "value date 500"], + ["a", "value a"], + ["aaa", "value aaa"] + ], + (actual, expected, label) => { + return assertArrayCustomEquals(actual, expected, assertEqualPostKeyRoundtripping, label); + } + ); +}, "Results are returned in IndexedDB order"); + +testWithArea(async area => { + await area.set(1, "value 1"); + await area.set(2, "value 2"); + await area.set(3, "value 3"); + + const iter = area.entries(); + const iterResults = [ + await iter.next(), + await iter.next(), + await iter.next(), + await iter.next(), + await iter.next(), + await iter.next() + ]; + + classAssert.iterResultsCustom( + iterResults, + [ + [[1, "value 1"], false], + [[2, "value 2"], false], + [[3, "value 3"], false], + [undefined, true], + [undefined, true], + [undefined, true] + ], + assertEqualsArrayOrUndefined + ); +}, "Manual testing of .next() calls, with awaiting"); + +testWithArea(async area => { + area.set(1, "value 1"); + area.set(2, "value 2"); + area.set(3, "value 3"); + + const iter = area.entries(); + const promises = [ + iter.next(), + iter.next(), + iter.next(), + iter.next(), + iter.next(), + iter.next() + ]; + const iterResults = await Promise.all(promises); + + classAssert.iterResultsCustom( + iterResults, + [ + [[1, "value 1"], false], + [[2, "value 2"], false], + [[3, "value 3"], false], + [undefined, true], + [undefined, true], + [undefined, true] + ], + assertEqualsArrayOrUndefined + ); +}, "Manual testing of .next() calls, no awaiting"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const entry of area.entries()) { + seen.push(entry); + if (entry[0] === 20) { + await area.set(15, "value 15"); + } + } + + assertArrayCustomEquals( + seen, + [[10, "value 10"], [20, "value 20"], [30, "value 30"], [40, "value 40"]], + assert_array_equals + ); +}, "Inserting an entry before the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const entry of area.entries()) { + seen.push(entry); + if (entry[0] === 20) { + await area.set(25, "value 25"); + } + } + + assertArrayCustomEquals( + seen, + [[10, "value 10"], [20, "value 20"], [25, "value 25"], [30, "value 30"], [40, "value 40"]], + assert_array_equals + ); +}, "Inserting an entry after the current entry must show up in iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const entry of area.entries()) { + seen.push(entry); + if (entry[0] === 20) { + await area.delete(10); + } + } + + assertArrayCustomEquals( + seen, + [[10, "value 10"], [20, "value 20"], [30, "value 30"], [40, "value 40"]], + assert_array_equals + ); +}, "Deleting an entry before the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const entry of area.entries()) { + seen.push(entry); + if (entry[0] === 20) { + await area.delete(20); + } + } + + assertArrayCustomEquals( + seen, + [[10, "value 10"], [20, "value 20"], [30, "value 30"], [40, "value 40"]], + assert_array_equals + ); +}, "Deleting the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const entry of area.entries()) { + seen.push(entry); + if (entry[0] === 20) { + await area.delete(30); + } + } + + assertArrayCustomEquals( + seen, + [[10, "value 10"], [20, "value 20"], [40, "value 40"]], + assert_array_equals + ); +}, "Deleting an entry after the current entry must show up in iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const entry of area.entries()) { + seen.push(entry); + if (entry[0] === 20) { + await area.set(10, "value 10, but changed!!"); + } + } + + assertArrayCustomEquals( + seen, + [[10, "value 10"], [20, "value 20"], [30, "value 30"], [40, "value 40"]], + assert_array_equals + ); +}, "Modifying a value before the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const entry of area.entries()) { + seen.push(entry); + if (entry[0] === 20) { + await area.set(20, "value 20, but changed!!"); + } + } + + assertArrayCustomEquals( + seen, + [[10, "value 10"], [20, "value 20"], [30, "value 30"], [40, "value 40"]], + assert_array_equals + ); +}, "Modifying a value at the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const entry of area.entries()) { + seen.push(entry); + if (entry[0] === 20) { + await area.set(30, "value 30, but changed!!"); + } + } + + assertArrayCustomEquals( + seen, + [[10, "value 10"], [20, "value 20"], [30, "value 30, but changed!!"], [40, "value 40"]], + assert_array_equals + ); +}, "Modifying a value after the current entry must show up in iteration"); +</script> 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) { + label = formatLabel(label); + assert_equals(expected.constructor, Date, - "assertEqualDates usage check: expected must be a 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); + } - 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(actual, expected, label); } export function assertEqualArrayBuffers(actual, expected, label) { + label = formatLabel(label); + assert_equals(expected.constructor, ArrayBuffer, - "assertEqualArrayBuffers usage check: expected must be an ArrayBuffer"); + `${label}assertEqualArrayBuffers usage check: expected must be an ArrayBuffer`); - 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(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 assertAsyncIteratorEquals(actual, expected, label) { + return assertAsyncIteratorCustomEquals(actual, expected, Object.is, label); +} + export function assertArrayCustomEquals(actual, expected, equalityAsserter, label) { + label = formatLabel(label); + assert_true(Array.isArray(expected), - "assertArrayCustomEquals usage check: expected must be an Array"); + `${label} assertArrayCustomEquals usage check: expected must be an Array`); - 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`); + 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 valuesPromise = area.values(); - assertIsPromise(valuesPromise); - assert_array_equals(await valuesPromise, [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 keysIter = area.keys(); + await assertAsyncIteratorCustomEquals(keysIter, [key], keyEqualityAsserter, "keys() must have the key"); + + const valuesIter = area.values(); + await assertAsyncIteratorEquals(valuesIter, [value], "values() must have 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 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>KV Storage: keys()/values()/entries()</title> +<!-- + This file contains tests that are easy to generalize over all three methods. + See sibling files for more complicated tests which are not worth generalizing. +--> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/IndexedDB/support-promises.js"></script> + +<script type="module"> +import { testWithArea } from "./helpers/kvs-tests.js"; +import * as classAssert from "./helpers/class-assert.js"; +import { assertAsyncIteratorEquals } from "./helpers/equality-asserters.js"; +// Also uses some global functions included via support-promises.js. + +const AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(async function*() {}).prototype); + +testWithArea(async area => { + const keysProto = Object.getPrototypeOf(area.keys()); + const valuesProto = Object.getPrototypeOf(area.values()); + const entriesProto = Object.getPrototypeOf(area.entries()); + + assert_equals(keysProto, valuesProto, "keys() and values() return values' must have the same [[Prototype]]"); + assert_equals(valuesProto, entriesProto, "values() and entries () return values' must have the same [[Prototype]]"); +}, "keys()/values()/entries() all use the same prototype object"); + +for (const method of ["keys", "values", "entries"]) { + testWithArea(async area => { + const iter = area[method](); + const proto = Object.getPrototypeOf(iter); + assert_equals(Object.getPrototypeOf(proto), AsyncIteratorPrototype, + "[[Prototype]] must be the async iterator prototype"); + classAssert.propertyKeys(proto, ["next"], [], "must only have a next() method"); + }, `${method}() return value is an async iterator of the expected shape`); + + testWithArea(async area => { + const iter = area[method](); + const promise = iter.next(); + + await area.set(1, "value 1"); + + const iterResults = [ + await promise, + await iter.next() + ]; + + classAssert.iterResults(iterResults, [ + [undefined, true], + [undefined, true] + ]); + }, `${method}(): .next() on empty means forever done, even if you set more`); + + testWithArea(async area => { + for await (const key of area[method]()) { + assert_unreached("Loop body must not be entered"); + } + }, `${method}(): for-await-of loop body never executes`); + + testWithArea(async (area, t) => { + await area.set(1, "value 1"); + + const iter = area[method](); + + const { database, store, version } = area.backingStore; + await migrateNamedDatabase(t, database, version + 1, () => {}); + + const iterResultPromise1 = iter.next(); + const iterResultPromise2 = iter.next(); + + await promise_rejects(t, "VersionError", iterResultPromise1, "first next()"); + await promise_rejects(t, "VersionError", iterResultPromise2, "second next()"); + + const iterResultPromise3 = iter.next(); + + assert_not_equals(iterResultPromise1, iterResultPromise2, + "Two promises retrieved from synchronous next() calls must be different (1 vs 2)"); + assert_not_equals(iterResultPromise1, iterResultPromise3, + "Two promises, one retrieved after waiting for the other, must be different (1 vs 3)"); + assert_not_equals(iterResultPromise2, iterResultPromise3, + "Two promises, one retrieved after waiting for the other, must be different (2 vs 3)"); + + await promise_rejects(t, "VersionError", iterResultPromise2, "third next()"); + + const reason1 = await iterResultPromise1.catch(r => r); + const reason2 = await iterResultPromise2.catch(r => r); + const reason3 = await iterResultPromise3.catch(r => r); + + assert_equals(reason1, reason2, "reasons must be the same (1 vs 2)"); + assert_equals(reason2, reason3, "reasons must be the same (2 vs 3)"); + }, `${method}(): error path: returns new rejected promises, each with the same reason`); +} +</script> 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 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>KV Storage: keys() trickier tests</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script type="module"> +import { testWithArea } from "./helpers/kvs-tests.js"; +import * as classAssert from "./helpers/class-assert.js"; +import { + assertAsyncIteratorEquals, + assertAsyncIteratorCustomEquals, + assertEqualPostKeyRoundtripping +} from "./helpers/equality-asserters.js"; + +testWithArea(async area => { + await area.set(1, "value 1"); + await area.set(2, "value 2"); + await area.set(3, "value 3"); + + await assertAsyncIteratorEquals(area.keys(), [1, 2, 3]); +}, "Using for-await-of to collect the results works"); + +testWithArea(async area => { + // We're not testing every key type since this isn't a test of IndexedDB. + await area.set(1, "value 1"); + await area.set(new Date(500), "value date 500"); + await area.set(-1, "value -1"); + await area.set(new Date(-20), "value date -20"); + await area.set("aaa", "value aaa"); + await area.set("a", "value a"); + await area.set(-Infinity, "value -Infinity"); + + await assertAsyncIteratorCustomEquals( + area.keys(), + [ + -Infinity, + -1, + 1, + new Date(-20), + new Date(500), + "a", + "aaa" + ], + assertEqualPostKeyRoundtripping + ); +}, "Results are returned in IndexedDB order"); + +testWithArea(async area => { + await area.set(1, "value 1"); + await area.set(2, "value 2"); + await area.set(3, "value 3"); + + const iter = area.keys(); + const iterResults = [ + await iter.next(), + await iter.next(), + await iter.next(), + await iter.next(), + await iter.next(), + await iter.next() + ]; + + classAssert.iterResults(iterResults, [ + [1, false], + [2, false], + [3, false], + [undefined, true], + [undefined, true], + [undefined, true] + ]); +}, "Manual testing of .next() calls, with awaiting"); + +testWithArea(async area => { + area.set(1, "value 1"); + area.set(2, "value 2"); + area.set(3, "value 3"); + + const iter = area.keys(); + const promises = [ + iter.next(), + iter.next(), + iter.next(), + iter.next(), + iter.next(), + iter.next() + ]; + const iterResults = await Promise.all(promises); + + classAssert.iterResults(iterResults, [ + [1, false], + [2, false], + [3, false], + [undefined, true], + [undefined, true], + [undefined, true] + ]); +}, "Manual testing of .next() calls, no awaiting"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const key of area.keys()) { + seen.push(key); + if (key === 20) { + await area.set(15, "value 15"); + } + } + + assert_array_equals(seen, [10, 20, 30, 40]); +}, "Inserting an entry before the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const key of area.keys()) { + seen.push(key); + if (key === 20) { + await area.set(25, "value 25"); + } + } + + assert_array_equals(seen, [10, 20, 25, 30, 40]); +}, "Inserting an entry after the current entry must show up in iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const key of area.keys()) { + seen.push(key); + if (key === 20) { + await area.delete(10); + } + } + + assert_array_equals(seen, [10, 20, 30, 40]); +}, "Deleting an entry before the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const key of area.keys()) { + seen.push(key); + if (key === 20) { + await area.delete(20); + } + } + + assert_array_equals(seen, [10, 20, 30, 40]); +}, "Deleting the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const key of area.keys()) { + seen.push(key); + if (key === 20) { + await area.delete(30); + } + } + + assert_array_equals(seen, [10, 20, 40]); +}, "Deleting an entry after the current entry must show up in iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const key of area.keys()) { + seen.push(key); + if (key === 20) { + await area.set(10, "value 10, but changed!!"); + } + } + + assert_array_equals(seen, [10, 20, 30, 40]); +}, "Modifying a value before the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const key of area.keys()) { + seen.push(key); + if (key === 20) { + await area.set(20, "value 20, but changed!!"); + } + } + + assert_array_equals(seen, [10, 20, 30, 40]); +}, "Modifying a value at the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const key of area.keys()) { + seen.push(key); + if (key === 20) { + await area.set(30, "value 30, but changed!!"); + } + } + + assert_array_equals(seen, [10, 20, 30, 40]); +}, "Modifying a value after the current entry must have no effect on iteration (since we're iterating keys)"); +</script> 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 @@ <script type="module"> import { StorageArea } from "std:kv-storage"; import { testWithArea } from "./helpers/kvs-tests.js"; +import { assertAsyncIteratorEquals } from "./helpers/equality-asserters.js"; testWithArea(async (area) => { assert_equals(await area.get("key"), undefined); @@ -18,9 +19,9 @@ testWithArea(async (area) => { await area.set("key", undefined); assert_equals(await area.get("key"), undefined); - assert_equals((await area.keys()).length, 0, "number of keys"); - assert_equals((await area.values()).length, 0, "number of values"); - assert_equals((await area.entries()).length, 0, "number of entries"); + await assertAsyncIteratorEquals(area.keys(), [], "keys"); + await assertAsyncIteratorEquals(area.values(), [], "values"); + await assertAsyncIteratorEquals(area.entries(), [], "entries"); }, "Setting undefined as a value when nothing was present is a no-op"); testWithArea(async (area) => { @@ -29,8 +30,8 @@ testWithArea(async (area) => { assert_equals(await area.get("key"), undefined); - assert_equals((await area.keys()).length, 0, "number of keys"); - assert_equals((await area.values()).length, 0, "number of values"); - assert_equals((await area.entries()).length, 0, "number of entries"); + await assertAsyncIteratorEquals(area.keys(), [], "keys"); + await assertAsyncIteratorEquals(area.values(), [], "values"); + await assertAsyncIteratorEquals(area.entries(), [], "entries"); }, "Setting undefined as a value deletes what was previously there"); </script> 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 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>KV Storage: values() trickier tests</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script type="module"> +import { testWithArea } from "./helpers/kvs-tests.js"; +import * as classAssert from "./helpers/class-assert.js"; +import { assertAsyncIteratorEquals } from "./helpers/equality-asserters.js"; + +testWithArea(async area => { + await area.set(1, "value 1"); + await area.set(2, "value 2"); + await area.set(3, "value 3"); + + await assertAsyncIteratorEquals(area.values(), ["value 1", "value 2", "value 3"]); +}, "Using for-await-of to collect the results works"); + +testWithArea(async area => { + // We're not testing every key type since this isn't a test of IndexedDB. + await area.set(1, "value 1"); + await area.set(new Date(500), "value date 500"); + await area.set(-1, "value -1"); + await area.set(new Date(-20), "value date -20"); + await area.set("aaa", "value aaa"); + await area.set("a", "value a"); + await area.set(-Infinity, "value -Infinity"); + + await assertAsyncIteratorEquals( + area.values(), + [ + "value -Infinity", + "value -1", + "value 1", + "value date -20", + "value date 500", + "value a", + "value aaa" + ] + ); +}, "Results are returned in IndexedDB key order"); + +testWithArea(async area => { + await area.set(1, "value 1"); + await area.set(2, "value 2"); + await area.set(3, "value 3"); + + const iter = area.values(); + const iterResults = [ + await iter.next(), + await iter.next(), + await iter.next(), + await iter.next(), + await iter.next(), + await iter.next() + ]; + + classAssert.iterResults(iterResults, [ + ["value 1", false], + ["value 2", false], + ["value 3", false], + [undefined, true], + [undefined, true], + [undefined, true] + ]); +}, "Manual testing of .next() calls, with awaiting"); + +testWithArea(async area => { + area.set(1, "value 1"); + area.set(2, "value 2"); + area.set(3, "value 3"); + + const iter = area.values(); + const promises = [ + iter.next(), + iter.next(), + iter.next(), + iter.next(), + iter.next(), + iter.next() + ]; + const iterResults = await Promise.all(promises); + + classAssert.iterResults(iterResults, [ + ["value 1", false], + ["value 2", false], + ["value 3", false], + [undefined, true], + [undefined, true], + [undefined, true] + ]); +}, "Manual testing of .next() calls, no awaiting"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const value of area.values()) { + seen.push(value); + if (value === "value 20") { + await area.set(15, "value 15"); + } + } + + assert_array_equals(seen, ["value 10", "value 20", "value 30", "value 40"]); +}, "Inserting an entry before the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const value of area.values()) { + seen.push(value); + if (value === "value 20") { + await area.set(25, "value 25"); + } + } + + assert_array_equals(seen, ["value 10", "value 20", "value 25", "value 30", "value 40"]); +}, "Inserting an entry after the current entry must show up in iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const value of area.values()) { + seen.push(value); + if (value === "value 20") { + await area.delete(10); + } + } + + assert_array_equals(seen, ["value 10", "value 20", "value 30", "value 40"]); +}, "Deleting an entry before the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const value of area.values()) { + seen.push(value); + if (value === "value 20") { + await area.delete(20); + } + } + + assert_array_equals(seen, ["value 10", "value 20", "value 30", "value 40"]); +}, "Deleting the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const value of area.values()) { + seen.push(value); + if (value === "value 20") { + await area.delete(30); + } + } + + assert_array_equals(seen, ["value 10", "value 20", "value 40"]); +}, "Deleting an entry after the current entry must show up in iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const value of area.values()) { + seen.push(value); + if (value === "value 20") { + await area.set(10, "value 10, but changed!!"); + } + } + + assert_array_equals(seen, ["value 10", "value 20", "value 30", "value 40"]); +}, "Modifying a value before the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const value of area.values()) { + seen.push(value); + if (value === "value 20") { + await area.set(20, "value 20, but changed!!"); + } + } + + assert_array_equals(seen, ["value 10", "value 20", "value 30", "value 40"]); +}, "Modifying a value at the current entry must have no effect on iteration"); + +testWithArea(async area => { + await area.set(10, "value 10"); + await area.set(20, "value 20"); + await area.set(30, "value 30"); + await area.set(40, "value 40"); + + let seen = []; + for await (const value of area.values()) { + seen.push(value); + if (value === "value 20") { + await area.set(30, "value 30, but changed!!"); + } + } + + assert_array_equals(seen, ["value 10", "value 20", "value 30, but changed!!", "value 40"]); +}, "Modifying a value after the current entry must show up in iteration"); +</script> 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 @@ <script> 'use strict'; - // The promise_factory must return a promise that runs the feature and - // resolves if feature usage is successful, otherwise rejects. Using - // getUserMedia is successful if at least one mic/camera is returned when - // mic/camera has been explicitly allowed by feature policy. - function promise_factory(allowed_features) { - return new Promise((resolve, reject) => { - navigator.mediaDevices.getUserMedia({video: true, audio: true}).then( - function(stream) { - // If microphone is allowed, there should be at least one microphone - // in the result. If camera is allowed, there should be at least one - // camera in the result. - if ((allowed_features.includes('microphone') && - stream.getAudioTracks().length == 0) || - (allowed_features.includes('camera') && - stream.getVideoTracks().length == 0)) { - reject('Feature policy allowed feature but devices not ' + - 'present.'); - } else { - // Otherwise the result is expected. - resolve(); - } - }, - function(error) { reject(error); }); - }); - }; + async function gUM({audio, video}) { + let stream; + try { + stream = await navigator.mediaDevices.getUserMedia({audio, video}); + // getUserMedia must guarantee the number of tracks requested or fail. + if ((audio && stream.getAudioTracks().length == 0) || + (video && stream.getVideoTracks().length == 0)) { + throw {name: `All requested devices must be present with ` + + `audio ${audio} and video ${video}, or fail`}; + } + } finally { + if (stream) { + stream.getTracks().forEach(track => track.stop()); + } + } + } - var cross_domain = get_host_info().HTTPS_REMOTE_ORIGIN; + async function must_disallow_gUM({audio, video}) { + try { + await gUM({audio, video}); + } catch (e) { + if (e.name == 'NotAllowedError') { + return; + } + throw e; + } + throw {name: `audio ${audio} and video ${video} constraints must not be ` + + `allowed.`}; + } + + const cross_domain = get_host_info().HTTPS_REMOTE_ORIGIN; run_all_fp_tests_allow_self( - cross_domain, - 'microphone', - 'NotAllowedError', - function() { - return promise_factory('microphone'); - }); + cross_domain, + 'microphone', + 'NotAllowedError', + async () => { + await gUM({audio: true}); + if (window.location.href.includes(cross_domain)) { + await must_disallow_gUM({video: true}); + await must_disallow_gUM({audio: true, video: true}); + } + } + ); run_all_fp_tests_allow_self( - cross_domain, - 'camera', - 'NotAllowedError', - function() { - return promise_factory('camera'); - }); + cross_domain, + 'camera', + 'NotAllowedError', + async () => { + await gUM({video: true}); + if (window.location.href.includes(cross_domain)) { + await must_disallow_gUM({audio: true}); + await must_disallow_gUM({audio: true, video: true}); + } + } + ); run_all_fp_tests_allow_self( cross_domain, - 'camera; microphone', + 'camera;microphone', 'NotAllowedError', - function() { - return promise_factory('camera; microphone'); - }); + async () => { + await gUM({audio: true, video: true}); + await gUM({audio: true}); + await gUM({video: true}); + } + ); </script> </body> 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 @@ -<!DOCTYPE html> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<body> -<script> - let channelIndex = 0; - async function openPortalAndReceiveMessage(portalSrc) { - let channelName = `portals-host-exposure-${channelIndex++}` - let broadcastChannel = new BroadcastChannel(channelName); - try { - let received = new Promise((resolve, reject) => { - broadcastChannel.addEventListener('message', e => { - resolve(e.data); - }, {once: true}) - }); - let portal = document.createElement('portal'); - portal.src = `${portalSrc}?broadcastchannel=${channelName}`; - document.body.appendChild(portal); - return await received; - } finally { - broadcastChannel.close(); - } - } - - promise_test(async t => { - let {hasHost} = await openPortalAndReceiveMessage( - 'resources/portal-host.html'); - assert_true(hasHost, "window.portalHost should be defined"); - }, "window.portalHost should be exposed in same-origin portal"); - - promise_test(async t => { - let {hasHost} = await openPortalAndReceiveMessage( - 'http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/portal-host-cross-origin.sub.html'); - assert_true(hasHost, "window.portalHost should be defined"); - }, "window.portalHost should be exposed in cross-origin portal"); - - promise_test(async t => { - let {hasHost} = await openPortalAndReceiveMessage( - 'resources/portal-host-cross-origin-navigate.sub.html'); - assert_true(hasHost, "window.portalHost should be defined"); - }, "window.portalHost should be exposed in portal after cross-origin navigation"); - -</script> -</body> 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 @@ -<!DOCTYPE html> -<body> - <script> - function forwardMessage(e) { - let broadcastChannel = new BroadcastChannel(new URL(location).searchParams.get('broadcastchannel')); - try { - broadcastChannel.postMessage(e.data); - } finally { - broadcastChannel.close(); - } - } - window.addEventListener("message", forwardMessage); - </script> -</body> 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 @@ -<!DOCTYPE html> -<body> - <script> - let channelName = new URL(location).searchParams.get('broadcastchannel'); - window.location.href = `http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/portal-host-cross-origin.sub.html?broadcastchannel=${channelName}`; - </script> -</body> 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 @@ -<!DOCTYPE html> -<body> - <script> - let message = { - hasHost: !!window.portalHost - }; - let forwardingIframe = document.createElement('iframe'); - let channelName = new URL(location).searchParams.get('broadcastchannel'); - forwardingIframe.src = `http://{{host}}:{{ports[http][0]}}/portals/resources/portal-forward-with-broadcast.sub.html?broadcastchannel=${channelName}`; - forwardingIframe.onload = () => { - forwardingIframe.contentWindow.postMessage(message, '*'); - } - document.body.appendChild(forwardingIframe); - </script> -</body> 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 @@ -<!DOCTYPE html> -<body> - <script> - let message = { - hasHost: !!window.portalHost - }; - let broadcastChannel = new BroadcastChannel(new URL(location).searchParams.get('broadcastchannel')); - try { - broadcastChannel.postMessage(message); - } finally { - broadcastChannel.close(); - } - </script> -</body> 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().'); + </script> |