Update web-platform-tests to revision 0abb411331f86f472103183c7ec1136ea21a7e1b

This commit is contained in:
WPT Sync Bot 2019-10-31 10:27:09 +00:00
parent d671010e46
commit 5a5512f805
139 changed files with 2559 additions and 1445 deletions

View file

@ -7,7 +7,7 @@
expected: FAIL expected: FAIL
[Opening a blob URL in a new window immediately before revoking it works.] [Opening a blob URL in a new window immediately before revoking it works.]
expected: FAIL expected: TIMEOUT
[Opening a blob URL in a noopener about:blank window immediately before revoking it works.] [Opening a blob URL in a noopener about:blank window immediately before revoking it works.]
expected: FAIL expected: FAIL

View file

@ -128395,6 +128395,18 @@
{} {}
] ]
], ],
"css/css-images/infinite-radial-gradient-crash.html": [
[
"css/css-images/infinite-radial-gradient-crash.html",
[
[
"/css/css-images/infinite-radial-gradient-crash-ref.html",
"=="
]
],
{}
]
],
"css/css-images/linear-gradient-1.html": [ "css/css-images/linear-gradient-1.html": [
[ [
"css/css-images/linear-gradient-1.html", "css/css-images/linear-gradient-1.html",
@ -251340,6 +251352,9 @@
"css/css-images/gradients-with-transparent-ref.html": [ "css/css-images/gradients-with-transparent-ref.html": [
[] []
], ],
"css/css-images/infinite-radial-gradient-crash-ref.html": [
[]
],
"css/css-images/linear-gradient-ref.html": [ "css/css-images/linear-gradient-ref.html": [
[] []
], ],
@ -264627,6 +264642,9 @@
"docs/writing-tests/lint-tool.md": [ "docs/writing-tests/lint-tool.md": [
[] []
], ],
"docs/writing-tests/making-a-testing-plan.md": [
[]
],
"docs/writing-tests/manual.md": [ "docs/writing-tests/manual.md": [
[] []
], ],
@ -274512,9 +274530,21 @@
"infrastructure/metadata/infrastructure/expected-fail/timeout.html.ini": [ "infrastructure/metadata/infrastructure/expected-fail/timeout.html.ini": [
[] []
], ],
"infrastructure/metadata/infrastructure/expected-fail/uncaught-exception-following-subtest.html.ini": [
[]
],
"infrastructure/metadata/infrastructure/expected-fail/uncaught-exception-single-test.html.ini": [
[]
],
"infrastructure/metadata/infrastructure/expected-fail/uncaught-exception.html.ini": [ "infrastructure/metadata/infrastructure/expected-fail/uncaught-exception.html.ini": [
[] []
], ],
"infrastructure/metadata/infrastructure/expected-fail/unhandled-rejection-following-subtest.html.ini": [
[]
],
"infrastructure/metadata/infrastructure/expected-fail/unhandled-rejection-single-test.html.ini": [
[]
],
"infrastructure/metadata/infrastructure/expected-fail/unhandled-rejection.html.ini": [ "infrastructure/metadata/infrastructure/expected-fail/unhandled-rejection.html.ini": [
[] []
], ],
@ -276015,6 +276045,9 @@
"mixed-content/META.yml": [ "mixed-content/META.yml": [
[] []
], ],
"mixed-content/README.md": [
[]
],
"mixed-content/gen/top.http-rp/opt-in/audio-tag/cross-http.keep-scheme.https.html.headers": [ "mixed-content/gen/top.http-rp/opt-in/audio-tag/cross-http.keep-scheme.https.html.headers": [
[] []
], ],
@ -287343,6 +287376,9 @@
"upgrade-insecure-requests/META.yml": [ "upgrade-insecure-requests/META.yml": [
[] []
], ],
"upgrade-insecure-requests/README.md": [
[]
],
"upgrade-insecure-requests/gen/top.http-rp/upgrade/fetch/cross-http-downgrade.downgrade.https.html.headers": [ "upgrade-insecure-requests/gen/top.http-rp/upgrade/fetch/cross-http-downgrade.downgrade.https.html.headers": [
[] []
], ],
@ -288492,6 +288528,9 @@
"webgpu/framework/test_group.js": [ "webgpu/framework/test_group.js": [
[] []
], ],
"webgpu/framework/tree.js": [
[]
],
"webgpu/framework/url_query.js": [ "webgpu/framework/url_query.js": [
[] []
], ],
@ -288510,6 +288549,12 @@
"webgpu/framework/version.js": [ "webgpu/framework/version.js": [
[] []
], ],
"webgpu/runtime/helper/options.js": [
[]
],
"webgpu/runtime/helper/test_worker.js": [
[]
],
"webgpu/runtime/wpt.js": [ "webgpu/runtime/wpt.js": [
[] []
], ],
@ -288555,6 +288600,9 @@
"webgpu/suites/cts/fences.spec.js": [ "webgpu/suites/cts/fences.spec.js": [
[] []
], ],
"webgpu/suites/cts/format_info.js": [
[]
],
"webgpu/suites/cts/gpu_test.js": [ "webgpu/suites/cts/gpu_test.js": [
[] []
], ],
@ -316696,30 +316744,6 @@
{} {}
] ]
], ],
"css/css-box/parsing/min-height-invalid.html": [
[
"css/css-box/parsing/min-height-invalid.html",
{}
]
],
"css/css-box/parsing/min-height-valid.html": [
[
"css/css-box/parsing/min-height-valid.html",
{}
]
],
"css/css-box/parsing/min-width-invalid.html": [
[
"css/css-box/parsing/min-width-invalid.html",
{}
]
],
"css/css-box/parsing/min-width-valid.html": [
[
"css/css-box/parsing/min-width-valid.html",
{}
]
],
"css/css-box/parsing/overflow-invalid.html": [ "css/css-box/parsing/overflow-invalid.html": [
[ [
"css/css-box/parsing/overflow-invalid.html", "css/css-box/parsing/overflow-invalid.html",
@ -327724,6 +327748,12 @@
{} {}
] ]
], ],
"css/css-transforms/transform-scale-hittest.html": [
[
"css/css-transforms/transform-scale-hittest.html",
{}
]
],
"css/css-transforms/transform_translate.html": [ "css/css-transforms/transform_translate.html": [
[ [
"css/css-transforms/transform_translate.html", "css/css-transforms/transform_translate.html",
@ -337797,6 +337827,12 @@
{} {}
] ]
], ],
"element-timing/multi-redirect-image.html": [
[
"element-timing/multi-redirect-image.html",
{}
]
],
"element-timing/multiple-background-images.html": [ "element-timing/multiple-background-images.html": [
[ [
"element-timing/multiple-background-images.html", "element-timing/multiple-background-images.html",
@ -367713,12 +367749,36 @@
{} {}
] ]
], ],
"infrastructure/expected-fail/uncaught-exception-following-subtest.html": [
[
"infrastructure/expected-fail/uncaught-exception-following-subtest.html",
{}
]
],
"infrastructure/expected-fail/uncaught-exception-single-test.html": [
[
"infrastructure/expected-fail/uncaught-exception-single-test.html",
{}
]
],
"infrastructure/expected-fail/uncaught-exception.html": [ "infrastructure/expected-fail/uncaught-exception.html": [
[ [
"infrastructure/expected-fail/uncaught-exception.html", "infrastructure/expected-fail/uncaught-exception.html",
{} {}
] ]
], ],
"infrastructure/expected-fail/unhandled-rejection-following-subtest.html": [
[
"infrastructure/expected-fail/unhandled-rejection-following-subtest.html",
{}
]
],
"infrastructure/expected-fail/unhandled-rejection-single-test.html": [
[
"infrastructure/expected-fail/unhandled-rejection-single-test.html",
{}
]
],
"infrastructure/expected-fail/unhandled-rejection.html": [ "infrastructure/expected-fail/unhandled-rejection.html": [
[ [
"infrastructure/expected-fail/unhandled-rejection.html", "infrastructure/expected-fail/unhandled-rejection.html",
@ -424316,6 +424376,12 @@
{} {}
] ]
], ],
"webgpu/runtime/helper/test_worker.worker.js": [
[
"webgpu/runtime/helper/test_worker.worker.html",
{}
]
],
"webmessaging/Channel_postMessage_Blob.htm": [ "webmessaging/Channel_postMessage_Blob.htm": [
[ [
"webmessaging/Channel_postMessage_Blob.htm", "webmessaging/Channel_postMessage_Blob.htm",
@ -468754,7 +468820,7 @@
"support" "support"
], ],
"common/security-features/README.md": [ "common/security-features/README.md": [
"2bb060a8900396da3fcaf605b768400801523cb1", "98afe1af1be8d6329f9ae687320d4bd4797ca2c8",
"support" "support"
], ],
"common/security-features/resources/common.sub.js": [ "common/security-features/resources/common.sub.js": [
@ -468878,7 +468944,7 @@
"support" "support"
], ],
"common/security-features/tools/generate.py": [ "common/security-features/tools/generate.py": [
"fa36d8c63d6d84a1c5eafd3160b879f7f3c94310", "6fac19827aa1043ad7d3244cf78f44a8ed0b5cbc",
"support" "support"
], ],
"common/security-features/tools/spec_validator.py": [ "common/security-features/tools/spec_validator.py": [
@ -468894,11 +468960,11 @@
"support" "support"
], ],
"common/security-features/tools/template/test.debug.html.template": [ "common/security-features/tools/template/test.debug.html.template": [
"8ec0ab7c07544854367b662b9d0e1fd337189c40", "b4b0fec733e1ce6f6a5cad0f9c9d4391aa244fb1",
"support" "support"
], ],
"common/security-features/tools/template/test.release.html.template": [ "common/security-features/tools/template/test.release.html.template": [
"6416baa8ac83cae43f18b83965e985ecf8740b68", "d93506e231a4c6e719b055b1e312bd163eb9519d",
"support" "support"
], ],
"common/security-features/tools/util.py": [ "common/security-features/tools/util.py": [
@ -557229,22 +557295,6 @@
"1e08a820d9dd1dc98f2bd0ada5550e32081d2e75", "1e08a820d9dd1dc98f2bd0ada5550e32081d2e75",
"testharness" "testharness"
], ],
"css/css-box/parsing/min-height-invalid.html": [
"edc480e1e897e1a46edf8e8aa64d1b4486f96fde",
"testharness"
],
"css/css-box/parsing/min-height-valid.html": [
"0154c02b7b913681515878471553791d9e8a7d45",
"testharness"
],
"css/css-box/parsing/min-width-invalid.html": [
"e89826fb05694890f3469291316db1e2f4a569b9",
"testharness"
],
"css/css-box/parsing/min-width-valid.html": [
"f745b66bd43e24460548b9d5fd3a6d0e46bf4284",
"testharness"
],
"css/css-box/parsing/overflow-invalid.html": [ "css/css-box/parsing/overflow-invalid.html": [
"4747764fb6a4ddd6fadf08d970753923d4afb42b", "4747764fb6a4ddd6fadf08d970753923d4afb42b",
"testharness" "testharness"
@ -577109,6 +577159,14 @@
"6947515f7e4634fc3f240ffda91c6f5bdac862ce", "6947515f7e4634fc3f240ffda91c6f5bdac862ce",
"visual" "visual"
], ],
"css/css-images/infinite-radial-gradient-crash-ref.html": [
"a80236dcf75c22ecd8e43935d004f1fddf0550cb",
"support"
],
"css/css-images/infinite-radial-gradient-crash.html": [
"a3a1e7fb069d311162c5cfa427125bac524ffaa2",
"reftest"
],
"css/css-images/inheritance.html": [ "css/css-images/inheritance.html": [
"5ca1ed6b23ff70637d790baf81ae4e3cbf5afe8c", "5ca1ed6b23ff70637d790baf81ae4e3cbf5afe8c",
"testharness" "testharness"
@ -589186,7 +589244,7 @@
"testharness" "testharness"
], ],
"css/css-sizing/parsing/min-height-invalid.html": [ "css/css-sizing/parsing/min-height-invalid.html": [
"0bb939b12be245758dde7ce93e1edab8a19fa0df", "57119fc1ae50339c6ce34b09a285b6c09185df55",
"testharness" "testharness"
], ],
"css/css-sizing/parsing/min-height-valid.html": [ "css/css-sizing/parsing/min-height-valid.html": [
@ -589198,7 +589256,7 @@
"testharness" "testharness"
], ],
"css/css-sizing/parsing/min-width-invalid.html": [ "css/css-sizing/parsing/min-width-invalid.html": [
"b4e600900dbb8c722567570caa3629c7c5811461", "1286acd9d07047d89fec5d32abe60a7ff5ffae77",
"testharness" "testharness"
], ],
"css/css-sizing/parsing/min-width-valid.html": [ "css/css-sizing/parsing/min-width-valid.html": [
@ -601497,6 +601555,10 @@
"62b5d39037edf2e4ef499c03065e280012b9ddf8", "62b5d39037edf2e4ef499c03065e280012b9ddf8",
"reftest" "reftest"
], ],
"css/css-transforms/transform-scale-hittest.html": [
"5a9d3f85f3983b221bf3705ac342eeddd5c933a3",
"testharness"
],
"css/css-transforms/transform-scale-percent-001.html": [ "css/css-transforms/transform-scale-percent-001.html": [
"79d32b5c0453d7a219cb3d6e03a7653ed342f947", "79d32b5c0453d7a219cb3d6e03a7653ed342f947",
"reftest" "reftest"
@ -631098,13 +631160,17 @@
"support" "support"
], ],
"docs/writing-tests/index.md": [ "docs/writing-tests/index.md": [
"88e279b0ad128d168efc9be3d25209c8ebfec21e", "0e0d3f35b00a20345d319914344bf779d4016aa8",
"support" "support"
], ],
"docs/writing-tests/lint-tool.md": [ "docs/writing-tests/lint-tool.md": [
"f3a34ef1bc0b7c44b28493c246859b172b6f9506", "f3a34ef1bc0b7c44b28493c246859b172b6f9506",
"support" "support"
], ],
"docs/writing-tests/making-a-testing-plan.md": [
"0f5673016c0502edc11c915ee64b4901ed384c23",
"support"
],
"docs/writing-tests/manual.md": [ "docs/writing-tests/manual.md": [
"122a22b3f367d36d749c567c62c09ae9454c2aee", "122a22b3f367d36d749c567c62c09ae9454c2aee",
"support" "support"
@ -633669,6 +633735,10 @@
"06d9bfd07a0f342dbacd00c23bc36b155335f531", "06d9bfd07a0f342dbacd00c23bc36b155335f531",
"testharness" "testharness"
], ],
"element-timing/multi-redirect-image.html": [
"c2f570f20df7989617ea37beaee266562cbf7756",
"testharness"
],
"element-timing/multiple-background-images.html": [ "element-timing/multiple-background-images.html": [
"b29e66c04a70dffbc17f05f516d3d190159ec1c5", "b29e66c04a70dffbc17f05f516d3d190159ec1c5",
"testharness" "testharness"
@ -633730,7 +633800,7 @@
"support" "support"
], ],
"element-timing/resources/element-timing-helpers.js": [ "element-timing/resources/element-timing-helpers.js": [
"6328ee7bb6fc8b29003882b458de90cc282dc591", "b7f2eef5978ac5d559865dd34848f15ef0abba10",
"support" "support"
], ],
"element-timing/resources/iframe-stores-entry.html": [ "element-timing/resources/iframe-stores-entry.html": [
@ -638038,11 +638108,11 @@
"support" "support"
], ],
"fetch/content-length/content-length.html": [ "fetch/content-length/content-length.html": [
"af8ea44eeefa6d797ac69623aaedb11a09161a0e", "cda9b5b523701558c0d613bf6e0e5462b0ffa9c2",
"testharness" "testharness"
], ],
"fetch/content-length/content-length.html.headers": [ "fetch/content-length/content-length.html.headers": [
"385ea556d7a1da0d9a0507ec3633550e4bd82060", "25389b7c0fab38799f117bbe0a4261c02b96cae5",
"support" "support"
], ],
"fetch/content-type/README.md": [ "fetch/content-type/README.md": [
@ -638218,11 +638288,11 @@
"testharness" "testharness"
], ],
"fetch/corb/script-js-mislabeled-as-html-nosniff.sub.html": [ "fetch/corb/script-js-mislabeled-as-html-nosniff.sub.html": [
"f155deff090e4352580847a2aaa41e462d97958a", "b6bc90964deb14afaf4abe3b668d577ca8b23a7e",
"testharness" "testharness"
], ],
"fetch/corb/script-js-mislabeled-as-html.sub.html": [ "fetch/corb/script-js-mislabeled-as-html.sub.html": [
"3a923e66356db1725b1de1b7e211df001cb6f2a5", "44cb1f8659d81dc8059b866bd473caec06add274",
"testharness" "testharness"
], ],
"fetch/corb/script-resource-with-json-parser-breaker.tentative.sub.html": [ "fetch/corb/script-resource-with-json-parser-breaker.tentative.sub.html": [
@ -638230,23 +638300,23 @@
"testharness" "testharness"
], ],
"fetch/corb/script-resource-with-nonsniffable-types.tentative.sub.html": [ "fetch/corb/script-resource-with-nonsniffable-types.tentative.sub.html": [
"592a33ef3baf49b02812d49bbba1105b7766b302", "4e34ecd94b47839f271ec8d6998c06941e76b44f",
"testharness" "testharness"
], ],
"fetch/corb/style-css-mislabeled-as-html-nosniff.sub.html": [ "fetch/corb/style-css-mislabeled-as-html-nosniff.sub.html": [
"1d53621186d26edc447fb74e02b6630c69b03271", "8fef0dc59e437b167cac10edddf113393eab3fa0",
"testharness" "testharness"
], ],
"fetch/corb/style-css-mislabeled-as-html.sub.html": [ "fetch/corb/style-css-mislabeled-as-html.sub.html": [
"05f6fdb9fb955b610b4fc1032cd74bcb48292868", "4f0b4c22f56681f42b540821799cfe4f87cb0580",
"testharness" "testharness"
], ],
"fetch/corb/style-css-with-json-parser-breaker.sub.html": [ "fetch/corb/style-css-with-json-parser-breaker.sub.html": [
"c6b5889c331e22102f77d90f76efae200d051cd7", "29ed586a4f0f2f5b1c26534e45572b559bbc963e",
"testharness" "testharness"
], ],
"fetch/corb/style-html-correctly-labeled.sub.html": [ "fetch/corb/style-html-correctly-labeled.sub.html": [
"c99eb053d61862260891ebdf04338a841f49d2cf", "cdefcd2d2c9a5fa8cd4436591ac31f3ff26700fd",
"testharness" "testharness"
], ],
"fetch/cors-rfc1918/idlharness.tentative.any.js": [ "fetch/cors-rfc1918/idlharness.tentative.any.js": [
@ -638398,7 +638468,7 @@
"testharness" "testharness"
], ],
"fetch/images/canvas-remote-read-remote-image-redirect.html": [ "fetch/images/canvas-remote-read-remote-image-redirect.html": [
"bfcb7537651f285d0aa5d60a41032c534ff39b95", "32a387288af1db934458bcc77512c388ec2ab168",
"testharness" "testharness"
], ],
"fetch/metadata/README.md": [ "fetch/metadata/README.md": [
@ -661106,7 +661176,7 @@
"support" "support"
], ],
"infrastructure/browsers/firefox/prefs.html": [ "infrastructure/browsers/firefox/prefs.html": [
"51f9f994ac50ea8c286bbcb2f47863550e800415", "9656aa051eb6539de8024c56f092f010bfcd1962",
"testharness" "testharness"
], ],
"infrastructure/expected-fail/failing-test.html": [ "infrastructure/expected-fail/failing-test.html": [
@ -661117,10 +661187,26 @@
"29ff348a9af645ff59d860e91af9534e64a606c5", "29ff348a9af645ff59d860e91af9534e64a606c5",
"testharness" "testharness"
], ],
"infrastructure/expected-fail/uncaught-exception-following-subtest.html": [
"ed95c6032841bbdc8ee589ed71cbbb0926dc3ec3",
"testharness"
],
"infrastructure/expected-fail/uncaught-exception-single-test.html": [
"4f88704cad67b24d6291555425b37506b30f8262",
"testharness"
],
"infrastructure/expected-fail/uncaught-exception.html": [ "infrastructure/expected-fail/uncaught-exception.html": [
"4442d513753112fac2e35855268d0b246f01fa09", "4442d513753112fac2e35855268d0b246f01fa09",
"testharness" "testharness"
], ],
"infrastructure/expected-fail/unhandled-rejection-following-subtest.html": [
"2cc19d96243620903eeb115397724380e9ec0289",
"testharness"
],
"infrastructure/expected-fail/unhandled-rejection-single-test.html": [
"925787191c37a2bf897d7ed3fb29def0e15fc92a",
"testharness"
],
"infrastructure/expected-fail/unhandled-rejection.html": [ "infrastructure/expected-fail/unhandled-rejection.html": [
"f25f6e088fa06fbcd38b62929309e761b0060988", "f25f6e088fa06fbcd38b62929309e761b0060988",
"testharness" "testharness"
@ -661157,10 +661243,26 @@
"53b281f8358c4f90aab96c731076439ccb5567b4", "53b281f8358c4f90aab96c731076439ccb5567b4",
"support" "support"
], ],
"infrastructure/metadata/infrastructure/expected-fail/uncaught-exception-following-subtest.html.ini": [
"f7f3d4f7b5dfe3549a1602d84fffb29e70cf18d6",
"support"
],
"infrastructure/metadata/infrastructure/expected-fail/uncaught-exception-single-test.html.ini": [
"6d2bd7f236780e76afec7569405511ae94bf4b88",
"support"
],
"infrastructure/metadata/infrastructure/expected-fail/uncaught-exception.html.ini": [ "infrastructure/metadata/infrastructure/expected-fail/uncaught-exception.html.ini": [
"0bcdd374f2521b6534208ab750a1c0d36e7dd7ca", "0bcdd374f2521b6534208ab750a1c0d36e7dd7ca",
"support" "support"
], ],
"infrastructure/metadata/infrastructure/expected-fail/unhandled-rejection-following-subtest.html.ini": [
"ff1861aff94622eb8559b1c483b67b8da2c54df4",
"support"
],
"infrastructure/metadata/infrastructure/expected-fail/unhandled-rejection-single-test.html.ini": [
"f785f4cc6ec5451cd0d41414d28050165fe38aac",
"support"
],
"infrastructure/metadata/infrastructure/expected-fail/unhandled-rejection.html.ini": [ "infrastructure/metadata/infrastructure/expected-fail/unhandled-rejection.html.ini": [
"39773dfe714a6b5754bfe73c64294bcb38f2afa3", "39773dfe714a6b5754bfe73c64294bcb38f2afa3",
"support" "support"
@ -661490,7 +661592,7 @@
"support" "support"
], ],
"infrastructure/testdriver/file_upload.sub.html": [ "infrastructure/testdriver/file_upload.sub.html": [
"29c42b49f1716200ef6b68eda4fefd716441fcd8", "451ae500f077bab14d30c60f3e8608d10f6516b3",
"testharness" "testharness"
], ],
"infrastructure/testdriver/file_upload_data.txt": [ "infrastructure/testdriver/file_upload_data.txt": [
@ -662078,7 +662180,7 @@
"support" "support"
], ],
"interfaces/webauthn.idl": [ "interfaces/webauthn.idl": [
"cf86a25b1013e0e4102cc9cc67ae0791c963fac6", "81728b8aba4751c6791cad274be67e4c08f505a3",
"support" "support"
], ],
"interfaces/webdriver.idl": [ "interfaces/webdriver.idl": [
@ -665397,6 +665499,10 @@
"a2889eb6c7afd8894955c54c73e77e517541b562", "a2889eb6c7afd8894955c54c73e77e517541b562",
"support" "support"
], ],
"mixed-content/README.md": [
"407b8960cbeb108b729ba5bdc70e1ace41e944ea",
"support"
],
"mixed-content/gen/top.http-rp/opt-in/audio-tag/cross-http.keep-scheme.https.html": [ "mixed-content/gen/top.http-rp/opt-in/audio-tag/cross-http.keep-scheme.https.html": [
"7c3ca228d795bc7cd13d637f05baea5e1c0c61a6", "7c3ca228d795bc7cd13d637f05baea5e1c0c61a6",
"testharness" "testharness"
@ -667998,7 +668104,7 @@
"support" "support"
], ],
"mixed-content/generic/tools/generate.py": [ "mixed-content/generic/tools/generate.py": [
"b80bc8df6bbebe969b88fd48d52abc7819ac9a3c", "060bdabf91cc41f9be0d6c8e5bbf4a8e05c381c1",
"support" "support"
], ],
"mixed-content/imageset.https.sub.html": [ "mixed-content/imageset.https.sub.html": [
@ -677618,7 +677724,7 @@
"support" "support"
], ],
"referrer-policy/README.md": [ "referrer-policy/README.md": [
"498f7f26137b71a7776f07868261776c542b27c7", "ca9977c89ec36493bb6ec35cde30df8e8e6c187a",
"support" "support"
], ],
"referrer-policy/css-integration/README.md": [ "referrer-policy/css-integration/README.md": [
@ -689802,7 +689908,7 @@
"support" "support"
], ],
"referrer-policy/generic/tools/generate.py": [ "referrer-policy/generic/tools/generate.py": [
"480603b9bd870d3e1abd577de31f3f6192caa2e8", "7cace61c0f0b7cd973bf2ea6f88d12a436805d48",
"support" "support"
], ],
"referrer-policy/generic/unsupported-csp-referrer-directive.html": [ "referrer-policy/generic/unsupported-csp-referrer-directive.html": [
@ -690050,15 +690156,15 @@
"testharness" "testharness"
], ],
"resource-timing/crossorigin-sandwich-TAO.sub.html": [ "resource-timing/crossorigin-sandwich-TAO.sub.html": [
"04c5e2c9970c9fa1f6d4427a5a30fab4045f8e9b", "468d055af95b73c59f345065db76f927bf2473c3",
"testharness" "testharness"
], ],
"resource-timing/crossorigin-sandwich-no-TAO.sub.html": [ "resource-timing/crossorigin-sandwich-no-TAO.sub.html": [
"c7e7e5948dc5cbb5fb331112ab2dc562d5e430ad", "d90387b3bbda30224715f5b0602f603b2c2921d4",
"testharness" "testharness"
], ],
"resource-timing/crossorigin-sandwich-partial-TAO.sub.html": [ "resource-timing/crossorigin-sandwich-partial-TAO.sub.html": [
"2b748e9097dacea75424412beae53fe2bf7a2bb7", "076a003b7c993d6e2e092c482733579595928c5f",
"testharness" "testharness"
], ],
"resource-timing/document-domain-no-impact-loader.sub.html": [ "resource-timing/document-domain-no-impact-loader.sub.html": [
@ -690106,7 +690212,7 @@
"testharness" "testharness"
], ],
"resource-timing/resource_TAO_cross_origin_redirect_chain.html": [ "resource-timing/resource_TAO_cross_origin_redirect_chain.html": [
"9089e8fbb00bb8c0e84d7ce7eac84c90b1ed3e04", "054a0e5643e7d9464f27711599843910b57a05a9",
"testharness" "testharness"
], ],
"resource-timing/resource_TAO_match_origin.htm": [ "resource-timing/resource_TAO_match_origin.htm": [
@ -690230,7 +690336,7 @@
"testharness" "testharness"
], ],
"resource-timing/resource_timing_cross_origin_redirect_chain.html": [ "resource-timing/resource_timing_cross_origin_redirect_chain.html": [
"5675f20f1dd78c90c87313ccdbbf4c9a5b7f38dc", "f8d39e7bfa4a5d07e99cd82d8d0b7a5f3158d594",
"testharness" "testharness"
], ],
"resource-timing/resource_timing_same_origin_redirect.html": [ "resource-timing/resource_timing_same_origin_redirect.html": [
@ -690414,7 +690520,7 @@
"support" "support"
], ],
"resource-timing/resources/multi_redirect.py": [ "resource-timing/resources/multi_redirect.py": [
"e70c90bb44827466cfd5a55960de47fe37038f2c", "99387c15bb619e9006dc4a5fa161f1ab4ab66e93",
"support" "support"
], ],
"resource-timing/resources/navigate_back.html": [ "resource-timing/resources/navigate_back.html": [
@ -701566,7 +701672,7 @@
"support" "support"
], ],
"tools/ci/epochs_update.sh": [ "tools/ci/epochs_update.sh": [
"c95f9ca0f13481589ee1358c7ad8fdf94d13328b", "4b393fa6db5f90c18daccf6cef3a9706f1411415",
"support" "support"
], ],
"tools/ci/jobs.py": [ "tools/ci/jobs.py": [
@ -701854,7 +701960,7 @@
"support" "support"
], ],
"tools/manifest/item.py": [ "tools/manifest/item.py": [
"d7165787ca4d6f8e398ecb4400673da4aeaf2d49", "a38709193a9bed82e6bff5849c07679abb6abafd",
"support" "support"
], ],
"tools/manifest/log.py": [ "tools/manifest/log.py": [
@ -702306,11 +702412,11 @@
"support" "support"
], ],
"tools/requirements_flake8.txt": [ "tools/requirements_flake8.txt": [
"d73e7c3dbbe2f0cf20637e639c449b0fa4538caf", "16e35cf5aa957755d0b171e8a86f69c208484996",
"support" "support"
], ],
"tools/requirements_mypy.txt": [ "tools/requirements_mypy.txt": [
"cd4ae2b276937a9abc45db59d950d88ddb6dc626", "31545c2f0747a9c20d77b50d27096a4ecafd4351",
"support" "support"
], ],
"tools/runner/css/bootstrap-theme.min.css": [ "tools/runner/css/bootstrap-theme.min.css": [
@ -706398,7 +706504,7 @@
"support" "support"
], ],
"tools/wpt/revlist.py": [ "tools/wpt/revlist.py": [
"f750311914ac13408cc082e58c36c2471e8f48be", "c4cbc2943b7ce02ef2a58f65d34ab717bfb0c981",
"support" "support"
], ],
"tools/wpt/run.py": [ "tools/wpt/run.py": [
@ -706418,7 +706524,7 @@
"support" "support"
], ],
"tools/wpt/tests/test_revlist.py": [ "tools/wpt/tests/test_revlist.py": [
"7b13106d0f553727f6bdb32c47a6babf70d8f4a8", "ec2a6b899d5d1a927dcad1f9a7583f987a3ad947",
"support" "support"
], ],
"tools/wpt/tests/test_run.py": [ "tools/wpt/tests/test_run.py": [
@ -706686,7 +706792,7 @@
"support" "support"
], ],
"tools/wptrunner/wptrunner/browsers/chrome.py": [ "tools/wptrunner/wptrunner/browsers/chrome.py": [
"c71d77251ea1c84b404674ba6010361ae5705767", "80614c5e551c35dd1cf2bbd12495d40e02391371",
"support" "support"
], ],
"tools/wptrunner/wptrunner/browsers/chrome_android.py": [ "tools/wptrunner/wptrunner/browsers/chrome_android.py": [
@ -707746,7 +707852,7 @@
"support" "support"
], ],
"trusted-types/trusted-types-reporting.tentative.https.html": [ "trusted-types/trusted-types-reporting.tentative.https.html": [
"10a951fa12cb8d69249a96cb85ce34f6136e52c5", "70afb9745a88e6ffbce15a1d868d1f099c339e80",
"testharness" "testharness"
], ],
"trusted-types/trusted-types-reporting.tentative.https.html.headers": [ "trusted-types/trusted-types-reporting.tentative.https.html.headers": [
@ -707949,6 +708055,10 @@
"a30208ae10d9fea605655386462d289907729a16", "a30208ae10d9fea605655386462d289907729a16",
"support" "support"
], ],
"upgrade-insecure-requests/README.md": [
"516e8e262f4b18375689cb45d15f2c516c24571f",
"support"
],
"upgrade-insecure-requests/gen/iframe-blank-inherit.meta/unset/fetch/cross-http-downgrade.downgrade.https.html": [ "upgrade-insecure-requests/gen/iframe-blank-inherit.meta/unset/fetch/cross-http-downgrade.downgrade.https.html": [
"b85583ff2cee179ac58a7c429c79400c438c95b2", "b85583ff2cee179ac58a7c429c79400c438c95b2",
"testharness" "testharness"
@ -710914,7 +711024,7 @@
"support" "support"
], ],
"upgrade-insecure-requests/generic/tools/generate.py": [ "upgrade-insecure-requests/generic/tools/generate.py": [
"cde29893f5fbd35ff0ccf00f7ee323fbb3194c8b", "4c19f4c34dab0ecd302ae22fcffdc3f07ce935c6",
"support" "support"
], ],
"upgrade-insecure-requests/link-upgrade.sub.https.html": [ "upgrade-insecure-requests/link-upgrade.sub.https.html": [
@ -713338,7 +713448,7 @@
"testharness" "testharness"
], ],
"web-nfc/NDEFMessage_constructor.https.html": [ "web-nfc/NDEFMessage_constructor.https.html": [
"0ba82240781300a934cbc0f2fa96abc6a5ff490c", "a6a2e6bd67c5c480367e20dd46e7a796b4c4f8a9",
"testharness" "testharness"
], ],
"web-nfc/NDEFReader-document-hidden-manual.https.html": [ "web-nfc/NDEFReader-document-hidden-manual.https.html": [
@ -713346,7 +713456,7 @@
"manual" "manual"
], ],
"web-nfc/NDEFReader_options.https.html": [ "web-nfc/NDEFReader_options.https.html": [
"b9015dc2a57afbd1f511c84f12ae5085be3b18a0", "ab55e2c160bd39710a62238fce795ff63f03c995",
"testharness" "testharness"
], ],
"web-nfc/NDEFReader_scan.https.html": [ "web-nfc/NDEFReader_scan.https.html": [
@ -713362,7 +713472,7 @@
"testharness" "testharness"
], ],
"web-nfc/NDEFRecord_constructor.https.html": [ "web-nfc/NDEFRecord_constructor.https.html": [
"6a57616d126edf339fc7f3e077b8e427e3480c5e", "cea517d37aa17bf94c3d96c9abd19db5f1fa184c",
"testharness" "testharness"
], ],
"web-nfc/NDEFWriter-document-hidden-manual.https.html": [ "web-nfc/NDEFWriter-document-hidden-manual.https.html": [
@ -713370,7 +713480,7 @@
"manual" "manual"
], ],
"web-nfc/NDEFWriter_push.https.html": [ "web-nfc/NDEFWriter_push.https.html": [
"0d5722bfa019610633cef78d0d2164b2e55de8bb", "fbebac946dfbf77a49c11c0472da900ca26759be",
"testharness" "testharness"
], ],
"web-nfc/README.md": [ "web-nfc/README.md": [
@ -713386,7 +713496,7 @@
"testharness" "testharness"
], ],
"web-nfc/resources/nfc-helpers.js": [ "web-nfc/resources/nfc-helpers.js": [
"4685f65090dbd4c8be36af38960267bd4e7f07a0", "80f0882f9f8deff30b0c8c60ecb1bfc7c6df168c",
"support" "support"
], ],
"web-nfc/resources/support-iframe.html": [ "web-nfc/resources/support-iframe.html": [
@ -715578,7 +715688,7 @@
"support" "support"
], ],
"webdriver/tests/take_element_screenshot/iframe.py": [ "webdriver/tests/take_element_screenshot/iframe.py": [
"d081a14cdeb56d43ee7d10e5b3ec23a53c98bedc", "242122f0b5e7359c364a8aa1da345fc3da15acf1",
"wdspec" "wdspec"
], ],
"webdriver/tests/take_element_screenshot/screenshot.py": [ "webdriver/tests/take_element_screenshot/screenshot.py": [
@ -715594,7 +715704,7 @@
"support" "support"
], ],
"webdriver/tests/take_screenshot/iframe.py": [ "webdriver/tests/take_screenshot/iframe.py": [
"5206f2fa1736f118e5a4b06906325da0e06158b3", "4cf8ad06b56d8f44af06550af4c4a1b7715b908b",
"wdspec" "wdspec"
], ],
"webdriver/tests/take_screenshot/screenshot.py": [ "webdriver/tests/take_screenshot/screenshot.py": [
@ -715646,15 +715756,15 @@
"testharness" "testharness"
], ],
"webgpu/framework/allowed_characters.js": [ "webgpu/framework/allowed_characters.js": [
"f49e19641d95bcc510f09f1bb045825c19d6b28c", "af8f45172b52b3cdc6246218c40e5484a7517a63",
"support" "support"
], ],
"webgpu/framework/collect_garbage.js": [ "webgpu/framework/collect_garbage.js": [
"5589fa7deb3819dfa9cfa0b202e432b73569b675", "dc5a9caf850b967ea0779fee6b7c725376c0bbbb",
"support" "support"
], ],
"webgpu/framework/fixture.js": [ "webgpu/framework/fixture.js": [
"6e13385eef42d8af73b97a44a0945802483538c7", "2c1ea8314689e610528ba81254ee00e99242f4d5",
"support" "support"
], ],
"webgpu/framework/gpu/implementation.js": [ "webgpu/framework/gpu/implementation.js": [
@ -715674,15 +715784,15 @@
"support" "support"
], ],
"webgpu/framework/loader.js": [ "webgpu/framework/loader.js": [
"c9cd20f307c3006b48a3e9f8aac373d56914f76b", "328989a8d7b0a9a305953e735cd2eef58a47d8e0",
"support" "support"
], ],
"webgpu/framework/logger.js": [ "webgpu/framework/logger.js": [
"d97be59091a1d9b5eadd93a105ba1023e730f8a1", "e854292473640a21d6bb660a2a0999e740a90c8e",
"support" "support"
], ],
"webgpu/framework/params/combine.js": [ "webgpu/framework/params/combine.js": [
"d85e81dc88510a314bbffccbf6fa0b6ced61c5ae", "181877cf1650ef59c6d1f19a2ebff8cd84c5b790",
"support" "support"
], ],
"webgpu/framework/params/exclude.js": [ "webgpu/framework/params/exclude.js": [
@ -715694,7 +715804,7 @@
"support" "support"
], ],
"webgpu/framework/params/index.js": [ "webgpu/framework/params/index.js": [
"5d89da54f5b77174615a8d26edf206253fff0ace", "bb21202f92de8395873d807aa02e283067e84bf7",
"support" "support"
], ],
"webgpu/framework/params/options.js": [ "webgpu/framework/params/options.js": [
@ -715722,11 +715832,15 @@
"support" "support"
], ],
"webgpu/framework/test_group.js": [ "webgpu/framework/test_group.js": [
"09697765b8c7c715bac92536418cceb1ce632ef9", "69d8cc0401714f4f6ffe2ddfe0f8763b833914e5",
"support"
],
"webgpu/framework/tree.js": [
"a0690519dbbe9e6ddc4c036acbca60dd409e0dc0",
"support" "support"
], ],
"webgpu/framework/url_query.js": [ "webgpu/framework/url_query.js": [
"f7c7cbc17fe5a908eb5b496a4a267274ebbc0030", "3712432888f6d2ac46aa410bb098ce7971ef0f93",
"support" "support"
], ],
"webgpu/framework/util/async_mutex.js": [ "webgpu/framework/util/async_mutex.js": [
@ -715746,35 +715860,47 @@
"support" "support"
], ],
"webgpu/framework/version.js": [ "webgpu/framework/version.js": [
"0bfbfad4f3995d27200b1601ef8411f5b16c12ae", "55a72f5efb03ad9043ea2600a311cfff249a21ce",
"support" "support"
], ],
"webgpu/runtime/helper/options.js": [
"1a90beadf1ee459911b2b549fc9359b44fe37bbd",
"support"
],
"webgpu/runtime/helper/test_worker.js": [
"8a8c232f3b11b4a326a4f11ef60319d2b157710e",
"support"
],
"webgpu/runtime/helper/test_worker.worker.js": [
"513874144f714e50a289cd22cc88087cd73235e3",
"testharness"
],
"webgpu/runtime/wpt.js": [ "webgpu/runtime/wpt.js": [
"ec4ab0123924659e9cb23ba916c51d7ea6aa75cc", "c87f9167bbeba1edca847a76a6cb59401f0c7409",
"support" "support"
], ],
"webgpu/suites/cts/buffers/create_mapped.spec.js": [ "webgpu/suites/cts/buffers/create_mapped.spec.js": [
"30a6638889a916c03b57a9cbf33ae3f46cdc8eb0", "4a727008b8cfea4d9ef3fa5bd48f2b2c38d8cf37",
"support" "support"
], ],
"webgpu/suites/cts/buffers/map.spec.js": [ "webgpu/suites/cts/buffers/map.spec.js": [
"dfc79ac5d1e9bafb58b00c7bf4c23d029e9605c2", "3794573c83c6e6747e2c9055e72ba892c57fdc8c",
"support" "support"
], ],
"webgpu/suites/cts/buffers/map_detach.spec.js": [ "webgpu/suites/cts/buffers/map_detach.spec.js": [
"afaab08606be74d7bee8544a23b79228a770572b", "c8bd2dc68e5949f7b490b43304636ec1d4f290e2",
"support" "support"
], ],
"webgpu/suites/cts/buffers/map_oom.spec.js": [ "webgpu/suites/cts/buffers/map_oom.spec.js": [
"f39021ca9a181dd5f6b94ee17a895e7f0cd802f2", "db791cedd33018160726dd031272ea4f72ae0f63",
"support" "support"
], ],
"webgpu/suites/cts/buffers/mapping_test.js": [ "webgpu/suites/cts/buffers/mapping_test.js": [
"1baa6ffc3519091622dab337c92b87d1e357a157", "20d6c96ffa2ded3d25990a578d2109548a6f6966",
"support" "support"
], ],
"webgpu/suites/cts/canvas/context_creation.spec.js": [ "webgpu/suites/cts/canvas/context_creation.spec.js": [
"b0b2c48b418ebabf06c42d9a4216536484ae1c8f", "ba0d47228536da7192111f8bd7a6947de7c6181a",
"support" "support"
], ],
"webgpu/suites/cts/command_buffer/basic.spec.js": [ "webgpu/suites/cts/command_buffer/basic.spec.js": [
@ -715782,87 +715908,91 @@
"support" "support"
], ],
"webgpu/suites/cts/command_buffer/compute/basic.spec.js": [ "webgpu/suites/cts/command_buffer/compute/basic.spec.js": [
"a001cbc0d82dc1388e875254d1eddd505ffc01f4", "8fcc7ef9309b5a8760247f0c86ea374c0d3f3e14",
"support" "support"
], ],
"webgpu/suites/cts/command_buffer/copies.spec.js": [ "webgpu/suites/cts/command_buffer/copies.spec.js": [
"0055a58d115303f0dfdd79422babfede04efd3c3", "a93a1b2cbdf3e67724503f1a180cbdf45f5f5fc1",
"support" "support"
], ],
"webgpu/suites/cts/command_buffer/render/basic.spec.js": [ "webgpu/suites/cts/command_buffer/render/basic.spec.js": [
"8f4d8c879da7b16f3fc162c697025c2fab4c6ff7", "89bbdd8a639891cade5dbf11f8cabb3020ab50d7",
"support" "support"
], ],
"webgpu/suites/cts/command_buffer/render/rendering.spec.js": [ "webgpu/suites/cts/command_buffer/render/rendering.spec.js": [
"c065ed23be4f21d3368742e0760f07cea2c6f6ff", "46829a8d07cc51a04ad1ec323fdaf6f5b14e6cdc",
"support" "support"
], ],
"webgpu/suites/cts/command_buffer/render/storeop.spec.js": [ "webgpu/suites/cts/command_buffer/render/storeop.spec.js": [
"da58ad2d8a571685134180199369244339d4a4a1", "0b38debc13425c87def0548f88085aa362a7a7cb",
"support" "support"
], ],
"webgpu/suites/cts/examples.spec.js": [ "webgpu/suites/cts/examples.spec.js": [
"8a992a6239d78c1f45b2323d77690b8c5b4fab1f", "e57de1bfc8d9cf0c8d2264b77e68b56c6c2659f8",
"support" "support"
], ],
"webgpu/suites/cts/fences.spec.js": [ "webgpu/suites/cts/fences.spec.js": [
"ccf513633daf307119ffcfc0eb3e81d27da3f9d3", "ccf513633daf307119ffcfc0eb3e81d27da3f9d3",
"support" "support"
], ],
"webgpu/suites/cts/format_info.js": [
"d1b5b85530bdbd1af762083ad44314ecc7d36fc4",
"support"
],
"webgpu/suites/cts/gpu_test.js": [ "webgpu/suites/cts/gpu_test.js": [
"e437ee09449bae87f6b410c1643b8c23e628d703", "96f109d3043edf8f77d7cbfce88e13b348e44f58",
"support" "support"
], ],
"webgpu/suites/cts/index.js": [ "webgpu/suites/cts/index.js": [
"b38ea11df28f63c6374d9b58df5c276d636b7b8d", "33934cdd38cb51c8a00dc72c436a14965ab7aa28",
"support" "support"
], ],
"webgpu/suites/cts/validation/createBindGroup.spec.js": [ "webgpu/suites/cts/validation/createBindGroup.spec.js": [
"24d29d0e61e653c34ebde4a35bb01717ee23ab9e", "4bc1d0877bab8087b3fa2bd25431b1b681ddef44",
"support" "support"
], ],
"webgpu/suites/cts/validation/createBindGroupLayout.spec.js": [ "webgpu/suites/cts/validation/createBindGroupLayout.spec.js": [
"8e3bfc22572c6e8bbeab51c98520f1cfbb3633b2", "9ac11b49ba621ff076c0e0b94a868ec0b37e6d2e",
"support" "support"
], ],
"webgpu/suites/cts/validation/createPipelineLayout.spec.js": [ "webgpu/suites/cts/validation/createPipelineLayout.spec.js": [
"dc759750a986630dc87ea5136afffb4b3b5bd396", "b82229db3d9296f6dcadf70218d2143fccb8c8f6",
"support" "support"
], ],
"webgpu/suites/cts/validation/createRenderPipeline.spec.js": [ "webgpu/suites/cts/validation/createRenderPipeline.spec.js": [
"7cbe93dd9c958cc8331316a522846d126be89556", "cc838fc6515a5b9a7cc55bacc0361556a3bdd93c",
"support" "support"
], ],
"webgpu/suites/cts/validation/createTexture.spec.js": [ "webgpu/suites/cts/validation/createTexture.spec.js": [
"c99204b9667fbfa53d743eff285a4090abe70b07", "77f1c9709b6cddda912bacd988408671cb20e8bb",
"support" "support"
], ],
"webgpu/suites/cts/validation/createView.spec.js": [ "webgpu/suites/cts/validation/createView.spec.js": [
"2330c6ecdd91abedde02e88391921586cfd40dec", "855d32a3f43990295513385ebbd161fa38d4f04a",
"support" "support"
], ],
"webgpu/suites/cts/validation/error_scope.spec.js": [ "webgpu/suites/cts/validation/error_scope.spec.js": [
"2232db9b54e48426abf18f0d3c91f3c8901437de", "0ff9699a3ad3d8ef43176b3aeefb6c46d4796788",
"support" "support"
], ],
"webgpu/suites/cts/validation/fences.spec.js": [ "webgpu/suites/cts/validation/fences.spec.js": [
"4aca3d7773afff6a801a705ca36fe675ee429588", "6c5c9f9faa14a0b9f3ee2ff5bf6dc52a9fd4e8e6",
"support" "support"
], ],
"webgpu/suites/cts/validation/queue_submit.spec.js": [ "webgpu/suites/cts/validation/queue_submit.spec.js": [
"50d912f4d6f2a3d53e072fae9b9930616e7ed1a7", "410e3c26e82b82637d45a2bb01e136130d82a6aa",
"support" "support"
], ],
"webgpu/suites/cts/validation/render_pass.spec.js": [ "webgpu/suites/cts/validation/render_pass.spec.js": [
"f71a4a2b97420ab76ead6cadf29c31e3d440ce1a", "52da36fa7ac9cb196aaf578707acf09a7f62724d",
"support" "support"
], ],
"webgpu/suites/cts/validation/render_pass_descriptor.spec.js": [ "webgpu/suites/cts/validation/render_pass_descriptor.spec.js": [
"5a171879082762b039c1f21d18f7066b5c193078", "59caf533e6c3674b82ead7cd1e05048c4de3d308",
"support" "support"
], ],
"webgpu/suites/cts/validation/setBindGroup.spec.js": [ "webgpu/suites/cts/validation/setBindGroup.spec.js": [
"c669ea08d586b4911a74336314c72437aa2abec3", "73ae4ba502ea31e07fce16dc3b64766e43d53bfa",
"support" "support"
], ],
"webgpu/suites/cts/validation/setBlendColor.spec.js": [ "webgpu/suites/cts/validation/setBlendColor.spec.js": [
@ -715870,7 +716000,7 @@
"support" "support"
], ],
"webgpu/suites/cts/validation/setScissorRect.spec.js": [ "webgpu/suites/cts/validation/setScissorRect.spec.js": [
"ee1588d2a885bd2d0fc386737b3e37a5fc91dd7d", "aec75f536a1dca7c4448b6d901060735e7d86f6c",
"support" "support"
], ],
"webgpu/suites/cts/validation/setStencilReference.spec.js": [ "webgpu/suites/cts/validation/setStencilReference.spec.js": [
@ -715878,19 +716008,19 @@
"support" "support"
], ],
"webgpu/suites/cts/validation/setVertexBuffer.spec.js": [ "webgpu/suites/cts/validation/setVertexBuffer.spec.js": [
"949dd91932d8d4e6b498f578e11d5c7c3fb019df", "1df40173abe0eab97fe384b12df94f0e4ec03c3b",
"support" "support"
], ],
"webgpu/suites/cts/validation/setViewport.spec.js": [ "webgpu/suites/cts/validation/setViewport.spec.js": [
"5610930829e58862955ec7ba26e17d96ca5cb253", "715a236b18db388750f672d1caabf1466fe46611",
"support" "support"
], ],
"webgpu/suites/cts/validation/validation_test.js": [ "webgpu/suites/cts/validation/validation_test.js": [
"35ad5d895521f1207ab21be1de5af3a0d672cc4f", "099b8202204d06b41403410f287a770a0945559d",
"support" "support"
], ],
"webgpu/suites/cts/validation/vertex_input.spec.js": [ "webgpu/suites/cts/validation/vertex_input.spec.js": [
"432a04a4ceef0e895e0bc881bf6d4f2ec7f91034", "951c9ead3cfc53569bbcfa322252edef3b672609",
"support" "support"
], ],
"webmessaging/Channel_postMessage_Blob.htm": [ "webmessaging/Channel_postMessage_Blob.htm": [

View file

@ -0,0 +1,7 @@
[transform-scale-hittest.html]
[Hit test within unscaled box]
expected: FAIL
[Hit test intersecting scaled box]
expected: FAIL

View file

@ -6,9 +6,6 @@
[rethrows errors when getting handleEvent] [rethrows errors when getting handleEvent]
expected: TIMEOUT expected: TIMEOUT
[doesn't look up handleEvent method on callable event listeners]
expected: FAIL
[throws if handleEvent is thruthy and not callable] [throws if handleEvent is thruthy and not callable]
expected: NOTRUN expected: NOTRUN

View file

@ -2,6 +2,6 @@
[listeners are called when <iframe> is resized] [listeners are called when <iframe> is resized]
expected: FAIL expected: FAIL
[listener that was added twice is called only once] [listeners are called correct number of times]
expected: FAIL expected: FAIL

View file

@ -1,2 +0,0 @@
[contenttype_txt.html]
expected: CRASH

View file

@ -318,18 +318,15 @@
[<iframe>: separate response Content-Type: text/plain */*;charset=gbk] [<iframe>: separate response Content-Type: text/plain */*;charset=gbk]
expected: FAIL expected: FAIL
[<iframe>: separate response Content-Type: text/html */*]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;" text/plain] [<iframe>: combined response Content-Type: text/html;" text/plain]
expected: FAIL expected: FAIL
[<iframe>: combined response Content-Type: text/html */*]
expected: FAIL
[<iframe>: separate response Content-Type: text/html;x=" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;x=" text/plain] [<iframe>: combined response Content-Type: text/html;x=" text/plain]
expected: FAIL expected: FAIL
[<iframe>: separate response Content-Type: text/plain */*]
expected: FAIL
[<iframe>: separate response Content-Type: text/html;" \\" text/plain]
expected: FAIL

View file

@ -53,6 +53,15 @@
[combined text/javascript ] [combined text/javascript ]
expected: FAIL expected: FAIL
[separate text/javascript;charset=windows-1252 text/javascript] [separate text/javascript;charset=windows-1252 error text/javascript]
expected: FAIL
[separate text/javascript x/x]
expected: FAIL
[separate text/javascript error]
expected: FAIL
[separate text/javascript ]
expected: FAIL expected: FAIL

View file

@ -1,4 +1,5 @@
[script-resource-with-nonsniffable-types.tentative.sub.html] [script-resource-with-nonsniffable-types.tentative.sub.html]
expected: TIMEOUT
[CORB blocks 'multipart/byteranges'] [CORB blocks 'multipart/byteranges']
expected: FAIL expected: FAIL
@ -17,3 +18,6 @@
[CORB blocks 'application/x-gzip'] [CORB blocks 'application/x-gzip']
expected: FAIL expected: FAIL
[script-resource-with-nonsniffable-types]
expected: FAIL

View file

@ -0,0 +1,2 @@
[joint-session-history-remove-iframe.html]
expected: CRASH

View file

@ -1,4 +1,4 @@
[traverse_the_history_2.html] [traverse_the_history_4.html]
[Multiple history traversals, last would be aborted] [Multiple history traversals, last would be aborted]
expected: FAIL expected: FAIL

View file

@ -1,24 +1,5 @@
[open-features-negative-innerwidth-innerheight.html] [open-features-negative-innerwidth-innerheight.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: negative values for legacy `innerwidth`, `innerheight`] [HTML: window.open `features`: negative values for legacy `innerwidth`, `innerheight`]
expected: FAIL expected: FAIL
[features "innerheight=-404.5" should NOT set "height=404"]
expected: TIMEOUT
[features "innerwidth=-404.5" should NOT set "width=404"]
expected: TIMEOUT
[features "innerwidth=-404" should NOT set "width=404"]
expected: TIMEOUT
[features "innerheight=-404e1" should NOT set "height=404"]
expected: TIMEOUT
[features "innerheight=-404" should NOT set "height=404"]
expected: TIMEOUT
[features "innerwidth=-404e1" should NOT set "width=404"]
expected: TIMEOUT

View file

@ -1,24 +1,5 @@
[open-features-negative-width-height.html] [open-features-negative-width-height.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: negative values for `width`, `height`] [HTML: window.open `features`: negative values for `width`, `height`]
expected: FAIL expected: FAIL
[features "height=-404" should NOT set "height=404"]
expected: TIMEOUT
[features "height=-404e1" should NOT set "height=404"]
expected: TIMEOUT
[features "height=-404.5" should NOT set "height=404"]
expected: TIMEOUT
[features "width=-404" should NOT set "width=404"]
expected: TIMEOUT
[features "width=-404e1" should NOT set "width=404"]
expected: TIMEOUT
[features "width=-404.5" should NOT set "width=404"]
expected: TIMEOUT

View file

@ -1,48 +1,32 @@
[open-features-non-integer-height.html] [open-features-non-integer-height.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: non-integer values for feature `height`] [HTML: window.open `features`: non-integer values for feature `height`]
expected: FAIL expected: FAIL
[features "height=405*3" should set "height=405"] [features "height=405*3" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "height=405.32" should set "height=405"] [features "height=405.32" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "height=405e1" should set "height=405"] [features "height=405e1" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "height=405/5" should set "height=405"] [features "height=405/5" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "height=405^4" should set "height=405"] [features "height=405^4" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "height=405.5" should set "height=405"] [features "height=405.5" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "height=405e-1" should set "height=405"] [features "height=405e-1" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "height=405 " should set "height=405"] [features "height=405 " should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "height=405LLl" should set "height=405"] [features "height=405LLl" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "height=/404" should NOT set "height=404"]
expected: TIMEOUT
[top=0,left=0,width=401,: absence of feature "height" should be treated same as "height=0"]
expected: TIMEOUT
[top=0,left=0: absence of feature "height" should be treated same as "height=0"]
expected: TIMEOUT
[features "height=_404" should NOT set "height=404"]
expected: TIMEOUT
[features "height=L404" should NOT set "height=404"]
expected: TIMEOUT

View file

@ -1,42 +1,32 @@
[open-features-non-integer-innerheight.html] [open-features-non-integer-innerheight.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: non-integer values for legacy feature `innerheight`] [HTML: window.open `features`: non-integer values for legacy feature `innerheight`]
expected: FAIL expected: FAIL
[features "innerheight=405e-1" should set "height=405"] [features "innerheight=405e-1" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "innerheight=405LLl" should set "height=405"] [features "innerheight=405LLl" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "innerheight=405^4" should set "height=405"] [features "innerheight=405^4" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "innerheight=405e1" should set "height=405"] [features "innerheight=405e1" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "innerheight=405 " should set "height=405"] [features "innerheight=405 " should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "innerheight=405/5" should set "height=405"] [features "innerheight=405/5" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "innerheight=405.32" should set "height=405"] [features "innerheight=405.32" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "innerheight=405.5" should set "height=405"] [features "innerheight=405.5" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "innerheight=405*3" should set "height=405"] [features "innerheight=405*3" should set "height=405"]
expected: TIMEOUT expected: FAIL
[features "innerheight=_404" should NOT set "height=404"]
expected: TIMEOUT
[features "innerheight=L404" should NOT set "height=404"]
expected: TIMEOUT
[features "innerheight=/404" should NOT set "height=404"]
expected: TIMEOUT

View file

@ -1,42 +1,32 @@
[open-features-non-integer-innerwidth.html] [open-features-non-integer-innerwidth.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: non-integer values for legacy feature `innerwidth`] [HTML: window.open `features`: non-integer values for legacy feature `innerwidth`]
expected: FAIL expected: FAIL
[features "innerwidth=405e-1" should set "width=405"] [features "innerwidth=405e-1" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "innerwidth=405*3" should set "width=405"] [features "innerwidth=405*3" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "innerwidth=405.5" should set "width=405"] [features "innerwidth=405.5" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "innerwidth=405e1" should set "width=405"] [features "innerwidth=405e1" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "innerwidth=405.32" should set "width=405"] [features "innerwidth=405.32" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "innerwidth=405 " should set "width=405"] [features "innerwidth=405 " should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "innerwidth=405LLl" should set "width=405"] [features "innerwidth=405LLl" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "innerwidth=405/5" should set "width=405"] [features "innerwidth=405/5" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "innerwidth=405^4" should set "width=405"] [features "innerwidth=405^4" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "innerwidth=/404" should NOT set "width=404"]
expected: TIMEOUT
[features "innerwidth=_404" should NOT set "width=404"]
expected: TIMEOUT
[features "innerwidth=L404" should NOT set "width=404"]
expected: TIMEOUT

View file

@ -1,42 +1,32 @@
[open-features-non-integer-left.html] [open-features-non-integer-left.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: non-integer values for feature `left`] [HTML: window.open `features`: non-integer values for feature `left`]
expected: FAIL expected: FAIL
[features "left=105e1" should set "left=105"] [features "left=105e1" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "left=105 " should set "left=105"] [features "left=105 " should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "left=105/5" should set "left=105"] [features "left=105/5" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "left=105e-1" should set "left=105"] [features "left=105e-1" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "left=105^4" should set "left=105"] [features "left=105^4" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "left=105LLl" should set "left=105"] [features "left=105LLl" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "left=105.32" should set "left=105"] [features "left=105.32" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "left=105*3" should set "left=105"] [features "left=105*3" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "left=105.5" should set "left=105"] [features "left=105.5" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "left=L104" should NOT set "left=104"]
expected: TIMEOUT
[features "left=/104" should NOT set "left=104"]
expected: TIMEOUT
[features "left=_104" should NOT set "left=104"]
expected: TIMEOUT

View file

@ -1,17 +1,16 @@
[open-features-non-integer-screenx.html] [open-features-non-integer-screenx.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: non-integer values for legacy feature `screenx`] [HTML: window.open `features`: non-integer values for legacy feature `screenx`]
expected: FAIL expected: FAIL
[features "screenx=105.5" should set "left=105"] [features "screenx=105.5" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "screenx=105e1" should set "left=105"] [features "screenx=105e1" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "screenx=105 " should set "left=105"] [features "screenx=105 " should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "screenx=105*3" should set "left=105"] [features "screenx=105*3" should set "left=105"]
expected: FAIL expected: FAIL
@ -20,20 +19,14 @@
expected: FAIL expected: FAIL
[features "screenx=105^4" should set "left=105"] [features "screenx=105^4" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "screenx=105LLl" should set "left=105"] [features "screenx=105LLl" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "screenx=105/5" should set "left=105"] [features "screenx=105/5" should set "left=105"]
expected: TIMEOUT expected: FAIL
[features "screenx=105.32" should set "left=105"] [features "screenx=105.32" should set "left=105"]
expected: FAIL expected: FAIL
[features "screenx=L104" should NOT set "left=104"]
expected: TIMEOUT
[features "screenx=/104" should NOT set "left=104"]
expected: TIMEOUT

View file

@ -1,42 +1,32 @@
[open-features-non-integer-top.html] [open-features-non-integer-top.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: non-integer values for feature `top`] [HTML: window.open `features`: non-integer values for feature `top`]
expected: FAIL expected: FAIL
[features "top=105/5" should set "top=105"] [features "top=105/5" should set "top=105"]
expected: TIMEOUT expected: FAIL
[features "top=105*3" should set "top=105"] [features "top=105*3" should set "top=105"]
expected: TIMEOUT expected: FAIL
[features "top=105LLl" should set "top=105"] [features "top=105LLl" should set "top=105"]
expected: TIMEOUT expected: FAIL
[features "top=105e-1" should set "top=105"] [features "top=105e-1" should set "top=105"]
expected: TIMEOUT expected: FAIL
[features "top=105.32" should set "top=105"] [features "top=105.32" should set "top=105"]
expected: TIMEOUT expected: FAIL
[features "top=105e1" should set "top=105"] [features "top=105e1" should set "top=105"]
expected: TIMEOUT expected: FAIL
[features "top=105 " should set "top=105"] [features "top=105 " should set "top=105"]
expected: TIMEOUT expected: FAIL
[features "top=105^4" should set "top=105"] [features "top=105^4" should set "top=105"]
expected: TIMEOUT expected: FAIL
[features "top=105.5" should set "top=105"] [features "top=105.5" should set "top=105"]
expected: TIMEOUT expected: FAIL
[features "top=/104" should NOT set "top=104"]
expected: TIMEOUT
[features "top=_104" should NOT set "top=104"]
expected: TIMEOUT
[features "top=L104" should NOT set "top=104"]
expected: TIMEOUT

View file

@ -1,48 +1,32 @@
[open-features-non-integer-width.html] [open-features-non-integer-width.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: non-integer values for feature `width`] [HTML: window.open `features`: non-integer values for feature `width`]
expected: FAIL expected: FAIL
[features "width=405^4" should set "width=405"] [features "width=405^4" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "width=405.5" should set "width=405"] [features "width=405.5" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "width=405e1" should set "width=405"] [features "width=405e1" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "width=405 " should set "width=405"] [features "width=405 " should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "width=405.32" should set "width=405"] [features "width=405.32" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "width=405LLl" should set "width=405"] [features "width=405LLl" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "width=405*3" should set "width=405"] [features "width=405*3" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "width=405e-1" should set "width=405"] [features "width=405e-1" should set "width=405"]
expected: TIMEOUT expected: FAIL
[features "width=405/5" should set "width=405"] [features "width=405/5" should set "width=405"]
expected: TIMEOUT expected: FAIL
[top=0,left=0: absence of feature "width" should be treated same as "width=0"]
expected: TIMEOUT
[features "width=_404" should NOT set "width=404"]
expected: TIMEOUT
[top=0,left=0,height=401,: absence of feature "width" should be treated same as "width=0"]
expected: TIMEOUT
[features "width=/404" should NOT set "width=404"]
expected: TIMEOUT
[features "width=L404" should NOT set "width=404"]
expected: TIMEOUT

View file

@ -1,4 +1,5 @@
[embedded-opener-remove-frame.html] [embedded-opener-remove-frame.html]
expected: CRASH
[opener and "removed" embedded documents] [opener and "removed" embedded documents]
expected: FAIL expected: FAIL

View file

@ -1,11 +1,7 @@
[supported-elements.html] [supported-elements.html]
expected: TIMEOUT
[Contenteditable element should support autofocus] [Contenteditable element should support autofocus]
expected: FAIL expected: FAIL
[Element with tabindex should support autofocus] [Element with tabindex should support autofocus]
expected: TIMEOUT expected: FAIL
[Non-HTMLElement should not support autofocus]
expected: NOTRUN

View file

@ -1,10 +0,0 @@
[non-active-document.html]
[DOMParser]
expected: FAIL
[createHTMLDocument]
expected: FAIL
[<template>]
expected: FAIL

View file

@ -0,0 +1,4 @@
[DOMContentLoaded-defer.html]
[The end: DOMContentLoaded and defer scripts]
expected: FAIL

View file

@ -1,5 +0,0 @@
[018.html]
expected: TIMEOUT
[origin of the script that invoked the method, javascript:]
expected: TIMEOUT

View file

@ -1,4 +1,5 @@
[import-in-moduleworker.html] [import-in-moduleworker.html]
expected: ERROR
[Base URL in module dedicated workers: import] [Base URL in module dedicated workers: import]
expected: FAIL expected: FAIL

View file

@ -1,9 +1,15 @@
This directory contains the common infrastructure for the following tests.
This directory contains the common infrastructure for the following tests (also referred below as projects).
- referrer-policy/ - referrer-policy/
- mixed-content/ - mixed-content/
- upgrade-insecure-requests/ - upgrade-insecure-requests/
Subdirectories: Subdirectories:
- `resources`:
Serves JavaScript test helpers.
- `subresource`: - `subresource`:
Serves subresources, with support for redirects, stash, etc. Serves subresources, with support for redirects, stash, etc.
The subresource paths are managed by `subresourceMap` and The subresource paths are managed by `subresourceMap` and
@ -11,10 +17,183 @@ Subdirectories:
- `scope`: - `scope`:
Serves nested contexts, such as iframe documents or workers. Serves nested contexts, such as iframe documents or workers.
Used from `invokeFrom*()` functions in `resources/common.js`. Used from `invokeFrom*()` functions in `resources/common.js`.
- `tools`:
Scripts that generate test HTML files. Not used while running tests.
- `/referrer-policy/generic/subresource-test`:
Sanity checking tests for subresource invocation
(This is still placed outside common/)
# spec.src.json format # Test generator
## Source Contexts The test generator (`common/security-features/tools`) generates test HTML files from templates and a seed (`spec.src.json`) that defines all the test scenarios.
The project (i.e. a WPT subdirectory, for example `referrer-policy/`) that uses the generator should define per-project data and invoke the common generator logic in `common/security-features/tools`.
This is the overview of the project structure:
```
common/security-features/
└── tools/ - the common test generator logic
└── template/ - the test files templates
project-directory/ (e.g. referrer-policy/)
├── spec.src.json
├── generic/
│ ├── test-case.sub.js - Per-project test helper
│ └── tools/
│ └── generator.py - Per-project generator script
└── gen/ - generated tests
```
Invoking `project-directory/generic/tools/generate.py` will parse the spec JSON and determine which tests to generate (or skip) while using templates.
## Generating the tests
The repository already contains generated tests, so if you're making changes, see the [Removing all generated tests](#removing-all-generated-tests) section below, on how to remove them before you start generating tests which include your changes.
```bash
# Chdir into the project directory.
cd ~/web-platform-tests/project-directory
# Generate the test files under gen/ (HTMLs and .headers files).
./generic/tools/generate.py
# Add all generated tests to the repo.
git add gen/ && git commit -m "Add generated tests"
```
During the generation, the spec is validated by ```common/security-features/tools/spec_validator.py```. This is specially important when you're making changes to `spec.src.json`. Make sure it's a valid JSON (no comments or trailing commas). The validator reports specific errors (missing keys etc.), if any.
### Removing all generated tests
Simply remove all files under `project-directory/gen/`.
```bash
# Chdir into the project directory.
cd ~/web-platform-tests/project-directory
# Remove all generated tests.
rm -r gen/
```
### Options for generating tests
Note: this section is currently obsolete. Only the release template is working.
The generator script ```./generic/tools/generate.py``` has two targets: ```release``` and ```debug```.
* Using **release** for the target will produce tests using a template for optimizing size and performance. The release template is intended for the official web-platform-tests and possibly other test suites. No sanity checking is done in release mode. Use this option whenever you're checking into web-platform-tests.
* When generating for ```debug```, the produced tests will contain more verbosity and sanity checks. Use this target to identify problems with the test suites when making changes locally. Make sure you don't check in tests generated with the debug target.
Note that **release** is the default target when invoking ```generate.py```.
## Updating the tests
The main test logic lives in ```project-directory/generic/test-case.sub.js``` with helper functions defined in ```/common/security-features/resources/common.js``` so you should probably start there.
For updating the test suites you will most likely do **a subset** of the following:
* Add a new subresource type:
* Add a new sub-resource python script to `/common/security-features/subresource/`.
* Add a sanity check test for a sub-resource to `referrer-policy/generic/subresource-test/`.
* Add a new entry to `subresourceMap` in `/common/security-features/resources/common.js`.
* Add a new entry to `valid_subresource_names` in `/common/security-features/tools/spec_validator.py`.
* Add a new entry to `subresource_schema` in `spec.src.json`.
* Update `source_context_schema` to specify in which source context the subresource can be used.
* Add a new subresource redirection type
* TODO: to be documented. Example: [https://github.com/web-platform-tests/wpt/pull/18939](https://github.com/web-platform-tests/wpt/pull/18939)
* Add a new subresource origin type
* TODO: to be documented. Example: [https://github.com/web-platform-tests/wpt/pull/18940](https://github.com/web-platform-tests/wpt/pull/18940)
* Add a new source context (e.g. "module sharedworker global scope")
* TODO: to be documented. Example: [https://github.com/web-platform-tests/wpt/pull/18904](https://github.com/web-platform-tests/wpt/pull/18904)
* Add a new source context list (e.g. "subresource request from a dedicated worker in a `<iframe srcdoc>`")
* TODO: to be documented.
* Implement new or update existing assertions in ```project-directory/generic/test-case.sub.js```.
* Exclude or add some tests by updating ```spec.src.json``` test expansions.
* Implement a new delivery method.
* TODO: to be documented. Currently the support for delivery methods are implemented in many places across `common/security-features/`.
* Regenerate the tests and MANIFEST.json
## The spec JSON format
For examples of spec JSON files, see [referrer-policy/spec.src.json](../../referrer-policy/spec.src.json) or [mixed-content/spec.src.json](../../mixed-content/spec.src.json).
### Main sections
* **`specification`**
Top level requirements with description fields and a ```test_expansion``` rule.
This is closely mimicking the [Referrer Policy specification](http://w3c.github.io/webappsec/specs/referrer-policy/) structure.
* **`excluded_tests`**
List of ```test_expansion``` patterns expanding into selections which get skipped when generating the tests (aka. blacklisting/suppressing)
* **`test_expansion_schema`**
Provides valid values for each field.
Each test expansion can only contain fields and values defined by this schema (or `"*"` values that indicate all the valid values defined this schema).
* **`subresource_schema`**
Provides metadata of subresources, e.g. supported delivery types for each subresource.
* **`source_context_schema`**
Provides metadata of each single source context, e.g. supported delivery types and subresources that can be sent from the context.
* **`source_context_list_schema`**
Provides possible nested combinations of source contexts. See [Source Contexts](#source-contexts) section below for details.
### Test Expansion Patterns
Each field in a test expansion can be in one of the following formats:
* Single match: ```"value"```
* Match any of: ```["value1", "value2", ...]```
* Match all: ```"*"```
**NOTE:** An expansion is always constructive (inclusive), there isn't a negation operator for explicit exclusion. Be aware that using an empty list ```[]``` matches (expands into) exactly nothing. Tests which are to be excluded should be defined in the ```excluded_tests``` section instead.
A single test expansion pattern, be it a requirement or a suppressed pattern, gets expanded into a list of **selections** as follows:
* Expand each field's pattern (single, any of, or all) to list of allowed values (defined by the ```test_expansion_schema```)
* Permute - Recursively enumerate all **selections** across all fields
Be aware that if there is more than one pattern expanding into a same selection, the pattern appearing later in the spec JSON will overwrite a previously generated selection. To make sure this is not undetected when generating, set the value of the ```expansion``` field to ```default``` for an expansion appearing earlier and ```override``` for the one appearing later.
A **selection** is a single **test instance** (scenario) with explicit values that defines a single test. The scenario is then evaluated by the ```TestCase``` in JS. For the rest of the arranging part, examine ```/common/security-features/tools/generate.py``` to see how the values for the templates are produced.
Taking the spec JSON, the generator follows this algorithm:
* Expand all ```excluded_tests``` to create a blacklist of selections
* For each specification requirement: Expand the ```test_expansion``` pattern into selections and check each against the blacklist, if not marked as suppresed, generate the test resources for the selection
### Source Contexts
In **`source_context_list_schema`**, we can specify In **`source_context_list_schema`**, we can specify
@ -41,7 +220,7 @@ The keys of `source_context_list_schema` can be used as the values of
`source_context_list` fields, to indicate which source context configuration `source_context_list` fields, to indicate which source context configuration
to be used. to be used.
## PolicyDelivery placeholders ### PolicyDelivery placeholders
Each test contains Each test contains
@ -67,27 +246,51 @@ The following placeholder strings in `source_context_list_schema` can be used:
the target policy delivery. the target policy delivery.
For example, when the target policy delivery is For example, when the target policy delivery is
{deliveryType: "http-rp", key: "referrerPolicy", value: "no-referrer"}, `{deliveryType: "http-rp", key: "referrerPolicy", value: "no-referrer"}`,
```json
"sourceContextList": [ "sourceContextList": [
{"sourceContextType": "top", "policyDeliveries": ["anotherPolicy"]}, {
{"sourceContextType": "classic-worker", "policyDeliveries": ["policy"]} "sourceContextType": "top",
"policyDeliveries": [
"anotherPolicy"
] ]
},
{
"sourceContextType": "classic-worker",
"policyDeliveries": [
"policy"
]
}
]
```
is replaced with is replaced with
```json
"sourceContextList": [ "sourceContextList": [
{"sourceContextType": "top", "policyDeliveries": [ {
{"deliveryType": "meta", "sourceContextType": "top",
"policyDeliveries": [
{
"deliveryType": "meta",
"key": "referrerPolicy", "key": "referrerPolicy",
"value": "unsafe-url"}] "value": "unsafe-url"
},
{"sourceContextType": "classic-worker", "policyDeliveries": [
{"deliveryType": "http-rp",
"key": "referrerPolicy",
"value": "no-referrer"}]
} }
] ]
},
{
"sourceContextType": "classic-worker",
"policyDeliveries": [
{
"deliveryType": "http-rp",
"key": "referrerPolicy",
"value": "no-referrer"
}
]
}
]
```
which indicates which indicates
@ -95,7 +298,7 @@ which indicates
- The classic worker is created with - The classic worker is created with
`Referrer-Policy: no-referrer` HTTP response headers. `Referrer-Policy: no-referrer` HTTP response headers.
## `source_context_schema` and `subresource_schema` ### `source_context_schema` and `subresource_schema`
These represent supported delivery types and subresources These represent supported delivery types and subresources
for each source context or subresource type. These are used for each source context or subresource type. These are used

View file

@ -165,22 +165,14 @@ def generate_selection(spec_json, config, selection, spec,
['supported_delivery_type'][selection['subresource']]) ['supported_delivery_type'][selection['subresource']])
# We process the top source context below, and do not include it in # We process the top source context below, and do not include it in
# `test_parameters` in JavaScript. # `scenario` field in JavaScript.
top_source_context = selection['source_context_list'].pop(0) top_source_context = selection['source_context_list'].pop(0)
assert (top_source_context.source_context_type == 'top') assert (top_source_context.source_context_type == 'top')
test_parameters = dump_test_parameters(selection)
# Adjust the template for the test invoking JS. Indent it to look nice. # Adjust the template for the test invoking JS. Indent it to look nice.
indent = "\n" + " " * 8 indent = "\n" + " " * 8
test_parameters = test_parameters.replace("\n", indent) selection['scenario'] = dump_test_parameters(selection).replace(
"\n", indent)
selection['test_js'] = '''
%s(
%s,
document.querySelector("meta[name=assert]").content,
new SanityChecker()
).start();
''' % (config.test_case_name, test_parameters)
selection['spec_name'] = spec['name'] selection['spec_name'] = spec['name']
selection[ selection[

View file

@ -18,7 +18,13 @@
<script src="%(helper_js)s"></script> <script src="%(helper_js)s"></script>
</head> </head>
<body> <body>
<script>%(test_js)s</script> <script>
TestCase(
%(scenario)s,
document.querySelector("meta[name=assert]").content,
new SanityChecker()
).start();
</script>
<div id="log"></div> <div id="log"></div>
</body> </body>
</html> </html>

View file

@ -14,7 +14,13 @@
<script src="%(helper_js)s"></script> <script src="%(helper_js)s"></script>
</head> </head>
<body> <body>
<script>%(test_js)s</script> <script>
TestCase(
%(scenario)s,
document.querySelector("meta[name=assert]").content,
new SanityChecker()
).start();
</script>
<div id="log"></div> <div id="log"></div>
</body> </body>
</html> </html>

View file

@ -1,33 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS basic box model: parsing min-height with invalid values</title>
<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-box-3/#propdef-min-height">
<meta name="assert" content="min-height supports only the grammar '[ [<length> | <percentage>] && [border-box | content-box]? ] | available | min-content | max-content | fit-content'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
test_invalid_value("min-height", "complex");
test_invalid_value("min-height", "none");
test_invalid_value("min-height", "none available");
test_invalid_value("min-height", "max-content 10px");
test_invalid_value("min-height", "20% available");
test_invalid_value("min-height", "-10px");
test_invalid_value("min-height", "-20%");
test_invalid_value("min-height", "60");
test_invalid_value("min-height", "10px 20%");
test_invalid_value("min-height", "content-box border-box");
test_invalid_value("min-height", "10px border-box 20%");
test_invalid_value("min-height", "content-box 20% border-box");
// The following is not yet rejected by browsers:
test_invalid_value("min-height", "auto");
</script>
</body>
</html>

View file

@ -1,29 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS basic box model: parsing min-height with valid values</title>
<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-box-3/#propdef-min-height">
<meta name="assert" content="min-height supports the full grammar '[ [<length> | <percentage>] && [border-box | content-box]? ] | available | min-content | max-content | fit-content'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
test_valid_value("min-height", "10px");
test_valid_value("min-height", "20%");
test_valid_value("min-height", "calc(2em + 3ex)");
test_valid_value("min-height", "min-content");
test_valid_value("min-height", "max-content");
test_valid_value("min-height", "fit-content");
// The following are not yet supported by browsers:
// test_valid_value("min-height", "available");
// test_valid_value("min-height", "10px border-box");
// test_valid_value("min-height", "content-box 20%", "20% content-box");
</script>
</body>
</html>

View file

@ -1,33 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS basic box model: parsing min-width with invalid values</title>
<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-box-3/#propdef-min-width">
<meta name="assert" content="min-width supports only the grammar '[ [<length> | <percentage>] && [border-box | content-box]? ] | available | min-content | max-content | fit-content'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
test_invalid_value("min-width", "complex");
test_invalid_value("min-width", "none");
test_invalid_value("min-width", "none available");
test_invalid_value("min-width", "max-content 10px");
test_invalid_value("min-width", "20% available");
test_invalid_value("min-width", "-10px");
test_invalid_value("min-width", "-20%");
test_invalid_value("min-width", "60");
test_invalid_value("min-width", "10px 20%");
test_invalid_value("min-width", "content-box border-box");
test_invalid_value("min-width", "10px border-box 20%");
test_invalid_value("min-width", "content-box 20% border-box");
// The following is not yet rejected by browsers:
test_invalid_value("min-width", "auto");
</script>
</body>
</html>

View file

@ -1,29 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS basic box model: parsing min-width with valid values</title>
<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-box-3/#propdef-min-width">
<meta name="assert" content="min-width supports the full grammar '[ [<length> | <percentage>] && [border-box | content-box]? ] | available | min-content | max-content | fit-content'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
test_valid_value("min-width", "10px");
test_valid_value("min-width", "20%");
test_valid_value("min-width", "calc(2em + 3ex)");
test_valid_value("min-width", "min-content");
test_valid_value("min-width", "max-content");
test_valid_value("min-width", "fit-content");
// The following are not yet supported by browsers:
// test_valid_value("min-width", "available");
// test_valid_value("min-width", "10px border-box");
// test_valid_value("min-width", "content-box 20%", "20% content-box");
</script>
</body>
</html>

View file

@ -0,0 +1,3 @@
<!doctype html>
<p>You should see a 300x300px green square below and no crash.</p>
<div style="width:300px;height:300px;background:green"></div>

View file

@ -0,0 +1,13 @@
<!doctype html>
<title>CSS Images Test: repeating-radial-gradient with huge size crashes Chrome</title>
<link rel="help" href="https://crbug.com/1009307">
<link rel="match" href="infinite-radial-gradient-crash-ref.html">
<style>
#crash {
background-image: repeating-radial-gradient(closest-corner circle at 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999%, green, green);
width: 300px;
height: 300px;
}
</style>
<p>You should see a 300x300px green square below and no crash.</p>
<div id="crash"></div>

View file

@ -12,10 +12,22 @@
<body> <body>
<script> <script>
test_invalid_value("min-height", "none"); test_invalid_value("min-height", "none");
test_invalid_value("min-height", "min-content max-content"); test_invalid_value("min-height", "complex");
test_invalid_value("min-height", "-10%"); test_invalid_value("min-height", "-10%");
test_invalid_value("min-height", "-0.5em"); test_invalid_value("min-height", "-0.5em");
test_invalid_value("min-height", "60");
test_invalid_value("min-height", "10px 20%");
test_invalid_value("min-height", "max-content 10px");
test_invalid_value("min-height", "min-content max-content");
// The following were previously supported by a min-height definition in
// https://drafts.csswg.org/css-box-3/
test_invalid_value("min-height", "available");
test_invalid_value("min-height", "10px border-box");
test_invalid_value("min-height", "content-box 20%");
test_invalid_value("min-height", "fit-content");
</script> </script>
</body> </body>
</html> </html>

View file

@ -12,10 +12,22 @@
<body> <body>
<script> <script>
test_invalid_value("min-width", "none"); test_invalid_value("min-width", "none");
test_invalid_value("min-width", "min-content max-content"); test_invalid_value("min-width", "complex");
test_invalid_value("min-width", "-10%"); test_invalid_value("min-width", "-10%");
test_invalid_value("min-width", "-0.5em"); test_invalid_value("min-width", "-0.5em");
test_invalid_value("min-width", "60");
test_invalid_value("min-width", "10px 20%");
test_invalid_value("min-width", "max-content 10px");
test_invalid_value("min-width", "min-content max-content");
// The following were previously supported by a min-width definition in
// https://drafts.csswg.org/css-box-3/
test_invalid_value("min-width", "available");
test_invalid_value("min-width", "10px border-box");
test_invalid_value("min-width", "content-box 20%");
test_invalid_value("min-width", "fit-content");
</script> </script>
</body> </body>
</html> </html>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#propdef-scale">
<link rel="help" href="http://www.w3.org/TR/cssom-view/#extensions-to-the-document-interface">
<link rel="help" href="https://crbug.com/1015801">
<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#normal {
width: 100px;
height: 10px;
position: absolute;
top: 0px;
}
#scaled {
width: 1px;
height: 1px;
transform: scaleX(100) scaleY(100);
transform-origin: 0px 0px;
position: absolute;
top: 10px;
z-index: 1; /* Hit test #scaled before #normal */
}
</style>
<div id=normal></div>
<div id=scaled></div>
<script>
test(() => {
const result = document.elementFromPoint(50, 9);
assert_equals(result, document.getElementById('normal'));
}, 'Hit test within unscaled box');
test(() => {
const result = document.elementFromPoint(50, 9.1);
assert_equals(result, document.getElementById('scaled'));
}, 'Hit test intersecting scaled box');
</script>

View file

@ -1,7 +1,10 @@
# Writing Tests # Writing Tests
If you haven't already, it's strongly recommended to read So you'd like to write new tests for WPT? Great! For starters, we recommend
the [introduction](../index) first, as it introduces the various test types. reading [the introduction](../index) to learn how the tests are organized and
interpreted. You might already have an idea about what needs testing, but it's
okay if you don't know where to begin. In either case, [the guide on making a
testing plan](making-a-testing-plan) will help you decide what to write.
There's also a load of [general guidelines](general-guidelines) that apply to all tests. There's also a load of [general guidelines](general-guidelines) that apply to all tests.
@ -17,6 +20,7 @@ There's also a load of [general guidelines](general-guidelines) that apply to al
file-names file-names
h2tests h2tests
lint-tool lint-tool
making-a-testing-plan
manual manual
reftest-tutorial reftest-tutorial
reftests reftests

View file

@ -0,0 +1,535 @@
# Making a Testing Plan
When contributing to a project as large and open-ended as WPT, it's easy to get
lost in the details. It can be helpful to start by making a rough list of tests
you intend to write. That plan will let you anticipate how much work will be
involved, and it will help you stay focused once you begin.
Many people come to WPT with a general testing goal in mind:
- specification authors often want to test for new spec text
- browser maintainers often want to test new features or fixes to existing
features
- web developers often want to test discrepancies between browsers on their web
applications
(If you don't have any particular goal, we can help you get started. Check out
[the issues labeled with `type:missing-coverage` on
GitHub.com](https://github.com/web-platform-tests/wpt/labels/type%3Amissing-coverage).
Leave a comment if you'd like to get started with one, and don't hesitate to
ask clarifying questions!)
This guide will help you write a testing plan by:
1. showing you how to use the specifications to learn what kinds of tests will
be most helpful
2. developing your sense for what *doesn't* need to be tested
3. demonstrating methods for figuring out which tests (if any) have already
been written for WPT
The level of detail in useful testing plans can vary widely. From [a list of
specific
cases](https://github.com/web-platform-tests/wpt/issues/6980#issue-252255894),
to [an outline of important coverage
areas](https://github.com/web-platform-tests/wpt/issues/18549#issuecomment-522631537),
to [an annotated version of the specification under
test](https://rwaldron.github.io/webrtc-pc/), the appropriate fidelity depends
on your needs, so you can be as precise as you feel is helpful.
## Understanding the "testing surface"
Web platform specifications are instructions about how a feature should work.
They're critical for implementers to "build the right thing," but they are also
important for anyone writing tests. We can use the same instructions to infer
what kinds of tests would be likely to detect mistakes. Here are a few common
patterns in specification text and the kind of tests they suggest.
### Input sources
Algorithms may accept input from many sources. Modifying the input is the most
direct way we can influence the browser's behavior and verify that it matches
the specifications. That's why it's helpful to be able to recognize different
sources of input.
```eval_rst
================ ==============================================================
Type of feature Potential input sources
================ ==============================================================
JavaScript parameters, `context object <https://dom.spec.whatwg.org/#context-object>`_
HTML element content, attributes, attribute values
CSS selector strings, property values, markup
================ ==============================================================
```
Determine which input sources are relevant for your chosen feature, and build a
list of values which seem worthwhile to test (keep reading for advice on
identifying worthwhile values). For features that accept multiple sources of
input, remember that the interaction between values can often produce
interesting results. Every value you identify should go into your testing plan.
*Example:* This is the first step of the `Notification` constructor from [the
Notifications standard](https://notifications.spec.whatwg.org/#constructors):
> The Notification(title, options) constructor, when invoked, must run these steps:
>
> 1. If the [current global
> object](https://html.spec.whatwg.org/multipage/webappapis.html#current-global-object)
> is a
> [ServiceWorkerGlobalScope](https://w3c.github.io/ServiceWorker/#serviceworkerglobalscope)
> object, then [throw](https://heycam.github.io/webidl/#dfn-throw) a
> `TypeError` exception.
> 2. Let *notification* be the result of [creating a
> notification](https://notifications.spec.whatwg.org/#create-a-notification)
> given *title* and *options*. Rethrow any exceptions.
>
> [...]
A thorough test suite for this constructor will include tests for the behavior
of many different values of the *title* parameter and the *options* parameter.
Choosing those values can be a challenge unto itself--see [Avoid Excessive
Breadth](#avoid-excessive-breadth) for advice.
### Browser state
The state of the browser may also influence algorithm behavior. Examples
include the current document, the dimensions of the viewport, and the entries
in the browsing history. Just like with direct input, a thorough set of tests
will likely need to control these values. Browser state is often more expensive
to manipulate (whether in terms of code, execution time, or system resources),
and you may want to design your tests to mitigate these costs (e.g. by writing
many subtests from the same state).
You may not be able to control all relevant aspects of the browser's state.
[The `type:untestable`
label](https://github.com/web-platform-tests/wpt/issues?q=is%3Aopen+is%3Aissue+label%3Atype%3Auntestable)
includes issues for web platform features which cannot be controlled in a
cross-browser way. You should include tests like these in your plan both to
communicate your intention and to remind you when/if testing solutions become
available.
*Example:* In [the `Notification` constructor referenced
above](https://notifications.spec.whatwg.org/#constructors), the type of "the
current global object" is also a form of input. The test suite should include
tests which execute with different types of global objects.
### Branches
When an algorithm branches based on some condition, that's an indication of an
interesting behavior that might be missed. Your testing plan should have at
least one test that verifies the behavior when the branch is taken and at least
one more test that verifies the behavior when the branch is *not* taken.
*Example:* The following algorithm from [the HTML
standard](https://html.spec.whatwg.org/) describes how the
`localStorage.getItem` method works:
> The `getItem`(*key*) method must return the current value associated with the
> given *key*. If the given *key* does not exist in the list associated with
> the object then this method must return null.
This algorithm exhibits different behavior depending on whether or not an item
exists at the provided key. To test this thoroughly, we would write two tests:
one test would verify that `null` is returned when there is no item at the
provided key, and the other test would verify that an item we previously stored
was correctly retrieved when we called the method with its name.
### Sequence
Even without branching, the interplay between sequential algorithm steps can
suggest interesting test cases. If two steps have observable side-effects, then
it can be useful to verify they happen in the correct order.
Most of the time, step sequence is implicit in the nature of the
algorithm--each step operates on the result of the step that precedes it, so
verifying the end result implicitly verifies the sequence of the steps. But
sometimes, the order of two steps isn't particularly relevant to the result of
the overall algorithm. This makes it easier for implementations to diverge.
There are many common patterns where step sequence is observable but not
necessarily inherent to the correctness of the algorithm:
- input validation (when an algorithm verifies that two or more input values
satisfy some criteria)
- event dispatch (when an algorithm
[fires](https://dom.spec.whatwg.org/#concept-event-fire) two or more events)
- object property access (when an algorithm retrieves two or more property
values from an object provided as input)
*Example:* The following text is an abbreviated excerpt of the algorithm that
runs during drag operations (from [the HTML
specification](https://html.spec.whatwg.org/multipage/dnd.html#dnd)):
> [...]
> 4. Otherwise, if the user ended the drag-and-drop operation (e.g. by
> releasing the mouse button in a mouse-driven drag-and-drop interface), or
> if the `drag` event was canceled, then this will be the last iteration.
> Run the following steps, then stop the drag-and-drop operation:
> 1. If the [current drag
> operation](https://html.spec.whatwg.org/multipage/dnd.html#current-drag-operation)
> is "`none`" (no drag operation) [...] Otherwise, the drag operation
> might be a success; run these substeps:
> 1. Let *dropped* be true.
> 2. If the [current target
> element](https://html.spec.whatwg.org/multipage/dnd.html#current-target-element)
> is a DOM element, [fire a DND
> event](https://html.spec.whatwg.org/multipage/dnd.html#fire-a-dnd-event)
> named `drop` at it; otherwise, use platform-specific conventions for
> indicating a drop.
> 3. [...]
> 2. [Fire a DND
> event](https://html.spec.whatwg.org/multipage/dnd.html#fire-a-dnd-event)
> named `dragend` at the [source
> node](https://html.spec.whatwg.org/multipage/dnd.html#source-node).
> 3. [...]
A thorough test suite will verify that the `drop` event is fired as specified,
and it will also verify that the `dragend` event is fired as specified. An even
better test suite will also verify that the `drop` event is fired *before* the
`dragend` event.
In September of 2019, [Chromium accidentally changed the ordering of the `drop`
and `dragend`
events](https://bugs.chromium.org/p/chromium/issues/detail?id=1005747), and as
a result, real web applications stopped functioning. If there had been a test
for the sequence of these events, then this confusion would have been avoided.
When making your testing plan, be sure to look carefully for event dispatch and
the other patterns listed above. They won't always be as clear as the "drag"
example!
### Optional behavior
Specifications occasionally allow browsers discretion in how they implement
certain features. These are described using [RFC
2119](https://tools.ietf.org/html/rfc2119) terms like "MAY" and "OPTIONAL".
Although browsers should not be penalized for deciding not to implement such
behavior, WPT offers tests that verify the correctness of the browsers which
do. Be sure to [label the test as optional according to WPT's
conventions](file-names) so that people reviewing test results know how to
interpret failures.
*Example:* The algorithm underpinning
[`document.getElementsByTagName`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByTagName)
includes the following paragraph:
> When invoked with the same argument, and as long as *root*'s [node
> document](https://dom.spec.whatwg.org/#concept-node-document)'s
> [type](https://dom.spec.whatwg.org/#concept-document-type) has not changed,
> the same [HTMLCollection](https://dom.spec.whatwg.org/#htmlcollection) object
> may be returned as returned by an earlier call.
That statement uses the word "may," so even though it modifies the behavior of
the preceding algorithm, it is strictly optional. The test we write for this
should be designated accordingly.
It's important to read these sections carefully because the distinction between
"mandatory" behavior and "optional" behavior can be nuanced. In this case, the
optional behavior is never allowed if the document's type has changed. That
makes for a mandatory test, one that verifies browsers don't return the same
result when the document's type changes.
## Exercising Restraint
When writing conformance tests, choosing what *not* to test is sometimes just
as hard as finding what needs testing.
### Don't dive too deep
Algorithms are composed of many other algorithms which themselves are defined
in terms of still more algorithms. It can be intimidating to consider
exhaustively testing one of those "nested" algorithms, especially when they are
shared by many different APIs.
In general, you should plan to write "surface tests" for the nested algorithms.
That means only verifying that they exhibit the basic behavior you are
expecting.
It's definitely important to test exhaustively, but it's just as important to
do so in a structured way. Reach out to the test suite's maintainers to learn
if and how they have already tested those algorithms. In many cases, it's
acceptable to test them in just one place (and maybe through a different API
entirely), and rely only on surface-level testing everywhere else. While it's
always possible for more tests to uncover new bugs, the chances may be slim.
The time we spend writing tests is highly valuable, so we have to be efficient!
*Example:* The following algorithm from [the DOM
standard](https://dom.spec.whatwg.org/) powers
[`document.querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector):
> To **scope-match a selectors string** *selectors* against a *node*, run these
> steps:
>
> 1. Let *s* be the result of [parse a
> selector](https://drafts.csswg.org/selectors-4/#parse-a-selector)
> *selectors*.
> 2. If *s* is failure, then
> [throw](https://heycam.github.io/webidl/#dfn-throw) a
> "[`SyntaxError`](https://heycam.github.io/webidl/#syntaxerror)"
> [DOMException](https://heycam.github.io/webidl/#idl-DOMException).
> 3. Return the result of [match a selector against a
> tree](https://drafts.csswg.org/selectors-4/#match-a-selector-against-a-tree)
> with *s* and *node*'s
> [root](https://dom.spec.whatwg.org/#concept-tree-root) using [scoping
> root](https://drafts.csswg.org/selectors-4/#scoping-root) *node*.
As described earlier in this guide, we'd certainly want to test the branch
regarding the parsing failure. However, there are many ways a string might fail
to parse--should we verify them all in the tests for `document.querySelector`?
What about `document.querySelectorAll`? Should we test them all there, too?
The answers depend on the current state of the test suite: whether or not tests
for selector parsing exist and where they are located. That's why it's best to
confer with the people who are maintaining the tests.
### Avoid excessive breadth
When the set of input values is finite, it can be tempting to test them all
exhaustively. When the set is very large, test authors can reduce repetition by
defining tests programmatically in loops.
Using advanced control flow techniques to dynamically generate tests can
actually *reduce* test quality. It may obscure the intent of the tests since
readers have to mentally "unwind" the iteration to determine what is actually
being verified. The practice is more susceptible to bugs. These bugs may not be
obvious--they may not cause failures, and they may exercise fewer cases than
intended. Finally, tests authored using this approach often take a relatively
long time to complete, and that puts a burden on people who collect test
results in large numbers.
The severity of these drawbacks varies with the complexity of the generation
logic. For example, it would be pronounced in a test which conditionally made
different assertions within many nested loops. Conversely, the severity would
be low in a test which only iterated over a list of values in order to make the
same assertions about each. Recognizing when the benefits outweigh the risks
requires discretion, so once you understand them, you should use your best
judgement.
*Example:* We can see this consideration in the very first step of the
`Response` constructor from [the Fetch
standard](https://fetch.spec.whatwg.org/)
> The `Response`(*body*, *init*) constructor, when invoked, must run these
> steps:
>
> 1. If *init*["`status`"] is not in the range `200` to `599`, inclusive, then
> [throw](https://heycam.github.io/webidl/#dfn-throw) a `RangeError`.
>
> [...]
This function accepts exactly 400 values for the "status." With [WPT's
testharness.js](./testharness), it's easy to dynamically create one test for
each value. Unless we have reason to believe that a browser may exhibit
drastically different behavior for any of those values (e.g. correctly
accepting `546` but incorrectly rejecting `547`), then the complexity of
testing those cases probably isn't warranted.
Instead, focus on writing declarative tests for specific values which are novel
in the context of the algorithm. For ranges like in this example, testing the
boundaries is a good idea. `200` and `599` should not produce an error while
`199` and `600` should produce an error. Feel free to use what you know about
the feature to choose additional values. In this case, HTTP response status
codes are classified by the "hundred" order of magnitude, so we might also want
to test a "3xx" value and a "4xx" value.
## Assessing coverage
It's very likely that WPT already has some tests for the feature (or at least
the specification) that you're interesting in testing. In that case, you'll
have to learn what's already been done before starting to write new tests.
Understanding the design of existing tests will let you avoid duplicating
effort, and it will also help you integrate your work more logically.
Even if the feature you're testing does *not* have any tests, you should still
keep these guidelines in mind. Sooner or later, someone else will want to
extend your work, so you ought to give them a good starting point!
### File names
The names of existing files and folders in the repository can help you find
tests that are relevant to your work. [This page on the design of
WPT](../test-suite-design) goes into detail about how files are generally laid
out in the repository.
Generally speaking, every conformance tests is stored in a subdirectory
dedicated to the specification it verifies. The structure of these
subdirectories vary. Some organize tests in directories related to algorithms
or behaviors. Others have a more "flat" layout, where all tests are listed
together.
Whatever the case, test authors try to choose names that communicate the
behavior under test, so you can use them to make an educated guess about where
your tests should go.
*Example:* Imagine you wanted to write a test to verify that headers were made
immutable by the `Request.error` method defined in [the Fetch
standard](https://fetch.spec.whatwg.org). Here's the algorithm:
> The static error() method, when invoked, must run these steps:
>
> 1. Let *r* be a new [Response](https://fetch.spec.whatwg.org/#response)
> object, whose
> [response](https://fetch.spec.whatwg.org/#concept-response-response) is a
> new [network error](https://fetch.spec.whatwg.org/#concept-network-error).
> 2. Set *r*'s [headers](https://fetch.spec.whatwg.org/#response-headers) to a
> new [Headers](https://fetch.spec.whatwg.org/#headers) object whose
> [guard](https://fetch.spec.whatwg.org/#concept-headers-guard) is
> "`immutable`".
> 3. Return *r*.
In order to figure out where to write the test (and whether it's needed at
all), you can review the contents of the `fetch/` directory in WPT. Here's how
that looks on a UNIX-like command line:
$ ls fetch
api/ data-urls/ range/
content-encoding/ http-cache/ README.md
content-length/ images/ redirect-navigate/
content-type/ metadata/ security/
corb/ META.yml stale-while-revalidate/
cors-rfc1918/ nosniff/
cross-origin-resource-policy/ origin/
This test is for a behavior directly exposed through the API, so we should look
in the `api/` directory:
$ ls fetch/api
abort/ cors/ headers/ policies/ request/ response/
basic/ credentials/ idlharness.any.js redirect/ resources/
And since this is a static method on the `Response` constructor, we would
expect the test to belong in the `response/` directory:
$ ls fetch/api/response
multi-globals/ response-static-error.html
response-cancel-stream.html response-static-redirect.html
response-clone.html response-stream-disturbed-1.html
response-consume-empty.html response-stream-disturbed-2.html
response-consume.html response-stream-disturbed-3.html
response-consume-stream.html response-stream-disturbed-4.html
response-error-from-stream.html response-stream-disturbed-5.html
response-error.html response-stream-disturbed-6.html
response-from-stream.any.js response-stream-with-broken-then.any.js
response-init-001.html response-trailer.html
response-init-002.html
There seems to be a test file for the `error` method:
`response-static-error.html`. We can open that to decide if the behavior is
already covered. If not, then we know where to [write the
test](https://github.com/web-platform-tests/wpt/pull/19601)!
### Failures on wpt.fyi
There are many behaviors that are difficult to describe in a succinct file
name. That's commonly the case with low-level rendering details of CSS
specifications. Test authors may resort to generic number-based naming schemes
for their files, e.g. `feature-001.html`, `feature-002.html`, etc. This makes
it difficult to determine if a test case exists judging only by the names of
files.
If the behavior you want to test is demonstrated by some browsers but not by
others, you may be able to use the *results* of the tests to locate the
relevant test.
[wpt.fyi](https://wpt.fyi) is a website which publishes results of WPT in
various browsers. Because most browsers pass most tests, the pass/fail
characteristics of the behavior you're testing can help you filter through a
large number of highly similar tests.
*Example:* Imagine you've found a bug in the way Safari renders the top CSS
border of HTML tables. By searching through directory names and file names,
you've determined the probable location for the test: the `css/CSS2/borders/`
directory. However, there are *three hundred* files that begin with
`border-top-`! None of the names mention the `<table>` element, so any one of
the files may already be testing the case you found.
Luckily, you also know that Firefox and Chrome do not exhibit this bug. You
could find such tests by visual inspection of the [wpt.fyi](https://wpt.fyi)
results overview, but [the website's "search" feature includes operators that
let you query for this information
directly](https://github.com/web-platform-tests/wpt.fyi/blob/master/api/query/README.md).
To find the tests which begin with `border-top-`, pass in Chrome, pass in
Firefox, and fail in Safari, you could write [`border-top- chrome:pass
firefox:pass
safari:fail](https://wpt.fyi/results/?label=master&label=experimental&aligned&q=border-top-%20safari%3Afail%20firefox%3Apass%20chrome%3Apass).
The results show only three such tests exist:
- `border-top-applies-to-005.xht`
- `border-top-color-applies-to-005.xht`
- `border-top-width-applies-to-005.xht`
These may not describe the behavior you're interested in testing; the only way
to know for sure is to review their contents. However, this is a much more
manageable set to work with!
### Querying file contents
Some web platform features are enabled with a predictable pattern. For example,
HTML attributes follow a fairly consistent format. If you're interested in
testing a feature like this, you may be able to learn where your tests belong
by querying the contents of the files in WPT.
You may be able to perform such a search on the web. WPT is hosted on
GitHub.com, and [GitHub offers some basic functionality for querying
code](https://help.github.com/en/articles/about-searching-on-github). If your
search criteria are short and distinctive (e.g. all files containing
"querySelectorAll"), then this interface may be sufficient. However, more
complicated criteria may require [regular
expressions](https://www.regular-expressions.info/). For that, you can
[download the WPT
repository](https://web-platform-tests.org/writing-tests/github-intro.html) and
use [git](https://git-scm.com) to perform more powerful searches.
The following table lists some common search criteria and examples of how they
can be expressed using regular expressions:
```eval_rst
================================= ================== ==========================
Criteria Example match Example regular expression
================================= ================== ==========================
JavaScript identifier references ``obj.foo()`` ``\bfoo\b``
JavaScript string literals ``x = "foo";`` ``(["'])foo\1``
HTML tag names ``<foo attr>`` ``<foo(\s|>|$)``
HTML attributes ``<div foo=3>`` ``<[a-zA-Z][^>]*\sfoo(\s|>|=|$)``
CSS property name ``style="foo: 4"`` ``([{;=\"']|\s|^)foo\s+:``
================================= ================== ==========================
```
Bear in mind that searches like this are not necessarily exhaustive. Depending
on the feature, it may be difficult (or even impossible) to write a query that
correctly identifies all relevant tests. This strategy can give a helpful
guide, but the results may not be conclusive.
*Example:* Imagine you're interested in testing how the `src` attribute of the
`iframe` element works with `javascript:` URLs. Judging only from the names of
directories, you've found a lot of potential locations for such a test. You
also know many tests use `javascript:` URLs without describing that in their
name. How can you find where to contribute new tests?
You can design a regular expression that matches many cases where a
`javascript:` URL is assigned to the `src` property in HTML. You can use the
`git grep` command to query the contents of the `html/` directory:
$ git grep -lE "src\s*=\s*[\"']?javascript:" html
html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html
html/browsers/browsing-the-web/navigating-across-documents/javascript-url-return-value-handling.html
html/dom/documents/dom-tree-accessors/Document.currentScript.html
html/dom/self-origin.sub.html
html/editing/dnd/target-origin/114-manual.html
html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html
html/semantics/scripting-1/the-script-element/execution-timing/040.html
html/semantics/scripting-1/the-script-element/execution-timing/080.html
html/semantics/scripting-1/the-script-element/execution-timing/108.html
html/semantics/scripting-1/the-script-element/execution-timing/109.html
html/webappapis/dynamic-markup-insertion/opening-the-input-stream/document-open-cancels-javascript-url-navigation.html
You will still have to review the contents to know which are relevant for your
purposes (if any), but compared to the 5,000 files in the `html/` directory,
this list is far more approachable!
## Writing the Tests
With a complete testing plan in hand, you now have a good idea of the scope of
your work. It's finally time to write the tests! There's a lot to say about how
this is done technically. To learn more, check out [the WPT "reftest"
tutorial](./reftest-tutorial) and [the testharness.js
tutorial](./testharness-tutorial).

View file

@ -0,0 +1,55 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>This test validates element timing information for cross-origin redirect chain images.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/element-timing-helpers.js"></script>
<script src=/common/get-host-info.sub.js></script>
</head>
<body>
<script>
async_test(t => {
if (!window.PerformanceElementTiming) {
assert_unreached("PerformanceElementTiming is not implemented");
}
let destUrl = get_host_info().HTTP_REMOTE_ORIGIN
+ '/resource-timing/resources/multi_redirect.py?';
destUrl += 'page_origin=' + get_host_info().HTTP_ORIGIN;
destUrl += '&cross_origin=' + get_host_info().HTTP_REMOTE_ORIGIN;
destUrl += '&final_resource=' + '/images/blue.png';
destUrl += '&timing_allow=1';
destUrl += '&tao_steps=';
for (let taoSteps=0; taoSteps < 4; taoSteps++) {
const image = document.createElement('img');
image.src = destUrl + taoSteps;
image.setAttribute('elementtiming', taoSteps);
image.setAttribute('id', 'id' + taoSteps)
document.body.appendChild(image);
}
let numObserved = 0;
let observedMap = [false, false, false, false];
const beforeRender = performance.now();
new PerformanceObserver(t.step_func(entries => {
entries.getEntries().forEach(entry => {
const taoSteps = entry.identifier;
assert_false(observedMap[taoSteps], 'Should observe each image once');
observedMap[taoSteps] = true;
if (taoSteps !== '3') {
assert_equals(entry.renderTime, 0,
'renderTime should be 0 when there is ' + taoSteps + ' tao steps');
}
const bound = taoSteps === '3' ? beforeRender : 0;
checkElement(entry, destUrl + taoSteps, taoSteps, 'id' + taoSteps, bound,
document.getElementById(taoSteps));
});
numObserved += entries.getEntries().length;
if (numObserved === 4)
t.done();
})).observe({type: 'element', buffered: true});
}, 'Cross-origin image without TAO should not have its renderTime set, with full TAO it should.');
</script>
</body>
</html>

View file

@ -1,24 +1,25 @@
// Common checks between checkElement() and checkElementWithoutResourceTiming(). // Common checks between checkElement() and checkElementWithoutResourceTiming().
function checkElementInternal(entry, expectedUrl, expectedIdentifier, expectedID, beforeRender, function checkElementInternal(entry, expectedUrl, expectedIdentifier, expectedID, beforeRender,
expectedElement) { expectedElement) {
assert_equals(entry.entryType, 'element'); assert_equals(entry.entryType, 'element', 'entryType does not match');
assert_equals(entry.url, expectedUrl); assert_equals(entry.url, expectedUrl, 'url does not match');
assert_equals(entry.identifier, expectedIdentifier); assert_equals(entry.identifier, expectedIdentifier, 'identifier does not match');
if (beforeRender != 0) { if (beforeRender != 0) {
// In this case, renderTime is not 0. // In this case, renderTime is not 0.
assert_equals(entry.startTime, entry.renderTime); assert_equals(entry.startTime, entry.renderTime, 'startTime should equal renderTime');
} else { } else {
// In this case, renderTime is 0, so compare to loadTime. // In this case, renderTime is 0, so compare to loadTime.
assert_equals(entry.startTime, entry.loadTime); assert_equals(entry.startTime, entry.loadTime, 'startTime should equal loadTime');
} }
assert_equals(entry.duration, 0); assert_equals(entry.duration, 0, 'duration should be 0');
assert_equals(entry.id, expectedID); assert_equals(entry.id, expectedID, 'id does not match');
assert_greater_than_equal(entry.renderTime, beforeRender); assert_greater_than_equal(entry.renderTime, beforeRender, 'renderTime greater than beforeRender');
assert_greater_than_equal(performance.now(), entry.renderTime); assert_greater_than_equal(performance.now(), entry.renderTime, 'renderTime bounded by now()');
if (expectedElement !== null) { if (expectedElement !== null) {
assert_equals(entry.element, expectedElement); assert_equals(entry.element, expectedElement, 'element does not match');
assert_equals(entry.identifier, expectedElement.elementTiming); assert_equals(entry.identifier, expectedElement.elementTiming,
assert_equals(entry.id, expectedElement.id); 'identifier must be the elementtiming of the element');
assert_equals(entry.id, expectedElement.id, 'id must be the id of the element');
} }
} }

View file

@ -4,6 +4,7 @@
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script> <script>
setup({ single_test: true });
onload = function() { onload = function() {
assert_equals(document.body.textContent, "PASS"); assert_equals(document.body.textContent, "PASS");
done(); done();

View file

@ -1 +1 @@
Content-Length: 373 Content-Length: 403

View file

@ -16,6 +16,7 @@
<div id=log></div> <div id=log></div>
<script> <script>
setup({ single_test: true });
window.has_executed_script = false; window.has_executed_script = false;
</script> </script>

View file

@ -8,6 +8,7 @@
<div id=log></div> <div id=log></div>
<script> <script>
setup({ single_test: true });
window.has_executed_script = false; window.has_executed_script = false;
</script> </script>

View file

@ -14,7 +14,7 @@
<script src="/common/utils.js"></script> <script src="/common/utils.js"></script>
<div id=log></div> <div id=log></div>
<script> <script>
setup({allow_uncaught_exception : true}); setup({allow_uncaught_exception : true, single_test : true});
function test(mime_type, is_blocking_expected) { function test(mime_type, is_blocking_expected) {
var action = is_blocking_expected ? "blocks" : "does not block"; var action = is_blocking_expected ? "blocks" : "does not block";

View file

@ -9,6 +9,7 @@
- fetch/nosniff/stylesheet.html - fetch/nosniff/stylesheet.html
--> -->
<meta charset="utf-8"> <meta charset="utf-8">
<title>CSS is not applied (because of nosniff + non-text/css headers)</title>
<script src=/resources/testharness.js></script> <script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script> <script src=/resources/testharnessreport.js></script>
@ -31,11 +32,11 @@ h1 { color: green; }
</body> </body>
<script> <script>
// Verify that CSS is not applied (because of nosniff + non-text/css headers). test(() => {
let style = getComputedStyle(document.getElementById('header')); let style = getComputedStyle(document.getElementById('header'));
const external_color = 'rgb(255, 0, 0)'; // red const external_color = 'rgb(255, 0, 0)'; // red
const default_color = 'rgb(0, 128, 0)'; // green const default_color = 'rgb(0, 128, 0)'; // green
assert_equals(style.getPropertyValue('color'), default_color); assert_equals(style.getPropertyValue('color'), default_color);
assert_not_equals(style.getPropertyValue('color'), external_color); assert_not_equals(style.getPropertyValue('color'), external_color);
done(); });
</script> </script>

View file

@ -3,6 +3,7 @@
as text/html (because even without CORB mislabeled CSS will be rejected). as text/html (because even without CORB mislabeled CSS will be rejected).
--> -->
<meta charset="utf-8"> <meta charset="utf-8">
<title>CSS is not applied (because of strict content-type enforcement for cross-origin stylesheets)</title>
<script src=/resources/testharness.js></script> <script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script> <script src=/resources/testharnessreport.js></script>
@ -25,12 +26,11 @@ h1 { color: green; }
</body> </body>
<script> <script>
// Verify that CSS is not applied (because of strict content-type enforcement test(() => {
// for cross-origin stylesheets).
let style = getComputedStyle(document.getElementById('header')); let style = getComputedStyle(document.getElementById('header'));
const external_color = 'rgb(255, 0, 0)'; // red const external_color = 'rgb(255, 0, 0)'; // red
const default_color = 'rgb(0, 128, 0)'; // green const default_color = 'rgb(0, 128, 0)'; // green
assert_equals(style.getPropertyValue('color'), default_color); assert_equals(style.getPropertyValue('color'), default_color);
assert_not_equals(style.getPropertyValue('color'), external_color); assert_not_equals(style.getPropertyValue('color'), external_color);
done(); });
</script> </script>

View file

@ -4,6 +4,7 @@
2) starts with a JSON parser breaker (like )]}') 2) starts with a JSON parser breaker (like )]}')
--> -->
<meta charset="utf-8"> <meta charset="utf-8">
<title>CORB doesn't block a stylesheet that has a proper Content-Type and begins with a JSON parser breaker</title>
<script src=/resources/testharness.js></script> <script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script> <script src=/resources/testharnessreport.js></script>
@ -26,11 +27,12 @@ h1 { color: green; }
</body> </body>
<script> <script>
test(() => {
// Verify that CSS got applied / did not get blocked by CORB. // Verify that CSS got applied / did not get blocked by CORB.
let style = getComputedStyle(document.getElementById('header')); let style = getComputedStyle(document.getElementById('header'));
const external_color = 'rgb(255, 0, 0)'; // red const external_color = 'rgb(255, 0, 0)'; // red
const default_color = 'rgb(0, 128, 0)'; // green const default_color = 'rgb(0, 128, 0)'; // green
assert_equals(style.getPropertyValue('color'), external_color); assert_equals(style.getPropertyValue('color'), external_color);
assert_not_equals(style.getPropertyValue('color'), default_color); assert_not_equals(style.getPropertyValue('color'), default_color);
done(); });
</script> </script>

View file

@ -11,6 +11,7 @@
CORB-blocked response as a stylesheet. CORB-blocked response as a stylesheet.
--> -->
<meta charset="utf-8"> <meta charset="utf-8">
<title>CSS is not applied (because of mismatched Content-Type header)</title>
<script src=/resources/testharness.js></script> <script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script> <script src=/resources/testharnessreport.js></script>
@ -32,9 +33,9 @@ h1 { color: green; }
</body> </body>
<script> <script>
// Verify that CSS is not applied (because of mismatched Content-Type header). test(() => {
var style = getComputedStyle(document.getElementById('header')); var style = getComputedStyle(document.getElementById('header'));
const default_color = 'rgb(0, 128, 0)'; // green const default_color = 'rgb(0, 128, 0)'; // green
assert_equals(style.getPropertyValue('color'), default_color); assert_equals(style.getPropertyValue('color'), default_color);
done(); });
</script> </script>

View file

@ -5,6 +5,7 @@
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script> <script src="/common/get-host-info.sub.js"></script>
<script> <script>
setup({ single_test: true });
var image = new Image(); var image = new Image();
image.onload = function() { image.onload = function() {
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");

View file

@ -2,7 +2,8 @@
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script> <script>
test(function() {
assert_equals(getComputedStyle(document.documentElement).color, "rgb(0, 255, 0)") assert_equals(getComputedStyle(document.documentElement).color, "rgb(0, 255, 0)")
done(); });
</script> </script>
<p>This should be green</p> <p>This should be green</p>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Uncaught exception following subtest</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(function() {});
throw new Error("error outside any setup or test");
</script>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Uncaught exception in single-page test</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
setup({ single_test: true });
throw new Error("error outside any setup or test");
</script>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Unhandled rejection following subtest</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(function() {});
Promise.reject(new Error("error outside any setup or test"));
</script>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Unhandled rejection in single-page test</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
setup({ single_test: true });
Promise.reject(new Error("error outside any setup or test"));
</script>

View file

@ -0,0 +1,6 @@
[uncaught-exception-following-subtest.html]
expected: ERROR
[Uncaught exception following subtest]
expected: PASS

View file

@ -0,0 +1,4 @@
[uncaught-exception-single-test.html]
[Uncaught exception in single-page test]
expected: FAIL

View file

@ -0,0 +1,6 @@
[unhandled-rejection-following-subtest.html]
expected: ERROR
[Unhandled rejection following subtest]
expected: PASS

View file

@ -0,0 +1,4 @@
[unhandled-rejection-single-test.html]
[Unhandled rejection in single-page test]
expected: FAIL

View file

@ -9,9 +9,10 @@
<input id="file_input" name="file_input" type="file"> <input id="file_input" name="file_input" type="file">
</form> </form>
<script> <script>
promise_test(() => {
let form = document.getElementById("form"); let form = document.getElementById("form");
let input = document.getElementById("file_input"); let input = document.getElementById("file_input");
test_driver return test_driver
.send_keys(input, "{{fs_path(file_upload_data.txt)}}") .send_keys(input, "{{fs_path(file_upload_data.txt)}}")
.then(() => .then(() =>
fetch("file_upload.py", fetch("file_upload.py",
@ -20,7 +21,6 @@ test_driver
.then(response => response.text()) .then(response => response.text())
.then(data => { .then(data => {
assert_equals(data, "PASS"); assert_equals(data, "PASS");
done(); });
}) });
.catch(() => assert_unreached("File upload failed"));
</script> </script>

View file

@ -61,7 +61,6 @@ dictionary PublicKeyCredentialCreationOptions {
dictionary PublicKeyCredentialEntity { dictionary PublicKeyCredentialEntity {
required DOMString name; required DOMString name;
USVString icon;
}; };
dictionary PublicKeyCredentialRpEntity : PublicKeyCredentialEntity { dictionary PublicKeyCredentialRpEntity : PublicKeyCredentialEntity {

View file

@ -0,0 +1,4 @@
# Mixed-content Web Platform Tests
The subdirectory `gen/` is generated using the generator at `common/security-features`.
See [common/security-features/README.md](../common/security-features/README.md) for how to generate tests.

View file

@ -31,8 +31,6 @@ class MixedContentConfig(object):
self.sanity_checker_js = '/mixed-content/generic/sanity-checker.js' self.sanity_checker_js = '/mixed-content/generic/sanity-checker.js'
self.spec_json_js = '/mixed-content/spec_json.js' self.spec_json_js = '/mixed-content/spec_json.js'
self.test_case_name = 'TestCase'
script_directory = os.path.dirname(os.path.abspath(__file__)) script_directory = os.path.dirname(os.path.abspath(__file__))
self.spec_directory = os.path.abspath( self.spec_directory = os.path.abspath(
os.path.join(script_directory, '..', '..')) os.path.join(script_directory, '..', '..'))

View file

@ -2,239 +2,5 @@
The Referrer-Policy tests are designed for testing browser implementations and conformance to the [W3 Referrer-Policy Specification](http://w3c.github.io/webappsec/specs/referrer-policy/). The Referrer-Policy tests are designed for testing browser implementations and conformance to the [W3 Referrer-Policy Specification](http://w3c.github.io/webappsec/specs/referrer-policy/).
## Project structure The subdirectory `gen/` is generated using the generator at `common/security-features`.
See [common/security-features/README.md](../common/security-features/README.md) for how to generate tests.
The project contains tools, templates and a seed (```spec.src.json```) for generating tests. The main assertion logic resides in JS files in the root of the ```./generic/``` directory.
This is the overview of the project structure:
```
.
└── generic
├── subresource - documents being served as sub-resources (python scripts)
├── subresource-test - sanity checking tests for resource invocation
├── template - the test files template used for generating the tests
└── tools - for generating and maintaining the test suite
└── (genereated_tests_for_a_specification_1)
└── (genereated_tests_for_a_specification_2)
└── ...
└── (genereated_tests_for_a_specification_N)
```
## The spec JSON
The ```spec.src.json``` defines all the test scenarios for the referrer policy.
Invoking ```./generic/tools/generate.py``` will parse the spec JSON and determine which tests to generate (or skip) while using templates.
The spec can be validated by running ```./generic/tools/spec_validator.py```. This is specially important when you're making changes to ```spec.src.json```. Make sure it's a valid JSON (no comments or trailing commas). The validator should be informative and very specific on any issues.
The ```spec.src.json``` file can be formatted by running ```../common/security-features/tools/format_spec_src_json.py```.
For details about the spec JSON, see **Overview of the spec JSON** below.
## Generating and running the tests
The repository already contains generated tests, so if you're making changes,
see the **Removing all generated tests** section below, on how to remove them before you start generating tests which include your changes.
Start from the command line:
```bash
# Chdir into the tests directory.
cd ~/web-platform-tests/referrer-policy
# Generate the test resources.
./generic/tools/generate.py
# Add all generated tests to the repo.
git add * && git commit -m "Add generated tests"
# Regenerate the manifest.
../wpt manifest
```
Navigate to [http://web-platform.test:8000/tools/runner/index.html](http://web-platform.test:8000/tools/runner/index.html).
Run tests under path: ```/referrer-policy```.
Click start.
## Options for generating tests
The generator script ```./generic/tools/generate.py``` has two targets: ```release``` and ```debug```.
* Using **release** for the target will produce tests using a template for optimizing size and performance. The release template is intended for the official web-platform-tests and possibly other test suites. No sanity checking is done in release mode. Use this option whenever you're checking into web-platform-tests.
* When generating for ```debug```, the produced tests will contain more verbosity and sanity checks. Use this target to identify problems with the test suite when making changes locally. Make sure you don't check in tests generated with the debug target.
Note that **release** is the default target when invoking ```generate.py```.
## Removing all generated tests
```bash
# Chdir into the tests directory.
cd ~/web-platform-tests/referrer-policy
# Remove all generated tests.
./generic/tools/clean.py
# Remove all generated tests to the repo.
git add * && git commit -m "Remove generated tests"
# Regenerate the manifest.
../wpt manifest
```
**Important:**
The ```./generic/tools/clean.py``` utility will only work if there is a valid ```spec.src.json``` and previously generated directories match the specification requirement names. So make sure you run ```clean.py``` before you alter the specification section of the spec JSON.
## Updating the tests
The main test logic lives in ```./generic/referrer-policy-test-case.sub.js``` with helper functions defined in ```./common/security-features/resources/common.js``` so you should probably start there.
For updating the test suite you will most likely do **a subset** of the following:
* Add a new sub-resource python script to ```./generic/subresource/```,
and update the reference to it in ```spec.src.json```.
* Add a sanity check test for a sub-resource to ```./generic/subresource-test/```.
* Implement new or update existing assertions in ```./generic/referrer-policy-test-case.sub.js```.
* Exclude or add some tests by updating ```spec.src.json``` test expansions.
* Update the template files living in ```./generic/template/```.
* Implement a new delivery method via HTTP headers or as part of the test template in ```./generic/tools/generate.py```
* Update the spec schema by editing ```spec.src.json``` while updating the
```./generic/tools/spec_validator.py``` and ```./generic/tools/generate.py```
and making sure both still work after the change (by running them).
* Regenerate the tests and MANIFEST.json
## Updating the spec and regenerating
When updating the ```spec.src.json```, e.g. by adding a test expansion pattern to the ```excluded_tests``` section or when removing an expansion in the ```specification``` section, make sure to remove all previously generated files which would still get picked up by ```MANIFEST.json``` in the web-platform-tests root. As long as you don't change the specification requirements' names or remove them, you can easily regenerate the tests via command line:
```bash
# Chdir into the tests directory.
cd ~/web-platform-tests/referrer-policy
# Regenerate the test resources.
./generic/tools/regenerate
# Add all the tests to the repo.
git add * && git commit -m "Update generated tests"
# Regenerate the manifest.
../wpt manifest
```
## Overview of the spec JSON
**Main sections:**
* **specification**
Top level requirements with description fields and a ```test_expansion``` rule.
This is closely mimicking the [Referrer Policy specification](http://w3c.github.io/webappsec/specs/referrer-policy/) structure.
* **excluded_tests**
List of ```test_expansion``` patterns expanding into selections which get skipped when generating the tests (aka. blacklisting/suppressing)
* **referrer_policy_schema**
The schema to validate fields which define the ```referrer_policy``` elsewhere in the JSON.
A value for a referrer_policy can only be one specified in the referrer_policy_schema.
* **test_expansion_schema**
The schema used to check if a ```test_expansion``` is valid.
Each test expansion can only contain fields defined by this schema.
### Test Expansion Patterns
Each field in a test expansion can be in one of the following formats:
* Single match: ```"value"```
* Match any of: ```["value1", "value2", ...]```
* Match all: ```"*"```
#### Example: test expansion in a requirement specification
The following example shows how to restrict the expansion of ```referrer_url``` to ```origin``` and allow rest of the arrangement to expand (permute) to all possible values. The name field will be the prefix of a generated HTML file name for the test.
```json
{
"name": "origin-only",
"title": "Referrer Policy is set to 'origin-only'",
"description": "Check that all sub-resources in all cases get only the origin portion of the referrer URL.",
"specification_url": "https://w3c.github.io/webappsec/specs/referrer-policy/#referrer-policy-state-origin",
"referrer_policy": "origin",
"test_expansion": [
{
"name": "generic",
"expansion": "default",
"source_protocol": "*",
"target_protocol": "*",
"delivery_method": "*",
"redirection": "*",
"origin": "*",
"subresource": "*",
"referrer_url": "origin"
}
]
}
```
**NOTE:** An expansion is always constructive (inclusive), there isn't a negation operator for explicit exclusion. Be aware that using an empty list ```[]``` matches (expands into) exactly nothing. Tests which are to be excluded should be defined in the ```excluded_tests``` section instead.
A single test expansion pattern, be it a requirement or a suppressed pattern, gets expanded into a list of **selections** as follows:
* Expand each field's pattern (single, any of, or all) to list of allowed values (defined by the ```test_expansion_schema```)
* Permute - Recursively enumerate all **selections** across all fields
Be aware that if there is more than one pattern expanding into a same selection (which also shares the same ```name``` field), the pattern appearing later in the spec JSON will overwrite a previously generated selection. To make sure this is not undetected when generating, set the value of the ```expansion``` field to ```default``` for an expansion appearing earlier and ```override``` for the one appearing later.
A **selection** is a single **test instance** (scenario) with explicit values, for example:
```javascript
var scenario = {
"referrer_policy": "origin-when-cross-origin",
"delivery_method": "meta-referrer",
"redirection": "no-redirect",
"origin": "cross-origin",
"source_protocol": "http",
"target_protocol": "http",
"subresource": "iframe-tag",
"referrer_url": "origin"
};
```
Essentially, this is what gets generated and defines a single test. The scenario is then evaluated by the ```ReferrerPolicyTestCase``` in JS. For the rest of the arranging part, see the ```./generic/template/``` directory and examine ```./generic/tools/generate.py``` to see how the values for the templates are produced.
Taking the spec JSON, the generator follows this algorithm:
* Expand all ```excluded_tests``` to create a blacklist of selections
* For each specification requirement: Expand the ```test_expansion``` pattern into selections and check each against the blacklist, if not marked as suppresed, generate the test resources for the selection

View file

@ -31,8 +31,6 @@ class ReferrerPolicyConfig(object):
self.sanity_checker_js = '/referrer-policy/generic/sanity-checker.js' self.sanity_checker_js = '/referrer-policy/generic/sanity-checker.js'
self.spec_json_js = '/referrer-policy/spec_json.js' self.spec_json_js = '/referrer-policy/spec_json.js'
self.test_case_name = 'TestCase'
script_directory = os.path.dirname(os.path.abspath(__file__)) script_directory = os.path.dirname(os.path.abspath(__file__))
self.spec_directory = os.path.abspath( self.spec_directory = os.path.abspath(
os.path.join(script_directory, '..', '..')) os.path.join(script_directory, '..', '..'))

View file

@ -38,6 +38,7 @@
destUrl += 'page_origin=' + pageOrigin; destUrl += 'page_origin=' + pageOrigin;
destUrl += '&timing_allow=1'; destUrl += '&timing_allow=1';
destUrl += '&cross_origin=' + crossOrigin; destUrl += '&cross_origin=' + crossOrigin;
destUrl += '&final_resource=' + "/resource-timing/resources/blank-with-tao.html";
destUrl += '&tao_steps=3'; destUrl += '&tao_steps=3';
const frameContext = document.getElementById('frameContext'); const frameContext = document.getElementById('frameContext');
frameContext.onload = onload_test; frameContext.onload = onload_test;

View file

@ -37,6 +37,7 @@
let destUrl = pageOrigin + '/resource-timing/resources/multi_redirect.py?'; let destUrl = pageOrigin + '/resource-timing/resources/multi_redirect.py?';
destUrl += 'page_origin=' + pageOrigin; destUrl += 'page_origin=' + pageOrigin;
destUrl += '&cross_origin=' + crossOrigin; destUrl += '&cross_origin=' + crossOrigin;
destUrl += '&final_resource=' + "/resource-timing/resources/blank-with-tao.html";
const frameContext = document.getElementById('frameContext'); const frameContext = document.getElementById('frameContext');
frameContext.onload = onload_test; frameContext.onload = onload_test;
frameContext.src = destUrl; frameContext.src = destUrl;

View file

@ -38,6 +38,7 @@
destUrl += 'page_origin=' + pageOrigin; destUrl += 'page_origin=' + pageOrigin;
destUrl += '&timing_allow=1'; destUrl += '&timing_allow=1';
destUrl += '&cross_origin=' + crossOrigin; destUrl += '&cross_origin=' + crossOrigin;
destUrl += '&final_resource=' + "/resource-timing/resources/blank-with-tao.html";
destUrl += '&tao_steps=2'; destUrl += '&tao_steps=2';
const frameContext = document.getElementById('frameContext'); const frameContext = document.getElementById('frameContext');
frameContext.onload = onload_test; frameContext.onload = onload_test;

View file

@ -37,6 +37,7 @@
let destUrl = get_host_info().HTTP_REMOTE_ORIGIN + '/resource-timing/resources/multi_redirect.py?'; let destUrl = get_host_info().HTTP_REMOTE_ORIGIN + '/resource-timing/resources/multi_redirect.py?';
destUrl += 'page_origin=' + 'http://' + document.location.host; destUrl += 'page_origin=' + 'http://' + document.location.host;
destUrl += '&cross_origin=' + get_host_info().HTTP_REMOTE_ORIGIN; destUrl += '&cross_origin=' + get_host_info().HTTP_REMOTE_ORIGIN;
destUrl += '&final_resource=' + "/resource-timing/resources/blank-with-tao.html";
destUrl += '&tao_steps=3'; destUrl += '&tao_steps=3';
destUrl += '&timing_allow=1'; destUrl += '&timing_allow=1';
const frameContext = document.getElementById('frameContext'); const frameContext = document.getElementById('frameContext');

View file

@ -37,6 +37,7 @@
let destUrl = get_host_info().HTTP_REMOTE_ORIGIN + '/resource-timing/resources/multi_redirect.py?'; let destUrl = get_host_info().HTTP_REMOTE_ORIGIN + '/resource-timing/resources/multi_redirect.py?';
destUrl += 'page_origin=' + 'http://' + document.location.host; destUrl += 'page_origin=' + 'http://' + document.location.host;
destUrl += '&cross_origin=' + get_host_info().HTTP_REMOTE_ORIGIN; destUrl += '&cross_origin=' + get_host_info().HTTP_REMOTE_ORIGIN;
destUrl += '&final_resource=' + "/resource-timing/resources/blank-with-tao.html";
const frameContext = document.getElementById('frameContext'); const frameContext = document.getElementById('frameContext');
frameContext.onload = onload_test; frameContext.onload = onload_test;
frameContext.src = destUrl; frameContext.src = destUrl;

View file

@ -1,8 +1,13 @@
def main(request, response): def main(request, response):
"""Handler that causes multiple redirections. """Handler that causes multiple redirections. Redirect chain is as follows:
The request has two mandatory and one optional query parameters: 1. Initial URL containing multi-redirect.py
2. Redirect to cross-origin URL
3. Redirect to same-origin URL
4. Final URL containing the final same-origin resource.
The request has three mandatory and one optional query parameters:
page_origin - The page origin, used for redirection and to set TAO. This is a mandatory parameter. page_origin - The page origin, used for redirection and to set TAO. This is a mandatory parameter.
cross_origin - The cross origin used to make this a cross-origin redirect. This is a mandatory parameter. cross_origin - The cross origin used to make this a cross-origin redirect. This is a mandatory parameter.
final_resource - Path of the final resource, without origin. This is a mandatory parameter.
timing_allow - Whether TAO should be set or not in the redirect chain. This is an optional parameter. Default: not set. timing_allow - Whether TAO should be set or not in the redirect chain. This is an optional parameter. Default: not set.
Note that |step| is a parameter used internally for the multi-redirect. It's the step we're at in the redirect chain. Note that |step| is a parameter used internally for the multi-redirect. It's the step we're at in the redirect chain.
""" """
@ -16,6 +21,7 @@ def main(request, response):
origin = request.url_parts.scheme + "://" + request.url_parts.hostname + ":" + str(request.url_parts.port) origin = request.url_parts.scheme + "://" + request.url_parts.hostname + ":" + str(request.url_parts.port)
page_origin = request.GET.first("page_origin") page_origin = request.GET.first("page_origin")
cross_origin = request.GET.first("cross_origin") cross_origin = request.GET.first("cross_origin")
final_resource = request.GET.first("final_resource")
tao_steps = 0 tao_steps = 0
if "tao_steps" in request.GET: if "tao_steps" in request.GET:
tao_steps = int(request.GET.first("tao_steps")) tao_steps = int(request.GET.first("tao_steps"))
@ -27,6 +33,7 @@ def main(request, response):
redirect_url_path = "/resource-timing/resources/multi_redirect.py?" redirect_url_path = "/resource-timing/resources/multi_redirect.py?"
redirect_url_path += "page_origin=" + page_origin redirect_url_path += "page_origin=" + page_origin
redirect_url_path += "&cross_origin=" + cross_origin redirect_url_path += "&cross_origin=" + cross_origin
redirect_url_path += "&final_resource=" + final_resource
redirect_url_path += "&timing_allow=" + timing_allow redirect_url_path += "&timing_allow=" + timing_allow
redirect_url_path += "&tao_steps=" + str(next_tao_steps) redirect_url_path += "&tao_steps=" + str(next_tao_steps)
redirect_url_path += "&step=" redirect_url_path += "&step="
@ -41,7 +48,7 @@ def main(request, response):
redirect_url = page_origin + redirect_url_path + "3" redirect_url = page_origin + redirect_url_path + "3"
else: else:
# On the third request, redirect to a static response # On the third request, redirect to a static response
redirect_url = page_origin + "/resource-timing/resources/blank-with-tao.html" redirect_url = page_origin + final_resource
response.status = 302 response.status = 302
response.headers.set("Location", redirect_url) response.headers.set("Location", redirect_url)

View file

@ -3,6 +3,37 @@ set -ex
SCRIPT_DIR=$(cd $(dirname "$0") && pwd -P) SCRIPT_DIR=$(cd $(dirname "$0") && pwd -P)
WPT_ROOT=$SCRIPT_DIR/../.. WPT_ROOT=$SCRIPT_DIR/../..
EPOCHS=(
epochs/three_hourly::3h
epochs/six_hourly::6h
epochs/twelve_hourly::12h
epochs/daily::1d
epochs/weekly::1w
)
function get_epoch_branch_name () {
echo ${1} | awk -F '::' '{print $1}'
}
function get_epoch_timeval () {
echo ${1} | awk -F '::' '{print $2}'
}
main () {
ALL_BRANCHES_NAMES=""
for e in "${EPOCHS[@]}";
do
EPOCH=$(get_epoch_timeval ${e})
EPOCH_BRANCH_NAME=$(get_epoch_branch_name ${e})
git branch ${EPOCH_BRANCH_NAME} $(./wpt rev-list --epoch ${EPOCH})
ALL_BRANCHES_NAMES="${ALL_BRANCHES_NAMES} ${EPOCH_BRANCH_NAME}"
done
# This is safe because `git push` will by default fail for a non-fast-forward
# push, for example if the remote branch is ahead of the local branch.
git push ${REMOTE} ${ALL_BRANCHES_NAMES}
}
cd $WPT_ROOT cd $WPT_ROOT
if [ -z "$GITHUB_TOKEN" ]; then if [ -z "$GITHUB_TOKEN" ]; then
@ -12,7 +43,4 @@ fi
REMOTE=https://x-access-token:$GITHUB_TOKEN@github.com/web-platform-tests/wpt.git REMOTE=https://x-access-token:$GITHUB_TOKEN@github.com/web-platform-tests/wpt.git
git branch epochs/three_hourly $(./wpt rev-list --epoch 3h) main
# This is safe because `git push` will by default fail for a non-fast-forward
# push, for example if the remote branch is ahead of the local branch.
git push $REMOTE epochs/three_hourly

View file

@ -78,7 +78,7 @@ class ManifestItem(with_metaclass(ManifestItemMeta)):
def __repr__(self): def __repr__(self):
# type: () -> str # type: () -> str
return "<%s.%s id=%s, path=%s>" % (self.__module__, self.__class__.__name__, self.id, self.path) return "<%s.%s id=%r, path=%r>" % (self.__module__, self.__class__.__name__, self.id, self.path)
def to_json(self): def to_json(self):
# type: () -> Tuple[Any, ...] # type: () -> Tuple[Any, ...]

View file

@ -1,4 +1,4 @@
flake8==3.7.8 flake8==3.7.9
pycodestyle==2.5.0 pycodestyle==2.5.0
pyflakes==2.1.1 pyflakes==2.1.1
pep8-naming==0.8.2 pep8-naming==0.8.2

View file

@ -1,3 +1,3 @@
mypy==0.730 mypy==0.740
mypy-extensions==0.4.3 mypy-extensions==0.4.3
typed-ast==1.4.0 typed-ast==1.4.0

View file

@ -50,18 +50,14 @@ def get_tagged_revisions(pattern):
yield tag, commit, date yield tag, commit, date
def list_tagged_revisons(epoch, max_count): def get_epoch_revisions(epoch, until, max_count):
# type: (**Any) -> List[Text] # type: (**Any) -> List[Text]
logger.debug("list_tagged_revisons(%s, %s)" % (epoch, max_count)) logger.debug("get_epoch_revisions(%s, %s)" % (epoch, max_count))
# Set an offset to start to count the the weekly epoch from # Set an offset to start to count the the weekly epoch from
# Monday 00:00:00. This is particularly important for the weekly epoch # Monday 00:00:00. This is particularly important for the weekly epoch
# because fix the start of the epoch to Monday. This offset is calculated # because fix the start of the epoch to Monday. This offset is calculated
# from Thursday, 1 January 1970 0:00:00 to Monday, 5 January 1970 0:00:00 # from Thursday, 1 January 1970 0:00:00 to Monday, 5 January 1970 0:00:00
epoch_offset = 345600 epoch_offset = 345600
# "epoch_threshold" set a safety margin after this time it is fine to
# consider that any tags are created and pushed.
epoch_threshold = 600
epoch_until = int(time.time()) - epoch_threshold
count = 0 count = 0
# Iterates the tagged revisions in descending order finding the more # Iterates the tagged revisions in descending order finding the more
@ -84,12 +80,12 @@ def list_tagged_revisons(epoch, max_count):
# now # now
# Expected result: N,M,K,J,H,G,F,C,A # Expected result: N,M,K,J,H,G,F,C,A
cutoff_date = calculate_cutoff_date(epoch_until, epoch, epoch_offset) cutoff_date = calculate_cutoff_date(until, epoch, epoch_offset)
for _, commit, date in get_tagged_revisions("refs/tags/merge_pr_*"): for _, commit, date in get_tagged_revisions("refs/tags/merge_pr_*"):
if count >= max_count: if count >= max_count:
return return
if date < cutoff_date: if date < cutoff_date:
print(commit) yield commit
count += 1 count += 1
cutoff_date = calculate_cutoff_date(date, epoch, epoch_offset) cutoff_date = calculate_cutoff_date(date, epoch, epoch_offset)
@ -115,4 +111,9 @@ def get_parser():
def run_rev_list(**kwargs): def run_rev_list(**kwargs):
# type: (**Any) -> None # type: (**Any) -> None
list_tagged_revisons(kwargs["epoch"], kwargs["max_count"]) # "epoch_threshold" is a safety margin. After this time it is fine to
# assume that any tags are created and pushed.
epoch_threshold = 600
until = int(time.time()) - epoch_threshold
for line in get_epoch_revisions(kwargs["epoch"], until, kwargs["max_count"]):
print(line)

View file

@ -1,3 +1,4 @@
import mock
from tools.wpt import revlist from tools.wpt import revlist
@ -13,3 +14,150 @@ def test_parse_epoch():
assert revlist.parse_epoch(b"10h") == 36000 assert revlist.parse_epoch(b"10h") == 36000
assert revlist.parse_epoch(b"10d") == 864000 assert revlist.parse_epoch(b"10d") == 864000
assert revlist.parse_epoch(b"10w") == 6048000 assert revlist.parse_epoch(b"10w") == 6048000
@mock.patch('subprocess.check_output')
def test_get_epoch_revisions(mocked_check_output):
# check:
#
# * Several revisions in the same epoch offset (BC, DEF, HIJ, and LM)
# * Revision with a timestamp exactly equal to the epoch boundary (H)
# * Revision in non closed interval (O)
#
# mon tue wed thu fri sat sun mon thu wed
# | | | | | | | | |
# -A---B-C---DEF---G---H--IJ----------K-----L-M----N--O--
# ^
# until
# max_count: 5; epoch: 1d
# Expected result: N,M,K,J,G,F,C,A
epoch = 86400
until = 1188000 # Wednesday, 14 January 1970 18:00:00 UTC
mocked_check_output.return_value = b'''
merge_pr_O O 1166400 _wed_
merge_pr_N N 1080000 _tue_
merge_pr_M M 1015200 _mon_
merge_pr_L L 993600 _mon_
merge_pr_K K 907200 _sun_
merge_pr_J J 734400 _fri_
merge_pr_I I 712800 _fri_
merge_pr_H H 691200 _fri_
merge_pr_G G 648000 _thu_
merge_pr_F F 583200 _wed_
merge_pr_E E 561600 _wed_
merge_pr_D D 540000 _wed_
merge_pr_C C 475200 _tue_
merge_pr_B B 453600 _tue_
merge_pr_A A 388800 _mon_
'''
tagged_revisons = revlist.get_epoch_revisions(epoch, until, 8)
assert tagged_revisons.next() == 'N'
assert tagged_revisons.next() == 'M'
assert tagged_revisons.next() == 'K'
assert tagged_revisons.next() == 'J'
assert tagged_revisons.next() == 'G'
assert tagged_revisons.next() == 'F'
assert tagged_revisons.next() == 'C'
assert tagged_revisons.next() == 'A'
assert len(list(tagged_revisons)) == 0 # generator exhausted
# check: max_count with enough candidate items in the revision list
#
# mon tue wed thu fri sat sun mon
# | | | | | | |
# ------B-----C-----D----E-----F-----G------H---
# ^
# until
# max_count: 5; epoch: 1d
# Expected result: G,F,E,D,C
epoch = 86400
until = 1015200 # Monday, 12 January 1970 18:00:00 UTC
mocked_check_output.return_value = b'''
merge_pr_H H 993600 _mon_
merge_pr_G G 907200 _sun_
merge_pr_F F 820800 _sat_
merge_pr_E E 734400 _fri_
merge_pr_D D 648000 _thu_
merge_pr_C C 561600 _wed_
merge_pr_B B 475200 _thu_
'''
tagged_revisons = revlist.get_epoch_revisions(epoch, until, 5)
assert tagged_revisons.next() == 'G'
assert tagged_revisons.next() == 'F'
assert tagged_revisons.next() == 'E'
assert tagged_revisons.next() == 'D'
assert tagged_revisons.next() == 'C'
assert len(list(tagged_revisons)) == 0 # generator exhausted
# check: max_count with less returned candidates items than the needed
#
# mon tue wed thu fri sat sun mon
# | | | | | | |
# -----------------------------F-----G------H---
# ^
# until
# max_count: 5; epoch: 1d
# Expected result: G,F
epoch = 86400
until = 1015200 # Monday, 12 January 1970 18:00:00 UTC
mocked_check_output.return_value = b'''
merge_pr_H H 993600 _mon_
merge_pr_G G 907200 _sun_
merge_pr_F F 820800 _sat_
'''
tagged_revisons = revlist.get_epoch_revisions(epoch, until, 5)
assert tagged_revisons.next() == 'G'
assert tagged_revisons.next() == 'F'
assert len(list(tagged_revisons)) == 0 # generator exhausted
# check: initial until value is on an epoch boundary
#
# sud mon tue wed thu
# | | | |
# -F-G-----------------H
# ^
# until
# max_count: 3; epoch: 1d
# Expected result: G,F
# * H is skipped because because the epoch
# interval is defined as an right-open interval
# * G is included but in the Monday's interval
# * F is included because it is the unique candidate
# included in the Sunday's interval
epoch = 86400
until = 1296000 # Thursday, 15 January 1970 0:00:00 UTC
mocked_check_output.return_value = b'''
merge_pr_H H 1296000 _wed_
merge_pr_G G 950400 _mon_
merge_pr_F F 921600 _sud_
'''
tagged_revisons = revlist.get_epoch_revisions(epoch, until, 3)
assert tagged_revisons.next() == 'G'
assert tagged_revisons.next() == 'F'
assert len(list(tagged_revisons)) == 0 # generator exhausted
# check: until aligned with Monday, 5 January 1970 0:00:00 (345600)
# not with Thursday, 1 January 1970 0:00:00 (0)
#
# sud mon tue wed thu
# | | | |
# -F-G--------------H---
# ^
# until
# max_count: 1; epoch: 1w
# Expected result: F
epoch = 604800
moday = 950400 # Monday, 12 January 1970 00:00:00 UTC
until = moday + 345600 # 1296000. Thursday, 15 January 1970 0:00:00 UTC
mocked_check_output.return_value = b'''
merge_pr_H H 1180800 _wed_
merge_pr_G G 950400 _mon_
merge_pr_F F 921600 _sud_
'''
tagged_revisons = revlist.get_epoch_revisions(epoch, until, 1)
assert tagged_revisons.next() == 'F'
assert len(list(tagged_revisons)) == 0 # generator exhausted

View file

@ -39,7 +39,6 @@ def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
executor_kwargs["supports_eager_pageload"] = False executor_kwargs["supports_eager_pageload"] = False
capabilities = { capabilities = {
"acceptInsecureCerts": True,
"goog:chromeOptions": { "goog:chromeOptions": {
"prefs": { "prefs": {
"profile": { "profile": {
@ -62,7 +61,9 @@ def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
chrome_options["binary"] = kwargs["binary"] chrome_options["binary"] = kwargs["binary"]
# Here we set a few Chrome flags that are always passed. # Here we set a few Chrome flags that are always passed.
chrome_options["args"] = [] # ChromeDriver's "acceptInsecureCerts" capability only controls the current
# browsing context, whereas the CLI flag works for workers, too.
chrome_options["args"] = ["--ignore-certificate-errors"]
# Allow audio autoplay without a user gesture. # Allow audio autoplay without a user gesture.
chrome_options["args"].append("--autoplay-policy=no-user-gesture-required") chrome_options["args"].append("--autoplay-policy=no-user-gesture-required")
# Allow WebRTC tests to call getUserMedia. # Allow WebRTC tests to call getUserMedia.

View file

@ -179,18 +179,6 @@
return p; return p;
}, "Trusted Type violation report: sample for script innerText assignment"); }, "Trusted Type violation report: sample for script innerText assignment");
promise_test(t => {
let p = Promise.resolve()
.then(promise_violation("trusted-types one"))
.then(expect_blocked_uri("trusted-types-sink"))
.then(expect_sample("eval"))
.then(expect_sample("2+2"))
.then(promise_flush());
expect_throws(_ => eval("2+2"));
flush();
return p;
}, "Trusted Type violation report: sample for eval");
promise_test(t => { promise_test(t => {
// We expect the sample string to always contain the name, and at least the // We expect the sample string to always contain the name, and at least the
// start of the value, but it should not be excessively long. // start of the value, but it should not be excessively long.

View file

@ -0,0 +1,4 @@
# Upgrade-insecure-requests Web Platform Tests
The subdirectory `gen/` is generated using the generator at `common/security-features`.
See [common/security-features/README.md](../common/security-features/README.md) for how to generate tests.

View file

@ -31,8 +31,6 @@ class UpgradeInsecureRequestsConfig(object):
self.sanity_checker_js = '/upgrade-insecure-requests/generic/sanity-checker.js' self.sanity_checker_js = '/upgrade-insecure-requests/generic/sanity-checker.js'
self.spec_json_js = '/upgrade-insecure-requests/spec_json.js' self.spec_json_js = '/upgrade-insecure-requests/spec_json.js'
self.test_case_name = 'TestCase'
script_directory = os.path.dirname(os.path.abspath(__file__)) script_directory = os.path.dirname(os.path.abspath(__file__))
self.spec_directory = os.path.abspath( self.spec_directory = os.path.abspath(
os.path.join(script_directory, '..', '..')) os.path.join(script_directory, '..', '..'))

View file

@ -23,6 +23,8 @@
assert_equals(message.records.length, 1, 'one text record'); assert_equals(message.records.length, 1, 'one text record');
assert_equals(message.records[0].recordType, 'text', 'messageType'); assert_equals(message.records[0].recordType, 'text', 'messageType');
assert_equals(message.records[0].mediaType, 'text/plain', 'mediaType'); assert_equals(message.records[0].mediaType, 'text/plain', 'mediaType');
assert_equals(message.records[0].encoding, 'utf-8', 'encoding');
assert_equals(message.records[0].lang, 'en', 'lang');
assert_true(message.records[0].data instanceof DataView, assert_true(message.records[0].data instanceof DataView,
'data returns a DataView'); 'data returns a DataView');
const decoder = new TextDecoder(); const decoder = new TextDecoder();

View file

@ -47,6 +47,13 @@ const NDEFReaderOptionTests =
unmatchedScanOptions: {recordType: "json"}, unmatchedScanOptions: {recordType: "json"},
message: createMessage([createUrlRecord(test_url_data)]) message: createMessage([createUrlRecord(test_url_data)])
}, },
{
desc: "Test that reading data succeed when NDEFScanOptions'" +
" recordType is set to 'absolute-url'.",
scanOptions: {recordType: "absolute-url"},
unmatchedScanOptions: {recordType: "json"},
message: createMessage([createUrlRecord(test_url_data, true)])
},
{ {
desc: "Test that reading data succeed when NDEFScanOptions'" + desc: "Test that reading data succeed when NDEFScanOptions'" +
" recordType is set to a custom type for external type records.", " recordType is set to a custom type for external type records.",
@ -109,6 +116,13 @@ const ReadMultiMessagesTests =
message: createMessage([createUrlRecord(test_url_data)]), message: createMessage([createUrlRecord(test_url_data)]),
unmatchedMessage: createMessage([createTextRecord(test_text_data)]) unmatchedMessage: createMessage([createTextRecord(test_text_data)])
}, },
{
desc: "Test that filtering 'absolute-url' record from different messages" +
" correctly with NDEFScanOptions' recordType is set to 'absolute-url'.",
scanOptions: {recordType: "absolute-url"},
message: createMessage([createUrlRecord(test_url_data, true)]),
unmatchedMessage: createMessage([createTextRecord(test_text_data)])
},
{ {
desc: "Test that filtering external record from different messages" + desc: "Test that filtering external record from different messages" +
" correctly with NDEFScanOptions' recordType is set to the custom type.", " correctly with NDEFScanOptions' recordType is set to the custom type.",

View file

@ -20,12 +20,70 @@
const record = new NDEFRecord(createTextRecord(test_text_data)); const record = new NDEFRecord(createTextRecord(test_text_data));
assert_equals(record.recordType, 'text', 'recordType'); assert_equals(record.recordType, 'text', 'recordType');
assert_equals(record.mediaType, 'text/plain', 'mediaType'); assert_equals(record.mediaType, 'text/plain', 'mediaType');
assert_equals(record.encoding, 'utf-8', 'encoding');
assert_equals(record.lang, 'en', 'lang');
const decoder = new TextDecoder(); const decoder = new TextDecoder();
assert_equals(decoder.decode(record.data), test_text_data, assert_equals(decoder.decode(record.data), test_text_data,
'data has the same content with the original dictionary'); 'data has the same content with the original dictionary');
assert_equals(record.text(), test_text_data, }, 'NDEFRecord constructor with text record type and string data');
'text() has the same content with the original dictionary');
}, 'NDEFRecord constructor with text record type'); test(() => {
const encoder = new TextEncoder();
const uint8Array = encoder.encode(test_text_data);
const record = new NDEFRecord(createTextRecord(uint8Array.buffer));
assert_equals(record.recordType, 'text', 'recordType');
assert_equals(record.mediaType, 'text/plain', 'mediaType');
assert_equals(record.encoding, 'utf-8', 'encoding');
assert_equals(record.lang, 'en', 'lang');
const decoder = new TextDecoder();
assert_equals(decoder.decode(record.data), test_text_data,
'data has the same content with the original dictionary');
}, 'NDEFRecord constructor with text record type and arrayBuffer data');
test(() => {
const encoder = new TextEncoder();
const uint8Array = encoder.encode(test_text_data);
const record = new NDEFRecord(createTextRecord(uint8Array));
assert_equals(record.recordType, 'text', 'recordType');
assert_equals(record.mediaType, 'text/plain', 'mediaType');
assert_equals(record.encoding, 'utf-8', 'encoding');
assert_equals(record.lang, 'en', 'lang');
const decoder = new TextDecoder();
assert_equals(decoder.decode(record.data), test_text_data,
'data has the same content with the original dictionary');
}, 'NDEFRecord constructor with text record type and arrayBufferView data');
test(() => {
const encodings = ['utf-8', 'utf-16', 'utf-16be', 'utf-16le'];
for (const encoding of encodings) {
const lang = 'fr';
const record = new NDEFRecord(createTextRecord(test_text_data, encoding, lang));
assert_equals(record.recordType, 'text', 'recordType');
assert_equals(record.mediaType, 'text/plain', 'mediaType');
assert_equals(record.encoding, encoding, 'encoding');
assert_equals(record.lang, lang, 'lang');
const decoder = new TextDecoder();
assert_equals(decoder.decode(record.data), test_text_data,
'data has the same content with the original dictionary');
}
}, 'NDEFRecord constructor with text record type, encoding, and lang');
test(t => {
const previous_lang = document.querySelector('html').getAttribute('lang');
const test_lang = 'fr';
document.querySelector('html').setAttribute('lang', test_lang);
t.add_cleanup(() => {
document.querySelector('html').setAttribute('lang', previous_lang);
});
const record = new NDEFRecord(createTextRecord(test_text_data));
assert_equals(record.recordType, 'text', 'recordType');
assert_equals(record.mediaType, 'text/plain', 'mediaType');
assert_equals(record.encoding, 'utf-8', 'encoding');
assert_equals(record.lang, test_lang, 'lang');
const decoder = new TextDecoder();
assert_equals(decoder.decode(record.data), test_text_data,
'data has the same content with the original dictionary');
}, 'NDEFRecord constructor with text record type and custom document language');
test(() => { test(() => {
const record = new NDEFRecord(createUrlRecord(test_url_data)); const record = new NDEFRecord(createUrlRecord(test_url_data));
@ -38,6 +96,17 @@
'text() has the same content with the original dictionary'); 'text() has the same content with the original dictionary');
}, 'NDEFRecord constructor with url record type'); }, 'NDEFRecord constructor with url record type');
test(() => {
const record = new NDEFRecord(createUrlRecord(test_url_data, true));
assert_equals(record.recordType, 'absolute-url', 'recordType');
assert_equals(record.mediaType, 'text/plain', 'mediaType');
const decoder = new TextDecoder();
assert_equals(decoder.decode(record.data), test_url_data,
'data has the same content with the original dictionary');
assert_equals(record.text(), test_url_data,
'text() has the same content with the original dictionary');
}, 'NDEFRecord constructor with absolute-url record type');
test(() => { test(() => {
let buffer = new ArrayBuffer(4); let buffer = new ArrayBuffer(4);
let buffer_view = new Uint8Array(buffer); let buffer_view = new Uint8Array(buffer);

View file

@ -27,11 +27,18 @@ const invalid_type_messages =
// NDEFRecord must have data. // NDEFRecord must have data.
createMessage([createTextRecord()]), createMessage([createTextRecord()]),
// NDEFRecord.data for 'text' record must be a string. // NDEFRecord.data for 'text' record must be either a string,
createMessage([createTextRecord(test_buffer_data)]), // an arrayBuffer, or an arrayBufferView.
createMessage([createTextRecord(test_json_data)]), createMessage([createTextRecord(test_json_data)]),
createMessage([createTextRecord(test_number_data)]), createMessage([createTextRecord(test_number_data)]),
// NDEFRecord.encoding for 'text' record must be either "utf-8",
// "utf-16", "utf-16le" or "utf-16be".
createMessage([createTextRecord(test_text_data, "chinese")]),
// NDEFRecord.lang length for 'text' record must be lower than 64.
createMessage([createTextRecord(test_text_data, undefined /* encoding */, [...Array(64)].map(_ => 'a'))]),
// https://w3c.github.io/web-nfc/#dfn-map-a-json-object-to-ndef // https://w3c.github.io/web-nfc/#dfn-map-a-json-object-to-ndef
// NDEFRecord must have data. // NDEFRecord must have data.
createMessage([createJsonRecord()]), createMessage([createJsonRecord()]),
@ -40,11 +47,20 @@ const invalid_type_messages =
// NDEFRecord must have data. // NDEFRecord must have data.
createMessage([createUrlRecord()]), createMessage([createUrlRecord()]),
// https://w3c.github.io/web-nfc/#dfn-map-a-url-to-ndef
// NDEFRecord must have data.
createMessage([createUrlRecord(undefined, true)]),
// NDEFRecord.data for 'url' record must be string. // NDEFRecord.data for 'url' record must be string.
createMessage([createUrlRecord(test_buffer_data)]), createMessage([createUrlRecord(test_buffer_data)]),
createMessage([createUrlRecord(test_number_data)]), createMessage([createUrlRecord(test_number_data)]),
createMessage([createUrlRecord(test_json_data)]), createMessage([createUrlRecord(test_json_data)]),
// NDEFRecord.data for 'absolute-url' record must be string.
createMessage([createUrlRecord(test_buffer_data, true)]),
createMessage([createUrlRecord(test_number_data, true)]),
createMessage([createUrlRecord(test_json_data, true)]),
// https://w3c.github.io/web-nfc/#dfn-map-binary-data-to-ndef // https://w3c.github.io/web-nfc/#dfn-map-binary-data-to-ndef
// NDEFRecord must have data. // NDEFRecord must have data.
createMessage([createOpaqueRecord()]), createMessage([createOpaqueRecord()]),
@ -75,8 +91,9 @@ const invalid_syntax_messages =
createMessage([createRecord('text', 'application/json', createMessage([createRecord('text', 'application/json',
test_text_data)]), test_text_data)]),
// Data for 'url' record, must be a valid URL. // Data for 'url' or 'absolute-url' record, must be a valid URL.
createMessage([createUrlRecord('Invalid URL:// Data')]), createMessage([createUrlRecord('Invalid URL:// Data')]),
createMessage([createUrlRecord('Invalid URL:// Data', true)]),
// A JSON MIME type is any MIME type whose subtype ends in "+json" or // A JSON MIME type is any MIME type whose subtype ends in "+json" or
// whose essence is "application/json" or "text/json". // whose essence is "application/json" or "text/json".
@ -285,12 +302,13 @@ nfc_test(async (t, mockNFC) => {
createJsonRecord(test_number_data), createJsonRecord(test_number_data),
createOpaqueRecord(test_buffer_data), createOpaqueRecord(test_buffer_data),
createUrlRecord(test_url_data), createUrlRecord(test_url_data),
createUrlRecord(test_url_data, true),
createRecord('w3.org:xyz', '', test_buffer_data)], createRecord('w3.org:xyz', '', test_buffer_data)],
test_message_origin); test_message_origin);
await writer.push(message); await writer.push(message);
assertNDEFMessagesEqual(message, mockNFC.pushedMessage()); assertNDEFMessagesEqual(message, mockNFC.pushedMessage());
}, "NDEFWriter.push NDEFMessage containing text, json, opaque, url and external records \ }, "NDEFWriter.push NDEFMessage containing text, json, opaque, url, absolute-url \
with default NDEFPushOptions."); and external records with default NDEFPushOptions.");
nfc_test(async (t, mockNFC) => { nfc_test(async (t, mockNFC) => {
const writer = new NDEFWriter(); const writer = new NDEFWriter();
@ -429,14 +447,6 @@ nfc_test(async (t, mockNFC) => {
NDEFRecordInit.record's recordType is 'json' and NDEFRecordInit.record's \ NDEFRecordInit.record's recordType is 'json' and NDEFRecordInit.record's \
mediaType is undefined."); mediaType is undefined.");
nfc_test(async (t, mockNFC) => {
const writer = new NDEFWriter();
await writer.push({ records: [{ recordType: "url", data: test_url_data }] });
const message = createMessage([createUrlRecord(test_url_data)]);
assertNDEFMessagesEqual(message, mockNFC.pushedMessage());
}, "Test that mediaType should be set to 'text/plain' if NDEFRecordInit.record's \
recordType is 'url' and NDEFRecordInit.record's mediaType is undefined.");
nfc_test(async (t, mockNFC) => { nfc_test(async (t, mockNFC) => {
const writer = new NDEFWriter(); const writer = new NDEFWriter();
await writer.push({ records: [{ recordType: "w3.org:xyz", data: test_buffer_data }] }); await writer.push({ records: [{ recordType: "w3.org:xyz", data: test_buffer_data }] });

View file

@ -84,19 +84,23 @@ function createMessage(records) {
} }
} }
function createRecord(recordType, mediaType, data) { function createRecord(recordType, mediaType, data, encoding, lang) {
let record = {}; let record = {};
if (recordType !== undefined) if (recordType !== undefined)
record.recordType = recordType; record.recordType = recordType;
if (mediaType !== undefined) if (mediaType !== undefined)
record.mediaType = mediaType; record.mediaType = mediaType;
if (encoding !== undefined)
record.encoding = encoding;
if (lang !== undefined)
record.lang = lang;
if (data !== undefined) if (data !== undefined)
record.data = data; record.data = data;
return record; return record;
} }
function createTextRecord(text) { function createTextRecord(data, encoding, lang) {
return createRecord('text', 'text/plain', text); return createRecord('text', 'text/plain', data, encoding, lang);
} }
function createJsonRecord(json) { function createJsonRecord(json) {
@ -107,7 +111,10 @@ function createOpaqueRecord(buffer) {
return createRecord('opaque', 'application/octet-stream', buffer); return createRecord('opaque', 'application/octet-stream', buffer);
} }
function createUrlRecord(url) { function createUrlRecord(url, isAbsUrl) {
if (isAbsUrl) {
return createRecord('absolute-url', 'text/plain', url);
}
return createRecord('url', 'text/plain', url); return createRecord('url', 'text/plain', url);
} }

View file

@ -18,7 +18,7 @@ DEFAULT_CSS_STYLE = """
</style> </style>
""" """
DEFAULT_CONTENT = "<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>" DEFAULT_CONTENT = "<div>Lorem ipsum dolor sit amet.</div>"
def take_element_screenshot(session, element_id): def take_element_screenshot(session, element_id):

View file

@ -18,7 +18,7 @@ DEFAULT_CSS_STYLE = """
</style> </style>
""" """
DEFAULT_CONTENT = "<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>" DEFAULT_CONTENT = "<div>Lorem ipsum dolor sit amet.</div>"
def take_screenshot(session): def take_screenshot(session):

View file

@ -3,7 +3,7 @@
**/ **/
export function attemptGarbageCollection() { export function attemptGarbageCollection() {
const w = window; const w = self;
if (w.GCController) { if (w.GCController) {
w.GCController.collect(); w.GCController.collect();

View file

@ -13,6 +13,8 @@ export class Fixture {
_defineProperty(this, "rec", void 0); _defineProperty(this, "rec", void 0);
_defineProperty(this, "eventualExpectations", []);
_defineProperty(this, "numOutstandingAsyncExpectations", 0); _defineProperty(this, "numOutstandingAsyncExpectations", 0);
this.rec = rec; this.rec = rec;
@ -35,6 +37,8 @@ export class Fixture {
if (this.numOutstandingAsyncExpectations !== 0) { if (this.numOutstandingAsyncExpectations !== 0) {
throw new Error('there were outstanding asynchronous expectations (e.g. shouldReject) at the end of the test'); throw new Error('there were outstanding asynchronous expectations (e.g. shouldReject) at the end of the test');
} }
await Promise.all(this.eventualExpectations);
} }
warn(msg) { warn(msg) {
@ -45,18 +49,19 @@ export class Fixture {
this.rec.fail(msg); this.rec.fail(msg);
} }
ok(msg) { async immediateAsyncExpectation(fn) {
const m = msg ? ': ' + msg : '';
this.log('OK' + m);
}
async asyncExpectation(fn) {
this.numOutstandingAsyncExpectations++; this.numOutstandingAsyncExpectations++;
const ret = await fn(); const ret = await fn();
this.numOutstandingAsyncExpectations--; this.numOutstandingAsyncExpectations--;
return ret; return ret;
} }
eventualAsyncExpectation(fn) {
const promise = fn();
this.eventualExpectations.push(promise);
return promise;
}
expectErrorValue(expectedName, ex, m) { expectErrorValue(expectedName, ex, m) {
if (!(ex instanceof Error)) { if (!(ex instanceof Error)) {
this.fail('THREW NON-ERROR'); this.fail('THREW NON-ERROR');
@ -68,12 +73,12 @@ export class Fixture {
if (actualName !== expectedName) { if (actualName !== expectedName) {
this.fail(`THREW ${actualName} INSTEAD OF ${expectedName}${m}`); this.fail(`THREW ${actualName} INSTEAD OF ${expectedName}${m}`);
} else { } else {
this.ok(`threw ${actualName}${m}`); this.debug(`OK: threw ${actualName}${m}`);
} }
} }
async shouldReject(expectedName, p, msg) { shouldReject(expectedName, p, msg) {
this.asyncExpectation(async () => { this.eventualAsyncExpectation(async () => {
const m = msg ? ': ' + msg : ''; const m = msg ? ': ' + msg : '';
try { try {
@ -98,7 +103,8 @@ export class Fixture {
expect(cond, msg) { expect(cond, msg) {
if (cond) { if (cond) {
this.ok(msg); const m = msg ? ': ' + msg : '';
this.debug('expect OK' + m);
} else { } else {
this.rec.fail(msg); this.rec.fail(msg);
} }

View file

@ -38,9 +38,7 @@ export class TestLoader {
async loadTestsFromCmdLine(filters) { async loadTestsFromCmdLine(filters) {
// In actual URL queries (?q=...), + represents a space. But decodeURIComponent doesn't do this, return this.loadTests(filters);
// so do it manually. (+ is used over %20 for readability.) (See also encodeSelectively.)
return this.loadTests(filters.map(f => decodeURIComponent(f.replace(/\+/g, '%20'))));
} }
async loadTests(filters) { async loadTests(filters) {

View file

@ -5,6 +5,7 @@
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
import { makeQueryString } from './url_query.js'; import { makeQueryString } from './url_query.js';
import { extractPublicParams } from './url_query.js';
import { getStackTrace, now } from './util/index.js'; import { getStackTrace, now } from './util/index.js';
import { version } from './version.js'; import { version } from './version.js';
export class Logger { export class Logger {
@ -39,7 +40,7 @@ export class TestSpecRecorder {
record(test, params) { record(test, params) {
const result = { const result = {
test, test,
params, params: params ? extractPublicParams(params) : null,
status: 'running', status: 'running',
timems: -1 timems: -1
}; };

View file

@ -6,7 +6,7 @@ let _Symbol$iterator;
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
export function pcombine(params) { export function pcombine(...params) {
return new PCombine(params); return new PCombine(params);
} }

View file

@ -2,10 +2,11 @@
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/ **/
import { objectEquals } from '../util/index.js';
export * from './combine.js'; export * from './combine.js';
export * from './exclude.js';
export * from './filter.js'; export * from './filter.js';
export * from './options.js'; export * from './options.js';
export * from './exclude.js';
export function paramsEquals(x, y) { export function paramsEquals(x, y) {
if (x === y) { if (x === y) {
return true; return true;
@ -16,17 +17,17 @@ export function paramsEquals(x, y) {
} }
for (const xk of Object.keys(x)) { for (const xk of Object.keys(x)) {
if (!y.hasOwnProperty(xk)) { if (x[xk] !== undefined && !y.hasOwnProperty(xk)) {
return false; return false;
} }
if (x[xk] !== y[xk]) { if (!objectEquals(x[xk], y[xk])) {
return false; return false;
} }
} }
for (const yk of Object.keys(y)) { for (const yk of Object.keys(y)) {
if (!x.hasOwnProperty(yk)) { if (y[yk] !== undefined && !x.hasOwnProperty(yk)) {
return false; return false;
} }
} }

View file

@ -6,6 +6,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
import { allowedTestNameCharacters } from './allowed_characters.js'; import { allowedTestNameCharacters } from './allowed_characters.js';
import { paramsEquals } from './params/index.js'; import { paramsEquals } from './params/index.js';
import { checkPublicParamType, extractPublicParams } from './url_query.js';
const validNames = new RegExp('^[' + allowedTestNameCharacters + ']+$'); const validNames = new RegExp('^[' + allowedTestNameCharacters + ']+$');
export class TestGroup { export class TestGroup {
constructor(fixture) { constructor(fixture) {
@ -44,6 +45,12 @@ export class TestGroup {
test(name, fn) { test(name, fn) {
// Replace spaces with underscores for readability.
if (name.indexOf('_') !== -1) {
throw new Error('Invalid test name ${name}: contains underscore (use space)');
}
name = name.replace(/ /g, '_');
this.checkName(name); this.checkName(name);
const test = new Test(name, this.fixture, fn); const test = new Test(name, this.fixture, fn);
this.tests.push(test); this.tests.push(test);
@ -76,11 +83,18 @@ class Test {
const seen = []; // This is n^2. const seen = []; // This is n^2.
for (const spec of cases) { for (const spec of cases) {
if (seen.some(x => paramsEquals(x, spec))) { const publicParams = extractPublicParams(spec); // Check type of public params: can only be (currently):
// number, string, boolean, undefined, number[]
for (const v of Object.values(publicParams)) {
checkPublicParamType(v);
}
if (seen.some(x => paramsEquals(x, publicParams))) {
throw new Error('Duplicate test case params'); throw new Error('Duplicate test case params');
} }
seen.push(spec); seen.push(publicParams);
} }
this.cases = cases; this.cases = cases;
@ -88,27 +102,30 @@ class Test {
*iterate(rec) { *iterate(rec) {
for (const params of this.cases || [null]) { for (const params of this.cases || [null]) {
yield new RunCaseSpecific(rec, { yield new RunCaseSpecific(rec, this.name, params, this.fixture, this.fn);
test: this.name,
params
}, this.fixture, this.fn);
} }
} }
} }
class RunCaseSpecific { class RunCaseSpecific {
constructor(recorder, id, fixture, fn) { constructor(recorder, test, params, fixture, fn) {
_defineProperty(this, "id", void 0); _defineProperty(this, "id", void 0);
_defineProperty(this, "params", void 0);
_defineProperty(this, "recorder", void 0); _defineProperty(this, "recorder", void 0);
_defineProperty(this, "fixture", void 0); _defineProperty(this, "fixture", void 0);
_defineProperty(this, "fn", void 0); _defineProperty(this, "fn", void 0);
this.id = {
test,
params: params ? extractPublicParams(params) : null
};
this.params = params;
this.recorder = recorder; this.recorder = recorder;
this.id = id;
this.fixture = fixture; this.fixture = fixture;
this.fn = fn; this.fn = fn;
} }
@ -118,17 +135,32 @@ class RunCaseSpecific {
rec.start(debug); rec.start(debug);
try { try {
const inst = new this.fixture(rec, this.id.params || {}); const inst = new this.fixture(rec, this.params || {});
await inst.init(); await inst.init();
try {
await this.fn(inst); await this.fn(inst);
} catch (ex) {
// There was an exception from the test itself.
rec.threw(ex);
} // Runs as long as constructor and init succeeded, even if the test rejected.
await inst.finalize(); await inst.finalize();
} catch (e) { } catch (ex) {
rec.threw(e); // There was an exception from constructor, init, or finalize.
// (An error from finalize may have been an eventualAsyncExpectation failure.)
rec.threw(ex);
} }
rec.finish(); rec.finish();
return res; return res;
} }
injectResult(result) {
const [, res] = this.recorder.record(this.id.test, this.id.params);
Object.assign(res, result);
}
} }
//# sourceMappingURL=test_group.js.map //# sourceMappingURL=test_group.js.map

View file

@ -0,0 +1,90 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/
// e.g. iteratePath('a/b/c/d', ':') yields ['a/', 'a/b/', 'a/b/c/', 'a/b/c/d:']
function* iteratePath(path, terminator) {
const parts = path.split('/');
if (parts.length > 1) {
let partial = parts[0] + '/';
yield partial;
for (let i = 1; i < parts.length - 1; ++i) {
partial += parts[i] + '/';
yield partial;
} // Path ends in '/' (so is a README).
if (parts[parts.length - 1] === '') {
return;
}
}
yield path + terminator;
}
export function treeFromFilterResults(log, listing) {
function insertOrNew(n, k) {
const children = n.children;
if (children.has(k)) {
return children.get(k);
}
const v = {
children: new Map()
};
children.set(k, v);
return v;
}
const tree = {
children: new Map()
};
for (const f of listing) {
const files = insertOrNew(tree, f.id.suite + ':');
if (f.id.path === '') {
// This is a suite README.
files.description = f.spec.description;
continue;
}
let tests = files;
for (const path of iteratePath(f.id.path, ':')) {
tests = insertOrNew(tests, f.id.suite + ':' + path);
}
if (f.spec.description) {
// This is a directory README or spec file.
tests.description = f.spec.description.trim();
}
if (!('g' in f.spec)) {
// This is a directory README.
continue;
}
const [tRec] = log.record(f.id);
const fId = f.id.suite + ':' + f.id.path;
for (const t of f.spec.g.iterate(tRec)) {
let cases = tests;
for (const path of iteratePath(t.id.test, '~')) {
cases = insertOrNew(cases, fId + ':' + path);
}
const p = t.id.params ? JSON.stringify(t.id.params) : '';
cases.children.set(fId + ':' + t.id.test + '=' + p, {
runCase: t
});
}
}
return tree;
}
//# sourceMappingURL=tree.js.map

View file

@ -4,8 +4,6 @@
export function encodeSelectively(s) { export function encodeSelectively(s) {
let ret = encodeURIComponent(s); let ret = encodeURIComponent(s);
ret = ret.replace(/%20/g, '+'); // Encode space with + (equivalent but more readable)
ret = ret.replace(/%22/g, '"'); ret = ret.replace(/%22/g, '"');
ret = ret.replace(/%2C/g, ','); ret = ret.replace(/%2C/g, ',');
ret = ret.replace(/%2F/g, '/'); ret = ret.replace(/%2F/g, '/');
@ -17,6 +15,34 @@ export function encodeSelectively(s) {
ret = ret.replace(/%7D/g, '}'); ret = ret.replace(/%7D/g, '}');
return ret; return ret;
} }
export function extractPublicParams(params) {
const publicParams = {};
for (const k of Object.keys(params)) {
if (!k.startsWith('_')) {
publicParams[k] = params[k];
}
}
return publicParams;
}
export function checkPublicParamType(v) {
if (typeof v === 'number' || typeof v === 'string' || typeof v === 'boolean' || v === undefined) {
return;
}
if (v instanceof Array) {
for (const x of v) {
if (typeof x !== 'number') {
break;
}
}
return;
}
throw new Error('Invalid type for test case params ' + v);
}
export function makeQueryString(spec, testcase) { export function makeQueryString(spec, testcase) {
let s = spec.suite + ':'; let s = spec.suite + ':';
s += spec.path + ':'; s += spec.path + ':';
@ -25,7 +51,7 @@ export function makeQueryString(spec, testcase) {
s += testcase.test + '='; s += testcase.test + '=';
if (testcase.params) { if (testcase.params) {
s += JSON.stringify(testcase.params); s += JSON.stringify(extractPublicParams(testcase.params));
} }
} }

Some files were not shown because too many files have changed in this diff Show more