diff --git a/tests/wpt/meta-legacy-layout/css/css-box/parsing/clear-computed.html.ini b/tests/wpt/meta-legacy-layout/css/css-box/parsing/clear-computed.html.ini deleted file mode 100644 index 8e72ee8f2a2..00000000000 --- a/tests/wpt/meta-legacy-layout/css/css-box/parsing/clear-computed.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[clear-computed.html] - [Property clear value 'inline-start'] - expected: FAIL - - [Property clear value 'inline-end'] - expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-box/parsing/float-computed.html.ini b/tests/wpt/meta-legacy-layout/css/css-box/parsing/float-computed.html.ini deleted file mode 100644 index 3e7c0a24b57..00000000000 --- a/tests/wpt/meta-legacy-layout/css/css-box/parsing/float-computed.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[float-computed.html] - [Property float value 'inline-start'] - expected: FAIL - - [Property float value 'inline-end'] - expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-fonts/generic-family-keywords-001.html.ini b/tests/wpt/meta-legacy-layout/css/css-fonts/generic-family-keywords-001.html.ini index d6909124446..a234e1c3b3d 100644 --- a/tests/wpt/meta-legacy-layout/css/css-fonts/generic-family-keywords-001.html.ini +++ b/tests/wpt/meta-legacy-layout/css/css-fonts/generic-family-keywords-001.html.ini @@ -19,3 +19,6 @@ [@font-face matching for quoted and unquoted fangsong] expected: FAIL + + [@font-face matching for quoted and unquoted serif] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-shorthand-serialization.html.ini b/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-shorthand-serialization.html.ini index ba00bc04b8d..3a0572ef827 100644 --- a/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-shorthand-serialization.html.ini +++ b/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-shorthand-serialization.html.ini @@ -361,3 +361,63 @@ [e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(auto-fit, 3px); grid-template-areas: "one two" "three four" should set grid-template-rows] expected: FAIL + + [e.style.cssText = grid-template: none; should set grid] + expected: FAIL + + [e.style.cssText = grid-template: none; should set grid-template] + expected: FAIL + + [e.style.cssText = grid-template: none; should set grid-template-areas] + expected: FAIL + + [e.style.cssText = grid-template: none; should set grid-template-columns] + expected: FAIL + + [e.style.cssText = grid-template: none; should set grid-template-rows] + expected: FAIL + + [e.style.cssText = grid-template: auto / auto; should set grid] + expected: FAIL + + [e.style.cssText = grid-template: auto / auto; should set grid-template] + expected: FAIL + + [e.style.cssText = grid-template: auto / auto; should set grid-template-areas] + expected: FAIL + + [e.style.cssText = grid-template: auto / auto; should set grid-template-columns] + expected: FAIL + + [e.style.cssText = grid-template: auto / auto; should set grid-template-rows] + expected: FAIL + + [e.style.cssText = grid-template: [header-top\] "a a a" [header-bottom\] [main-top\] "b b b" 1fr [main-bottom\] / auto 1fr auto should set grid] + expected: FAIL + + [e.style.cssText = grid-template: [header-top\] "a a a" [header-bottom\] [main-top\] "b b b" 1fr [main-bottom\] / auto 1fr auto should set grid-template] + expected: FAIL + + [e.style.cssText = grid-template: [header-top\] "a a a" [header-bottom\] [main-top\] "b b b" 1fr [main-bottom\] / auto 1fr auto should set grid-template-areas] + expected: FAIL + + [e.style.cssText = grid-template: [header-top\] "a a a" [header-bottom\] [main-top\] "b b b" 1fr [main-bottom\] / auto 1fr auto should set grid-template-columns] + expected: FAIL + + [e.style.cssText = grid-template: [header-top\] "a a a" [header-bottom\] [main-top\] "b b b" 1fr [main-bottom\] / auto 1fr auto should set grid-template-rows] + expected: FAIL + + [e.style.cssText = grid-template: [header-top\] "a a a" [header-bottom\] [main-top\] "b b b" 1fr [main-bottom\] "c c c" "d d d" / auto should set grid] + expected: FAIL + + [e.style.cssText = grid-template: [header-top\] "a a a" [header-bottom\] [main-top\] "b b b" 1fr [main-bottom\] "c c c" "d d d" / auto should set grid-template] + expected: FAIL + + [e.style.cssText = grid-template: [header-top\] "a a a" [header-bottom\] [main-top\] "b b b" 1fr [main-bottom\] "c c c" "d d d" / auto should set grid-template-areas] + expected: FAIL + + [e.style.cssText = grid-template: [header-top\] "a a a" [header-bottom\] [main-top\] "b b b" 1fr [main-bottom\] "c c c" "d d d" / auto should set grid-template-columns] + expected: FAIL + + [e.style.cssText = grid-template: [header-top\] "a a a" [header-bottom\] [main-top\] "b b b" 1fr [main-bottom\] "c c c" "d d d" / auto should set grid-template-rows] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-template-shorthand-areas-valid.html.ini b/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-template-shorthand-areas-valid.html.ini index 25e5fb05d24..272f8abed26 100644 --- a/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-template-shorthand-areas-valid.html.ini +++ b/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-template-shorthand-areas-valid.html.ini @@ -13,3 +13,6 @@ [grid-template: 10px 20px 30px / 40px 50px 60px 70px and "grid-template-areas: "a . b ." "c d . e" "f g h .";" should be valid.] expected: FAIL + + [grid-template: none / none and "grid-template-areas: "a" "b" "c" "d" "e";" should be valid.] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-template-shorthand.html.ini b/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-template-shorthand.html.ini index 6c167c77773..4a5ccf1e296 100644 --- a/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-template-shorthand.html.ini +++ b/tests/wpt/meta-legacy-layout/css/css-grid/parsing/grid-template-shorthand.html.ini @@ -70,3 +70,15 @@ [e.style['grid-template'\] = " [\] \\"a a a\\" [\] [\] \\"b b b\\" 1fr [\] / [\] auto 1fr [\] auto [\]" should not set unrelated longhands] expected: FAIL + + [e.style['grid-template'\] = " [\] \\"a a a\\" [\] [\] \\"b b b\\" 1fr [\] \\"c c c\\" / [\] auto 1fr [\] auto [\]" should set grid-template-areas] + expected: FAIL + + [e.style['grid-template'\] = " [\] \\"a a a\\" [\] [\] \\"b b b\\" 1fr [\] \\"c c c\\" / [\] auto 1fr [\] auto [\]" should set grid-template-columns] + expected: FAIL + + [e.style['grid-template'\] = " [\] \\"a a a\\" [\] [\] \\"b b b\\" 1fr [\] \\"c c c\\" / [\] auto 1fr [\] auto [\]" should set grid-template-rows] + expected: FAIL + + [e.style['grid-template'\] = " [\] \\"a a a\\" [\] [\] \\"b b b\\" 1fr [\] \\"c c c\\" / [\] auto 1fr [\] auto [\]" should not set unrelated longhands] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-logical/logical-values-float-clear.html.ini b/tests/wpt/meta-legacy-layout/css/css-logical/logical-values-float-clear.html.ini deleted file mode 100644 index a8045bfd3eb..00000000000 --- a/tests/wpt/meta-legacy-layout/css/css-logical/logical-values-float-clear.html.ini +++ /dev/null @@ -1,12 +0,0 @@ -[logical-values-float-clear.html] - [Test that 'clear: inline-start' is supported.] - expected: FAIL - - [Test that 'clear: inline-end' is supported.] - expected: FAIL - - [Test that 'float: inline-start' is supported.] - expected: FAIL - - [Test that 'float: inline-end' is supported.] - expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-pseudo/parsing/the-check-pseudo-element.tentative.html.ini b/tests/wpt/meta-legacy-layout/css/css-pseudo/parsing/the-check-pseudo-element.tentative.html.ini index f7904aad447..062a58a6e3f 100644 --- a/tests/wpt/meta-legacy-layout/css/css-pseudo/parsing/the-check-pseudo-element.tentative.html.ini +++ b/tests/wpt/meta-legacy-layout/css/css-pseudo/parsing/the-check-pseudo-element.tentative.html.ini @@ -1,36 +1,2 @@ [the-check-pseudo-element.tentative.html] - ["::check" should be a valid selector] - expected: FAIL - - ["*::check" should be a valid selector] - expected: FAIL - - ["foo.bar[baz\]::check" should be a valid selector] - expected: FAIL - - ["::check::marker" should be a valid selector] - expected: FAIL - - ["::slotted(*)::check" should be a valid selector] - expected: FAIL - - ["::part(foo)::check" should be a valid selector] - expected: FAIL - - ["::checkmark" should be a valid selector] - expected: FAIL - - ["*::checkmark" should be a valid selector] - expected: FAIL - - ["foo.bar[baz\]::checkmark" should be a valid selector] - expected: FAIL - - ["::checkmark::marker" should be a valid selector] - expected: FAIL - - ["::slotted(*)::checkmark" should be a valid selector] - expected: FAIL - - ["::part(foo)::checkmark" should be a valid selector] - expected: FAIL + expected: TIMEOUT diff --git a/tests/wpt/meta-legacy-layout/css/css-pseudo/parsing/the-select-arrow-pseudo-element.tentative.html.ini b/tests/wpt/meta-legacy-layout/css/css-pseudo/parsing/the-select-arrow-pseudo-element.tentative.html.ini index 422e5abf336..a4c4197b59b 100644 --- a/tests/wpt/meta-legacy-layout/css/css-pseudo/parsing/the-select-arrow-pseudo-element.tentative.html.ini +++ b/tests/wpt/meta-legacy-layout/css/css-pseudo/parsing/the-select-arrow-pseudo-element.tentative.html.ini @@ -1,33 +1,2 @@ [the-select-arrow-pseudo-element.tentative.html] - ["::select-arrow" should be a valid selector] - expected: FAIL - - ["*::select-arrow" should be a valid selector] - expected: FAIL - - ["foo.bar[baz\]::select-arrow" should be a valid selector] - expected: FAIL - - ["::select-arrow::marker" should be a valid selector] - expected: FAIL - - ["::slotted(*)::select-arrow" should be a valid selector] - expected: FAIL - - ["::part(foo)::select-arrow" should be a valid selector] - expected: FAIL - - ["::picker-icon" should be a valid selector] - expected: FAIL - - ["*::picker-icon" should be a valid selector] - expected: FAIL - - ["foo.bar[baz\]::picker-icon" should be a valid selector] - expected: FAIL - - ["::slotted(*)::picker-icon" should be a valid selector] - expected: FAIL - - ["::part(foo)::picker-icon" should be a valid selector] - expected: FAIL + expected: TIMEOUT diff --git a/tests/wpt/meta-legacy-layout/css/css-values/vh_not_refreshing_on_chrome.html.ini b/tests/wpt/meta-legacy-layout/css/css-values/vh_not_refreshing_on_chrome.html.ini index 9bafc27593e..599b3e07f8d 100644 --- a/tests/wpt/meta-legacy-layout/css/css-values/vh_not_refreshing_on_chrome.html.ini +++ b/tests/wpt/meta-legacy-layout/css/css-values/vh_not_refreshing_on_chrome.html.ini @@ -1,3 +1,2 @@ [vh_not_refreshing_on_chrome.html] bug: https://github.com/servo/servo/issues/8984 - expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini b/tests/wpt/meta-legacy-layout/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini index 314dca9c1f5..d52a3e77a70 100644 --- a/tests/wpt/meta-legacy-layout/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini +++ b/tests/wpt/meta-legacy-layout/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini @@ -1,3 +1,6 @@ [MediaQueryList-addListener-removeListener.html] [listeners are called when - - - diff --git a/tests/wpt/tests/content-security-policy/report-hash/default-src.https.window.js b/tests/wpt/tests/content-security-policy/report-hash/default-src.https.window.js new file mode 100644 index 00000000000..c8edc03fd3f --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/default-src.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/tests/wpt/tests/content-security-policy/report-hash/default-src.https.window.js.sub.headers b/tests/wpt/tests/content-security-policy/report-hash/default-src.https.window.js.sub.headers new file mode 100644 index 00000000000..3566b037308 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/default-src.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy: default-src 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/tests/wpt/tests/content-security-policy/report-hash/multiple-policies.https.sub.html b/tests/wpt/tests/content-security-policy/report-hash/multiple-policies.https.sub.html new file mode 100644 index 00000000000..ae4f88864d8 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/multiple-policies.https.sub.html @@ -0,0 +1,18 @@ + + + + + Test that reports for same-origin subresources are sent with hashes + + + + + + + + + + + diff --git a/tests/wpt/tests/content-security-policy/report-hash/multiple-policies.https.sub.html.sub.headers b/tests/wpt/tests/content-security-policy/report-hash/multiple-policies.https.sub.html.sub.headers new file mode 100644 index 00000000000..17c313da488 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/multiple-policies.https.sub.html.sub.headers @@ -0,0 +1,7 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy: script-src-elem 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Reporting-Endpoints: csp-endpoint2="/reporting/resources/report.py?reportID={{$id2:uuid()}}" +Content-Security-Policy: script-src-elem 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha512'; report-to csp-endpoint2 +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" +Server-Timing: uuid2;desc="{{$id2}}",hash2;desc="sha512-hG4x56V5IhUUepZdYU/lX7UOQJ2M7f6ud2EI7os4JV3OwXSZ002P3zkb9tXQkjpOO8UbtjuEufvdcU67Qt2tlw==" + diff --git a/tests/wpt/tests/content-security-policy/report-hash/reportonly-default-src.https.window.js b/tests/wpt/tests/content-security-policy/report-hash/reportonly-default-src.https.window.js new file mode 100644 index 00000000000..c8edc03fd3f --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/reportonly-default-src.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/tests/wpt/tests/content-security-policy/report-hash/reportonly-default-src.https.window.js.sub.headers b/tests/wpt/tests/content-security-policy/report-hash/reportonly-default-src.https.window.js.sub.headers new file mode 100644 index 00000000000..0490f22ed47 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/reportonly-default-src.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy-Report-Only: default-src 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js new file mode 100644 index 00000000000..c8edc03fd3f --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js.sub.headers b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js.sub.headers new file mode 100644 index 00000000000..b7929547a09 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy-Report-Only: script-src-elem 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-none.https.window.js b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-none.https.window.js new file mode 100644 index 00000000000..d708e989b70 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-none.https.window.js @@ -0,0 +1,4 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); + diff --git a/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-none.https.window.js.sub.headers b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-none.https.window.js.sub.headers new file mode 100644 index 00000000000..9c6d3efd274 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src-none.https.window.js.sub.headers @@ -0,0 +1,4 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy-Report-Only: script-src 'none' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" + diff --git a/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src.https.window.js b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src.https.window.js new file mode 100644 index 00000000000..c8edc03fd3f --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src.https.window.js.sub.headers b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src.https.window.js.sub.headers new file mode 100644 index 00000000000..ee7eb6f7f53 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/reportonly-script-src.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy-Report-Only: script-src 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/tests/wpt/tests/content-security-policy/report-hash/resources/report-hash-test-runner.sub.js b/tests/wpt/tests/content-security-policy/report-hash/resources/report-hash-test-runner.sub.js new file mode 100644 index 00000000000..f336cf14bfb --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/resources/report-hash-test-runner.sub.js @@ -0,0 +1,129 @@ +function find_server_timing(name) { + const server_timing = performance.getEntriesByType("navigation")[0].serverTiming; + for (entry of server_timing) { + if (entry.name == name) { + return entry.description; + } + } + return null; +} + +const ORIGIN = "https://{{host}}:{{ports[https][0]}}"; +const REMOTE_ORIGIN = "https://{{hosts[alt][www]}}:{{ports[https][0]}}"; +const endpoint = `${ORIGIN}/reporting/resources/report.py`; +const id = find_server_timing("uuid"); +const id2 = find_server_timing("uuid2"); +const subresource_url = `${ORIGIN}/reporting/resources/comment.js`; +const crossorigin_subresource_url = `${REMOTE_ORIGIN}/reporting/resources/comment.js`; +const subresource_hash = find_server_timing("hash"); +const subresource_hash2 = find_server_timing("hash2"); +let counter = 0; + +function reporting_observer_setup(expected_url, expected_hash) { + return new Promise(resolve => { + new ReportingObserver((reports, observer) => { + assert_unreached(); + observer.disconnect(); + }, { types: ["csp-hash"] }).observe(); + step_timeout(resolve, 100); + }); +} + +async function check_reports(uuid, expected_hash, url) { + const reports = await pollReports(endpoint, uuid); + checkReportExists(reports, 'csp-hash', location.href); + const report = getReport(reports, 'csp-hash', location.href, url); + assert_not_equals(report, null); + assert_equals(report.body.hash, expected_hash); + assert_equals(report.body.type, "subresource"); + assert_equals(report.body.destination, "script"); +} + +function report_hash_test(url, populate_script_attributes, expected_hash, expected_hash2, description) { + promise_test(async t => { + const unique_subresource_url = `${url}?${++counter}`; + const observer_promise = reporting_observer_setup(unique_subresource_url, subresource_hash); + // Trigger a script load + await new Promise(resolve => { + const script = document.createElement('script'); + script.src = unique_subresource_url; + populate_script_attributes(script); + script.addEventListener('load', resolve); + document.head.appendChild(script); + }); + + await check_reports(id, expected_hash, unique_subresource_url); + if (id2) { + await check_reports(id2, expected_hash2, unique_subresource_url); + } + await observer_promise; + }, description); +} + +function no_report_test(create_element, description) { + promise_test(async t => { + const unique_subresource_url = `${subresource_url}?${++counter}`; + // Trigger a script load + await new Promise(resolve => { + const elem = create_element(unique_subresource_url); + elem.addEventListener('load', resolve); + elem.addEventListener('error', resolve); + document.head.appendChild(elem); + }); + + // Wait for report to be received. + const reports = await pollReports(endpoint, id); + const report = getReport(reports, 'csp-hash', location.href, unique_subresource_url); + assert_equals(report, null); + }, description); +}; + +function run_tests() { + report_hash_test(subresource_url, script => { + script.crossOrigin = "anonymous"; + }, subresource_hash, subresource_hash2, + "Reporting endpoints received hash for same-origin CORS script."); + + report_hash_test(subresource_url, script => { + }, subresource_hash, subresource_hash2, + "Reporting endpoints received hash for same-origin no-CORS script."); + + report_hash_test(crossorigin_subresource_url, script => { + script.crossOrigin = "anonymous"; + }, subresource_hash, subresource_hash2, + "Reporting endpoints received hash for cross-origin CORS script."); + + report_hash_test(crossorigin_subresource_url, script => { + }, /*expected_hash=*/"", /*expected_hash2=*/"", + "Reporting endpoints received no hash for cross-origin no-CORS script."); + + report_hash_test(subresource_url, script => { + script.crossOrigin = "anonymous"; + script.integrity = "sha512-hG4x56V5IhUUepZdYU/lX7UOQJ2M7f6ud2EI7os4JV3OwXSZ002P3zkb9tXQkjpOO8UbtjuEufvdcU67Qt2tlw=="; + }, subresource_hash, subresource_hash2, + "Reporting endpoints received the right hash for same-origin CORS script with integrity."); + + no_report_test(url => { + const script = document.createElement('script'); + script.src = url; + script.crossOrigin = "anonymous" + script.integrity = "sha256-foobar"; + return script; + }, "Reporting endpoints received no report for failed integrity check with sha256."); + + no_report_test(url => { + const script = document.createElement('script'); + script.src = url; + script.crossOrigin = "anonymous" + script.integrity = "sha512-foobar"; + return script; + }, "Reporting endpoints received no report for failed integrity check with sha512."); + + no_report_test(url => { + const link = document.createElement('link'); + link.href = url; + link.crossOrigin = "anonymous" + link.rel = "stylesheet" + return link; + }, "Reporting endpoints received no report for CORS stylesheet."); +} diff --git a/tests/wpt/tests/content-security-policy/report-hash/script-src-elem.https.window.js b/tests/wpt/tests/content-security-policy/report-hash/script-src-elem.https.window.js new file mode 100644 index 00000000000..c8edc03fd3f --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/script-src-elem.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/tests/wpt/tests/content-security-policy/report-hash/script-src-elem.https.window.js.sub.headers b/tests/wpt/tests/content-security-policy/report-hash/script-src-elem.https.window.js.sub.headers new file mode 100644 index 00000000000..d9c04180310 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/script-src-elem.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy: script-src-elem 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/tests/wpt/tests/content-security-policy/report-hash/script-src-sha512.https.window.js b/tests/wpt/tests/content-security-policy/report-hash/script-src-sha512.https.window.js new file mode 100644 index 00000000000..c8edc03fd3f --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/script-src-sha512.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/tests/wpt/tests/content-security-policy/report-hash/script-src-sha512.https.window.js.sub.headers b/tests/wpt/tests/content-security-policy/report-hash/script-src-sha512.https.window.js.sub.headers new file mode 100644 index 00000000000..eaa0873582b --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/script-src-sha512.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy: script-src 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha512' 'report-sha384' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha512-hG4x56V5IhUUepZdYU/lX7UOQJ2M7f6ud2EI7os4JV3OwXSZ002P3zkb9tXQkjpOO8UbtjuEufvdcU67Qt2tlw==" diff --git a/tests/wpt/tests/content-security-policy/report-hash/script-src.https.window.js b/tests/wpt/tests/content-security-policy/report-hash/script-src.https.window.js new file mode 100644 index 00000000000..c8edc03fd3f --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/script-src.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/tests/wpt/tests/content-security-policy/report-hash/script-src.https.window.js.sub.headers b/tests/wpt/tests/content-security-policy/report-hash/script-src.https.window.js.sub.headers new file mode 100644 index 00000000000..bd92f728c85 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/report-hash/script-src.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy: script-src 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/tests/wpt/tests/css/css-anchor-position/chrome-379758203-crash.html b/tests/wpt/tests/css/css-anchor-position/chrome-379758203-crash.html new file mode 100644 index 00000000000..eea43feb599 --- /dev/null +++ b/tests/wpt/tests/css/css-anchor-position/chrome-379758203-crash.html @@ -0,0 +1,31 @@ + + + + +
+
+
Hello World
+
+
+ diff --git a/tests/wpt/tests/css/css-grid/parsing/grid-shorthand-serialization.html b/tests/wpt/tests/css/css-grid/parsing/grid-shorthand-serialization.html index 61be1c2872b..aca07d7075d 100644 --- a/tests/wpt/tests/css/css-grid/parsing/grid-shorthand-serialization.html +++ b/tests/wpt/tests/css/css-grid/parsing/grid-shorthand-serialization.html @@ -2,7 +2,7 @@ -CSS Grid Layout Test: only serialize 'grid' when the value can roundtrip +CSS Grid Layout Test: only serialize 'grid' shorthands when the value can roundtrip @@ -236,6 +236,41 @@ 'grid-template-columns': 'none', 'grid-template-rows': 'repeat(auto-fit, 3px)' }); + + test_shorthand_roundtrip('grid-template: none;', + { + 'grid': '', + 'grid-template-areas': 'none', + 'grid-template-rows': 'none', + 'grid-template-columns': 'none', + 'grid-template': 'none' + }); + test_shorthand_roundtrip('grid-template: auto / auto;', + { + 'grid': '', + 'grid-template-areas': 'none', + 'grid-template-rows': 'auto', + 'grid-template-columns': 'auto', + 'grid-template': 'auto / auto' + }); + test_shorthand_roundtrip('grid-template: [header-top] "a a a" [header-bottom] [main-top] "b b b" 1fr [main-bottom] / auto 1fr auto', + { + 'grid': '', + 'grid-template-areas': '"a a a" "b b b"', + 'grid-template-rows': '[header-top] auto [header-bottom main-top] 1fr [main-bottom]', + 'grid-template-columns': 'auto 1fr auto', + 'grid-template': '[header-top] "a a a" [header-bottom main-top] "b b b" 1fr [main-bottom] / auto 1fr auto' + }); + + test_shorthand_roundtrip('grid-template: [header-top] "a a a" [header-bottom] [main-top] "b b b" 1fr [main-bottom] "c c c" "d d d" / auto', + { + 'grid': '', + 'grid-template-areas': '"a a a" "b b b" "c c c" "d d d"', + 'grid-template-rows': '[header-top] auto [header-bottom main-top] 1fr [main-bottom] auto auto', + 'grid-template-columns': 'auto', + 'grid-template': '[header-top] "a a a" [header-bottom main-top] "b b b" 1fr [main-bottom] "c c c" "d d d" / auto' + }); + test_shorthand_roundtrip('grid-template-rows: auto auto; grid-template-columns: repeat(2, 3px); grid-template-areas: "one two" "three four"', { 'grid': '', diff --git a/tests/wpt/tests/css/css-grid/parsing/grid-template-shorthand-areas-valid.html b/tests/wpt/tests/css/css-grid/parsing/grid-template-shorthand-areas-valid.html index 2d2b2433a41..c4703197e29 100644 --- a/tests/wpt/tests/css/css-grid/parsing/grid-template-shorthand-areas-valid.html +++ b/tests/wpt/tests/css/css-grid/parsing/grid-template-shorthand-areas-valid.html @@ -28,6 +28,7 @@ function testValidGridTemplate(valueGridTemplate, valueGridAreas, serializedGrid testValidGridTemplate("none / 1px", "\"a\"", ""); testValidGridTemplate("none / none", "\"a\"", ""); +testValidGridTemplate("none / none", "\"a\" \"b\" \"c\" \"d\" \"e\"", ""); testValidGridTemplate("auto / 1px", "\"a a a\"", "\"a a a\" / 1px"); testValidGridTemplate("auto / auto", "\"a a a\"", "\"a a a\" / auto"); testValidGridTemplate("10px 20px 30px / 40px 50px 60px 70px", diff --git a/tests/wpt/tests/css/css-grid/parsing/grid-template-shorthand-composition.html b/tests/wpt/tests/css/css-grid/parsing/grid-template-shorthand-composition.html new file mode 100644 index 00000000000..781410d5153 --- /dev/null +++ b/tests/wpt/tests/css/css-grid/parsing/grid-template-shorthand-composition.html @@ -0,0 +1,39 @@ + + + + +CSS Grid Layout Test: grid-template-rows, grid-template-columns, and grid-template-areas properly set grid-template longhand + + + + + + + + + + diff --git a/tests/wpt/tests/css/css-grid/parsing/grid-template-shorthand.html b/tests/wpt/tests/css/css-grid/parsing/grid-template-shorthand.html index d7e8f47e14a..bde0118a630 100644 --- a/tests/wpt/tests/css/css-grid/parsing/grid-template-shorthand.html +++ b/tests/wpt/tests/css/css-grid/parsing/grid-template-shorthand.html @@ -58,6 +58,15 @@ test_shorthand_value('grid-template', 'grid-template-columns': 'auto 1fr auto', 'grid-template-areas': '"a a a" "b b b"' }); + +test_shorthand_value('grid-template', + ' [] "a a a" []' + + ' [] "b b b" 1fr []' + + ' "c c c" / [] auto 1fr [] auto []', { + 'grid-template-rows': 'auto 1fr auto', + 'grid-template-columns': 'auto 1fr auto', + 'grid-template-areas': '"a a a" "b b b" "c c c"' +}); diff --git a/tests/wpt/tests/css/css-overflow/scrollable-overflow-padding-inline.html b/tests/wpt/tests/css/css-overflow/scrollable-overflow-padding-inline.html new file mode 100644 index 00000000000..38b02e99dce --- /dev/null +++ b/tests/wpt/tests/css/css-overflow/scrollable-overflow-padding-inline.html @@ -0,0 +1,57 @@ + +CSS Overflow Test: Ensure that padding inflation for inline elements are carried out as part of containing line box's bounds. + + + + + + + + + + + +
+
+ X +
+ +
+
+ X +
+ +
+
+ X +
+
+
+ X +
+ +
+
+ X +
+ +
+
+ +
+ diff --git a/tests/wpt/tests/css/css-pseudo/parsing/the-check-pseudo-element.tentative.html b/tests/wpt/tests/css/css-pseudo/parsing/the-checkmark-pseudo-element.tentative.html similarity index 93% rename from tests/wpt/tests/css/css-pseudo/parsing/the-check-pseudo-element.tentative.html rename to tests/wpt/tests/css/css-pseudo/parsing/the-checkmark-pseudo-element.tentative.html index f220e29bcd0..f50794a5128 100644 --- a/tests/wpt/tests/css/css-pseudo/parsing/the-check-pseudo-element.tentative.html +++ b/tests/wpt/tests/css/css-pseudo/parsing/the-checkmark-pseudo-element.tentative.html @@ -1,7 +1,7 @@ CSS ::checkmark Pseudo-Element Test - + diff --git a/tests/wpt/tests/css/css-pseudo/parsing/the-select-arrow-pseudo-element.tentative.html b/tests/wpt/tests/css/css-pseudo/parsing/the-picker-icon-pseudo-element.tentative.html similarity index 93% rename from tests/wpt/tests/css/css-pseudo/parsing/the-select-arrow-pseudo-element.tentative.html rename to tests/wpt/tests/css/css-pseudo/parsing/the-picker-icon-pseudo-element.tentative.html index 69e1d1e11dd..79a5e10e93b 100644 --- a/tests/wpt/tests/css/css-pseudo/parsing/the-select-arrow-pseudo-element.tentative.html +++ b/tests/wpt/tests/css/css-pseudo/parsing/the-picker-icon-pseudo-element.tentative.html @@ -1,7 +1,7 @@ CSS ::picker-icon Pseudo-Element Test - + diff --git a/tests/wpt/tests/css/css-rhythm/parsing/block-step-computed.html b/tests/wpt/tests/css/css-rhythm/parsing/block-step-computed.html new file mode 100644 index 00000000000..ea9a602d8ca --- /dev/null +++ b/tests/wpt/tests/css/css-rhythm/parsing/block-step-computed.html @@ -0,0 +1,60 @@ + + + +CSS Rhythm: block-step computed values + + + + + + + + +
+ + + diff --git a/tests/wpt/tests/css/css-rhythm/parsing/block-step-invalid.html b/tests/wpt/tests/css/css-rhythm/parsing/block-step-invalid.html new file mode 100644 index 00000000000..93961fad5b3 --- /dev/null +++ b/tests/wpt/tests/css/css-rhythm/parsing/block-step-invalid.html @@ -0,0 +1,23 @@ + + + +CSS Rhythm: block-step invalid values + + + + + + + + + + + diff --git a/tests/wpt/tests/css/css-rhythm/parsing/block-step-valid.html b/tests/wpt/tests/css/css-rhythm/parsing/block-step-valid.html new file mode 100644 index 00000000000..8a6fcc90edb --- /dev/null +++ b/tests/wpt/tests/css/css-rhythm/parsing/block-step-valid.html @@ -0,0 +1,59 @@ + + + +CSS Rhythm: block-step valid values + + + + + + + + + + + diff --git a/tests/wpt/tests/css/css-shadow-parts/pseudo-classes-after-part.html b/tests/wpt/tests/css/css-shadow-parts/pseudo-classes-after-part.html index 60292d27a71..873df771398 100644 --- a/tests/wpt/tests/css/css-shadow-parts/pseudo-classes-after-part.html +++ b/tests/wpt/tests/css/css-shadow-parts/pseudo-classes-after-part.html @@ -15,7 +15,6 @@ test_valid_selector("::part(mypart):active-view-transition-type(mytype)"); test_valid_selector("::part(mypart):any-link"); test_valid_selector("::part(mypart):autofill"); test_valid_selector("::part(mypart):checked"); -test_valid_selector("::part(mypart):closed"); test_valid_selector("::part(mypart):default"); test_valid_selector("::part(mypart):defined"); test_valid_selector("::part(mypart):dir(ltr)"); diff --git a/tests/wpt/tests/css/css-transitions/allow-discrete-auto-inset.html b/tests/wpt/tests/css/css-transitions/allow-discrete-auto-inset.html new file mode 100644 index 00000000000..d12264021eb --- /dev/null +++ b/tests/wpt/tests/css/css-transitions/allow-discrete-auto-inset.html @@ -0,0 +1,29 @@ + +CSS Transitions Test: discrete transition for auto inset + + + +

Test passes if there is a filled green square.

+
+
+
+ diff --git a/tests/wpt/tests/css/css-transitions/transition-behavior.html b/tests/wpt/tests/css/css-transitions/transition-behavior.html index fa24509a373..4c2ddb3c63b 100644 --- a/tests/wpt/tests/css/css-transitions/transition-behavior.html +++ b/tests/wpt/tests/css/css-transitions/transition-behavior.html @@ -4,10 +4,6 @@ - -
Allow discrete
-
No discrete
- - + +
Allow discrete
+
No discrete
+ + + + + + + + diff --git a/tests/wpt/tests/css/cssom/getComputedStyle-pseudo-picker-icon.html b/tests/wpt/tests/css/cssom/getComputedStyle-pseudo-picker-icon.html new file mode 100644 index 00000000000..dede199652c --- /dev/null +++ b/tests/wpt/tests/css/cssom/getComputedStyle-pseudo-picker-icon.html @@ -0,0 +1,46 @@ + + +CSSOM: Correct resolution of resolved value for the picker-icon pseudo-element + + + + + + + + + + + + + diff --git a/tests/wpt/tests/css/printing/huge-font-crash-print.html b/tests/wpt/tests/css/printing/huge-font-crash-print.html new file mode 100644 index 00000000000..6d58321b567 --- /dev/null +++ b/tests/wpt/tests/css/printing/huge-font-crash-print.html @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/tests/wpt/tests/css/selectors/invalidation/WEB_FEATURES.yml b/tests/wpt/tests/css/selectors/invalidation/WEB_FEATURES.yml index 33e80ad651e..860591654ac 100644 --- a/tests/wpt/tests/css/selectors/invalidation/WEB_FEATURES.yml +++ b/tests/wpt/tests/css/selectors/invalidation/WEB_FEATURES.yml @@ -13,3 +13,6 @@ features: - name: user-pseudos files: - user-valid-user-invalid.html +- name: state + files: + - state-in-has.html diff --git a/tests/wpt/tests/css/selectors/open-closed-pseudo.html b/tests/wpt/tests/css/selectors/open-pseudo.html similarity index 63% rename from tests/wpt/tests/css/selectors/open-closed-pseudo.html rename to tests/wpt/tests/css/selectors/open-pseudo.html index 9301fd2f416..0f3b9f3c379 100644 --- a/tests/wpt/tests/css/selectors/open-closed-pseudo.html +++ b/tests/wpt/tests/css/selectors/open-pseudo.html @@ -17,53 +17,39 @@ diff --git a/tests/wpt/tests/css/selectors/parsing/WEB_FEATURES.yml b/tests/wpt/tests/css/selectors/parsing/WEB_FEATURES.yml index 261019c003d..f3453b29162 100644 --- a/tests/wpt/tests/css/selectors/parsing/WEB_FEATURES.yml +++ b/tests/wpt/tests/css/selectors/parsing/WEB_FEATURES.yml @@ -6,3 +6,6 @@ features: files: - parse-has.html - parse-has-* +- name: state + files: + - parse-state.html diff --git a/tests/wpt/tests/custom-elements/state/WEB_FEATURES.yml b/tests/wpt/tests/custom-elements/state/WEB_FEATURES.yml new file mode 100644 index 00000000000..939658bfb16 --- /dev/null +++ b/tests/wpt/tests/custom-elements/state/WEB_FEATURES.yml @@ -0,0 +1,3 @@ +features: +- name: state + files: "**" diff --git a/tests/wpt/tests/editing/other/delete-selection-with-null-range-crash.html b/tests/wpt/tests/editing/other/delete-selection-with-null-range-crash.html new file mode 100644 index 00000000000..4d814eab807 --- /dev/null +++ b/tests/wpt/tests/editing/other/delete-selection-with-null-range-crash.html @@ -0,0 +1,37 @@ + + + This test crashes on Null-dereference READ in + blink::Range::StartPosition + + + +

This test should not crash.

+
diff --git a/tests/wpt/tests/fledge/tentative/private-aggregation.https.window.js b/tests/wpt/tests/fledge/tentative/private-aggregation.https.window.js new file mode 100644 index 00000000000..4386610abb3 --- /dev/null +++ b/tests/wpt/tests/fledge/tentative/private-aggregation.https.window.js @@ -0,0 +1,1065 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/utils.js +// META: script=resources/fledge-util.sub.js +// META: script=/common/subset-tests.js +// META: script=third_party/cbor-js/cbor.js +// META: timeout=long +// META: variant=?1-5 +// META: variant=?6-10 +// META: variant=?11-15 +// META: variant=?16-20 + +'use strict;' + +// To better isolate from private aggregation tests run in parallel, +// don't use the usual origin here. +const MAIN_ORIGIN = OTHER_ORIGIN1; +const ALT_ORIGIN = OTHER_ORIGIN4; + +const MAIN_PATH = '/.well-known/private-aggregation/report-protected-audience'; +const DEBUG_PATH = + '/.well-known/private-aggregation/debug/report-protected-audience'; + +const ADDITIONAL_BID_PUBLIC_KEY = + '11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo='; + +const enableDebugMode = 'privateAggregation.enableDebugMode();'; + +// The next 3 methods are for interfacing with the test handler for +// Private Aggregation reports; adopted wholesale from Chrome-specific +// wpt_internal/private-aggregation/resources/utils.js +const resetReports = url => { + url = `${url}?clear_stash=true`; + const options = { + method: 'POST', + mode: 'no-cors', + }; + return fetch(url, options); +}; + +const delay = ms => new Promise(resolve => step_timeout(resolve, ms)); + +async function pollReports(path, wait_for = 1, timeout = 5000 /*ms*/) { + const targetUrl = new URL(path, MAIN_ORIGIN); + const endTime = performance.now() + timeout; + const outReports = []; + + do { + const response = await fetch(targetUrl); + assert_true(response.ok, 'pollReports() fetch response should be OK.'); + const reports = await response.json(); + outReports.push(...reports); + if (outReports.length >= wait_for) { + break; + } + await delay(/*ms=*/ 100); + } while (performance.now() < endTime); + + return outReports.length ? outReports : null; +}; + +function decodeBase64(inStr) { + let strBytes = atob(inStr); + let arrBytes = new Uint8Array(strBytes.length); + for (let i = 0; i < strBytes.length; ++i) { + arrBytes[i] = strBytes.codePointAt(i); + } + return arrBytes.buffer; +} + +function byteArrayToBigInt(inArray) { + let out = 0n; + for (let byte of inArray) { + out = out * 256n + BigInt(byte); + } + return out; +} + +async function getDebugSamples(path) { + const debugReports = await pollReports(path); + + let samplesDict = new Map(); + + // Extract samples for debug reports, and aggregate them, so we are not + // reliant on how aggregation happens. + for (let jsonReport of debugReports) { + let report = JSON.parse(jsonReport); + for (let payload of report.aggregation_service_payloads) { + let decoded = CBOR.decode(decodeBase64(payload.debug_cleartext_payload)); + assert_equals(decoded.operation, 'histogram'); + for (let sample of decoded.data) { + let convertedSample = { + bucket: byteArrayToBigInt(sample.bucket), + value: byteArrayToBigInt(sample.value) + }; + if (convertedSample.value !== 0n) { + let oldCount = 0n; + if (samplesDict.has(convertedSample.bucket)) { + oldCount = samplesDict.get(convertedSample.bucket); + } + + samplesDict.set( + convertedSample.bucket, oldCount + convertedSample.value); + } + } + } + } + + return samplesDict; +} + +function stringifySamples(samplesDict) { + let samplesArray = []; + for (let [bucket, value] of samplesDict.entries()) { + // Stringify these so we can use assert_array_equals on them. + samplesArray.push(bucket + ' => ' + value); + } + samplesArray.sort(); + return samplesArray; +} + +function maybeDelay(delayParam) { + if (delayParam) { + return `&pipe=trickle(d${delayParam / 1000})` + } else { + return ''; + } +} + +function createIgOverrides(nameAndBid, fragments, originOverride = null) { + let originToUse = originOverride ? originOverride : MAIN_ORIGIN; + return { + name: nameAndBid, + biddingLogicURL: createBiddingScriptURL({ + origin: originToUse, + generateBid: + enableDebugMode + fragments.generateBidFragment, + reportWin: enableDebugMode + fragments.reportWinFragment, + bid: nameAndBid, + allowComponentAuction: true + }) + + maybeDelay(fragments.bidderDelayFactor ? + fragments.bidderDelayFactor * nameAndBid : + null) + }; +} + +function expectAndConsume(samplesDict, bucket, val) { + assert_equals(samplesDict.get(bucket), val, 'sample in bucket ' + bucket); + samplesDict.delete(bucket); +} + +function createAuctionConfigOverrides( + uuid, fragments, moreAuctionConfigOverrides = {}) { + return { + decisionLogicURL: + createDecisionScriptURL(uuid, { + origin: MAIN_ORIGIN, + scoreAd: enableDebugMode + fragments.scoreAdFragment, + reportResult: enableDebugMode + fragments.reportResultFragment + }) + + maybeDelay(fragments.sellerDelay), + seller: MAIN_ORIGIN, + interestGroupBuyers: [MAIN_ORIGIN], + ...moreAuctionConfigOverrides + }; +} + +// Runs an auction with numGroups interest groups, "1" and "2", etc., with +// fragments.generateBidFragment/fragments.reportWinFragment/ +// fragments.scoreAdFragment/fragments.reportResultFragment +// expected to make some Private Aggregation contributions. +// Returns the collected samples. +async function runPrivateAggregationTest( + test, uuid, fragments, numGroups = 2, moreAuctionConfigOverrides = {}) { + await resetReports(MAIN_ORIGIN + MAIN_PATH); + await resetReports(MAIN_ORIGIN + DEBUG_PATH); + + for (let i = 1; i <= numGroups; ++i) { + await joinCrossOriginInterestGroup( + test, uuid, MAIN_ORIGIN, createIgOverrides(i, fragments)); + } + + const auctionConfigOverrides = + createAuctionConfigOverrides(uuid, fragments, moreAuctionConfigOverrides); + + await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides); + return await getDebugSamples(DEBUG_PATH); +} + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogram({ bucket: 1n, value: 2 });`, + + reportWinFragment: + `privateAggregation.contributeToHistogram({ bucket: 2n, value: 3 });`, + + scoreAdFragment: + `privateAggregation.contributeToHistogram({ bucket: 3n, value: 4 });`, + + reportResultFragment: + `privateAggregation.contributeToHistogram({ bucket: 4n, value: 5 });` + }; + + const samples = await runPrivateAggregationTest(test, uuid, fragments); + assert_array_equals( + stringifySamples(samples), + [ + '1 => 4', // doubled since it's reported twice. + '2 => 3', + '3 => 8', // doubled since it's reported twice. + '4 => 5' + ]); +}, 'Basic contributions'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', + { bucket: 1n, value: 2 });`, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', + { bucket: 2n, value: 3 });`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', + { bucket: 3n, value: 4 });`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', + { bucket: 4n, value: 5 });` + }; + + const samples = await runPrivateAggregationTest(test, uuid, fragments); + assert_array_equals( + stringifySamples(samples), + [ + '1 => 4', // doubled since it's reported twice. + '2 => 3', + '3 => 8', // doubled since it's reported twice. + '4 => 5' + ]); +}, 'reserved.always'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.win', + { bucket: 1n, value: interestGroup.name });`, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.win', + { bucket: 2n, value: 3 });`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.win', + { bucket: 3n, value: bid });`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.win', + { bucket: 4n, value: 5 });` + }; + + const samples = await runPrivateAggregationTest(test, uuid, fragments); + assert_array_equals( + stringifySamples(samples), + [ + '1 => 2', // winning IG name + '2 => 3', + '3 => 2', // winning bid + '4 => 5' + ]); +}, 'reserved.win'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.loss', + { bucket: 1n, value: interestGroup.name });`, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.loss', + { bucket: 2n, value: 3 });`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.loss', + { bucket: 3n, value: bid });`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.loss', + { bucket: 4n, value: 5 });` + }; + + const samples = await runPrivateAggregationTest(test, uuid, fragments); + + // No reserved.loss from reporting since they only run for winners. + assert_array_equals( + stringifySamples(samples), + [ + '1 => 1', // losing IG name + '3 => 1', // losing bid + ]); +}, 'reserved.loss'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', + { bucket: 1n, value: interestGroup.name });`, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', + { bucket: 2n, value: 3 });`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', + { bucket: 3n, value: bid });`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', + { bucket: 4n, value: 5 });` + }; + + const samples = + stringifySamples(await runPrivateAggregationTest(test, uuid, fragments)); + + // No reserved.once from reporting since it throws an exception. + // bidder/scorer just pick one. + assert_equals(samples.length, 2, 'samples array length'); + assert_in_array(samples[0], ['1 => 1', '1 => 2'], 'samples[0]'); + assert_in_array(samples[1], ['3 => 1', '3 => 2'], 'samples[1]'); +}, 'reserved.once'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', + { bucket: 1n, value: 1 });`, + + reportWinFragment: ` + try { + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', + { bucket: 2n, value: 2 }); + } catch (e) { + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', + { bucket: 2n, value: (e instanceof TypeError ? 3 : 4) }); + }`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', + { bucket: 3n, value: 4 });`, + + reportResultFragment: ` + try { + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', + { bucket: 4n, value: 5 }); + } catch (e) { + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', + { bucket: 4n, value: (e instanceof TypeError ? 6 : 7) }); + }` + }; + + const samples = + stringifySamples(await runPrivateAggregationTest(test, uuid, fragments)); + + assert_array_equals(samples, [ + '1 => 1', + '2 => 3', + '3 => 4', + '4 => 6', + ]); +}, 'no reserved.once in reporting'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await resetReports(ALT_ORIGIN + DEBUG_PATH); + await resetReports(ALT_ORIGIN + MAIN_PATH); + + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: 'average-code-fetch-time', offset: 0n}, + value: 1});`, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: 'average-code-fetch-time', offset: 100000n}, + value: 1});`, + + bidderDelayFactor: 200, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: 'average-code-fetch-time', offset: 200000n}, + value: 1});`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: 'average-code-fetch-time', offset: 300000n}, + value: 1});`, + + sellerDelay: 500 + }; + + const altFragments = { + generateBidFragment: fragments.generateBidFragment, + bidderDelayFactor: 1000 + }; + + await joinCrossOriginInterestGroup( + test, uuid, ALT_ORIGIN, createIgOverrides('1', altFragments, ALT_ORIGIN)); + const auctionConfigOverrides = { + interestGroupBuyers: [MAIN_ORIGIN, ALT_ORIGIN] + }; + + const samples = await runPrivateAggregationTest( + test, uuid, fragments, 3, auctionConfigOverrides); + + let generateBidVal = -1; + let reportWinVal = -1; + let scoreAdVal = -1; + let reportResultVal = -1; + assert_equals(samples.size, 4, 'main domain samples'); + + for (let [bucket, val] of samples.entries()) { + assert_equals(val, 1n, 'bucket val'); + if (0n <= bucket && bucket < 100000n) { + generateBidVal = Number(bucket - 0n); + } else if (100000n <= bucket && bucket < 200000n) { + reportWinVal = Number(bucket - 100000n); + } else if (200000n <= bucket && bucket < 300000n) { + scoreAdVal = Number(bucket - 200000n); + } else if (300000n <= bucket && bucket < 400000n) { + reportResultVal = Number(bucket - 300000n); + } else { + assert_unreached('Unexpected bucket number ' + bucket); + } + } + + assert_greater_than_equal(generateBidVal, 400, 'generateBid code fetch time'); + assert_greater_than_equal(reportWinVal, 600, 'reportWin code fetch time'); + assert_greater_than_equal(scoreAdVal, 500, 'scoreAd code fetch time'); + assert_greater_than_equal( + reportResultVal, 500, 'reportResult code fetch time'); + + let otherSamples = await getDebugSamples(ALT_ORIGIN + DEBUG_PATH); + assert_equals(otherSamples.size, 1, 'alt domain samples'); + let otherGenerateBidVal = -1; + for (let [bucket, val] of otherSamples.entries()) { + assert_equals(val, 1n, 'other bucket val'); + if (0n <= bucket && bucket < 100000n) { + otherGenerateBidVal = Number(bucket - 0n); + } else { + assert_unreached('Unexpected other bucket number ' + bucket); + } + } + assert_greater_than_equal( + otherGenerateBidVal, 1000, 'other generateBid code fetch time'); +}, 'average-code-fetch-time'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: 'percent-scripts-timeout', offset: 0n}, + value: 1}); + if (interestGroup.name === '1') { + while (true) {} + } + `, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: 'percent-scripts-timeout', offset: 200n}, + value: 1}); + while(true) {}`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: 'percent-scripts-timeout', offset: 400n}, + value: 1}); + if (bid == 2) { + while (true) {} + } + `, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: 'percent-scripts-timeout', offset: 600n}, + value: 1});` + }; + + const samples = await runPrivateAggregationTest(test, uuid, fragments, 3); + + let expected = [ + '33 => 1', // 33% of generateBid (base bucket 0) + '300 => 1', // 100% of reportWin (base bucket 200) + '450 => 1', // 50% of scoreAd (base bucket 400) + '600 => 1', // 0% of reportResult (base bucket 600) + ].sort(); + + assert_array_equals(stringifySamples(samples), expected); +}, 'percent-scripts-timeout'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await resetReports(ALT_ORIGIN + DEBUG_PATH); + await resetReports(ALT_ORIGIN + MAIN_PATH); + + const ADDITIONAL_BID_PUBLIC_KEY = + '11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo='; + + // Join a negative group, one without ads. + // These shouldn't count towards participant number. + await joinNegativeInterestGroup( + test, MAIN_ORIGIN, 'some negative group', ADDITIONAL_BID_PUBLIC_KEY); + await joinCrossOriginInterestGroup(test, uuid, MAIN_ORIGIN, {ads: []}); + + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: 'participating-ig-count', offset: 0n}, + value: 1});`, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: 'participating-ig-count', offset: 200n}, + value: 1});`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: 'participating-ig-count', offset: 400n}, + value: 1});`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: 'participating-ig-count', offset: 600n}, + value: 1});` + }; + + // ... and a different participant should get their own samples. + await joinCrossOriginInterestGroup( + test, uuid, ALT_ORIGIN, createIgOverrides('1', fragments, ALT_ORIGIN)); + await joinCrossOriginInterestGroup( + test, uuid, ALT_ORIGIN, createIgOverrides('2', fragments, ALT_ORIGIN)); + const auctionConfigOverrides = { + interestGroupBuyers: [MAIN_ORIGIN, ALT_ORIGIN] + }; + + const samples = await runPrivateAggregationTest( + test, uuid, fragments, 5, auctionConfigOverrides); + + let expected = [ + '5 => 1', // 5 in generateBid (base bucket 0) + '205 => 1', // 5 in reportWin (base bucket 200) + '400 => 1', // 0 in scoreAd (base bucket 400) + '600 => 1', // 0 in reportResult (base bucket 600) + ].sort(); + + assert_array_equals(stringifySamples(samples), expected); + + let otherSamples = await getDebugSamples(ALT_ORIGIN + DEBUG_PATH); + assert_array_equals(stringifySamples(otherSamples), ['2 => 1']); +}, 'participating-ig-count'); + + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: { + baseValue: 'percent-igs-cumulative-timeout', + offset: 0n + }, + value: 1}); + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: { + baseValue: 'cumulative-buyer-time', + offset: 10000n + }, + value: 1}); + setBid({bid: interestGroup.name, render: interestGroup.ads[0].renderURL}); + while (true) {} + `, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: { + baseValue: 'percent-igs-cumulative-timeout', + offset: 200n + }, + value: 1}); + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: { + baseValue: 'cumulative-buyer-time', + offset: 20000n + }, + value: 1}); + `, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: { + baseValue: 'percent-igs-cumulative-timeout', + offset: 400n + }, + value: 1}); + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: { + baseValue: 'cumulative-buyer-time', + offset: 40000n + }, + value: 1}); + `, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: { + baseValue: 'percent-igs-cumulative-timeout', + offset: 600n + }, + value: 1}); + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: { + baseValue: 'cumulative-buyer-time', + offset: 60000n + }, + value: 1});` + }; + + const auctionConfigOverrides = { + perBuyerTimeouts: { + '*': 500 // max. + }, + perBuyerCumulativeTimeouts: {'*': 2000} + }; + + const samples = await runPrivateAggregationTest( + test, uuid, fragments, 15, auctionConfigOverrides); + + // Timeout is reported as 3000 (limit + 1000) for generateBid + // and reportWin, as 0 for the seller methods. + expectAndConsume(samples, 13000n, 1n); // base is 10,000 + expectAndConsume(samples, 23000n, 1n); + expectAndConsume(samples, 40000n, 1n); + expectAndConsume(samples, 60000n, 1n); + + // percent time is 0 on the seller side. + expectAndConsume(samples, 400n, 1n); + expectAndConsume(samples, 600n, 1n); + + assert_equals(samples.size, 2, 'buyer samples'); + + let percentGenerateBid = -1; + let percentReportWin = -1; + + for (let [bucket, val] of samples.entries()) { + assert_equals(val, 1n, 'bucket val'); + if (0n <= bucket && bucket <= 110n) { + percentGenerateBid = bucket; + } else if (200n <= bucket && bucket <= 310n) { + percentReportWin = bucket - 200n; + } else { + assert_unreached('Unexpected bucket number ' + bucket); + } + } + + assert_equals( + percentGenerateBid, percentReportWin, + 'same % in generateBid and reportWin'); + + // This assumes that at least some time out; which may not be guaranteed with + // sufficient level of parallelism. At any rate, the denominator is 15, + // however, so only some percentages are possible. + assert_in_array( + percentGenerateBid, + [6n, 13n, 20n, 26n, 33n, 40n, 46n, 53n, 60n, 66n, 73n, 80n, 86n, 93n], + 'percent timeout is as expected'); +}, 'percent-igs-cumulative-timeout, and cumulative-buyer-time when hit'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: 'cumulative-buyer-time', offset: 0n}, + value: 1});`, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: 'cumulative-buyer-time', offset: 200n}, + value: 1});`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: 'cumulative-buyer-time', offset: 400n}, + value: 1});`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: 'cumulative-buyer-time', offset: 600n}, + value: 1});` + }; + + const samples = await runPrivateAggregationTest(test, uuid, fragments, 5); + + // 0s for all the bases. + let expected = ['0 => 1', '200 => 1', '400 => 1', '600 => 1'].sort(); + + assert_array_equals(stringifySamples(samples), expected); +}, 'cumulative-buyer-time when not configured'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: 'cumulative-buyer-time', offset: 0n}, + value: 1});`, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: 'cumulative-buyer-time', offset: 10000n}, + value: 1});`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: 'cumulative-buyer-time', offset: 20000n}, + value: 1});`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: 'cumulative-buyer-time', offset: 30000n}, + value: 1});` + }; + + const auctionConfigOverrides = {perBuyerCumulativeTimeouts: {'*': 4000}}; + + const samples = await runPrivateAggregationTest( + test, uuid, fragments, 5, auctionConfigOverrides); + + // Sellers stuff is just 0s (so 1 to the base bucket offset). + expectAndConsume(samples, 20000n, 1n); + expectAndConsume(samples, 30000n, 1n); + + assert_equals(samples.size, 2, 'buyer samples'); + + let timeGenerateBid = -1; + let timeReportWin = -1; + + for (let [bucket, val] of samples.entries()) { + assert_equals(val, 1n, 'bucket val'); + if (0n <= bucket && bucket <= 5000n) { + timeGenerateBid = bucket; + } else if (10000n <= bucket && bucket <= 15000n) { + timeReportWin = bucket - 10000n; + } else { + assert_unreached('Unexpected bucket number'); + } + } + + assert_equals( + timeGenerateBid, timeReportWin, 'same time in generateBid and reportWin'); + + // This assume this takes more than 0ms to run; it's not really required to + // be the case, but feels like a realistic assumption that makes the test + // more useful. + assert_true( + 1n <= timeGenerateBid && timeGenerateBid <= 4000n, + 'time ' + timeGenerateBid + ' is reasonable and non-zero'); +}, 'cumulative-buyer-time when configured'); + + +async function testStorageQuotaMetric(test, name) { + const uuid = generateUuid(test); + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: '${name}', offset: 0n}, + value: 1});`, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: '${name}', offset: 10000n}, + value: 1});`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: '${name}', offset: 20000n}, + value: 1});`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: '${name}', offset: 30000n}, + value: 1});` + }; + + const samples = await runPrivateAggregationTest(test, uuid, fragments, 5); + + // Sellers stuff is just 0s (so 1 to the base bucket offset). + expectAndConsume(samples, 20000n, 1n); + expectAndConsume(samples, 30000n, 1n); + + assert_equals(samples.size, 2, 'buyer samples'); + + let generateBidVal = -1; + let reportWinVal = -1; + + for (let [bucket, val] of samples.entries()) { + assert_equals(val, 1n, 'bucket val'); + if (0n <= bucket && bucket < 10000n) { + generateBidVal = Number(bucket); + } else if (10000n <= bucket && bucket <= 20000n) { + reportWinVal = Number(bucket - 10000n); + } else { + assert_unreached('Unexpected bucket number ' + bucket); + } + } + + assert_equals( + generateBidVal, reportWinVal, 'same value in generateBid and reportWin'); + + // We don't know what the impls quota is, or even how much we are using, + // but at least make sure it's in range. + assert_between_inclusive( + generateBidVal, 0, 110, 'reported percent value is in expected range'); +} + +subsetTest(promise_test, async test => { + await testStorageQuotaMetric(test, 'percent-regular-ig-count-quota-used'); +}, 'percent-regular-ig-count-quota-used'); + +subsetTest(promise_test, async test => { + await testStorageQuotaMetric(test, 'percent-negative-ig-count-quota-used'); +}, 'percent-negative-ig-count-quota-used'); + +subsetTest(promise_test, async test => { + await testStorageQuotaMetric(test, 'percent-ig-storage-quota-used'); +}, 'percent-ig-storage-quota-used'); + + +async function testStorageUsageMetric(test, name, min) { + const uuid = generateUuid(test); + const spacing = 1000000000n; + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: '${name}', offset: 0n}, + value: 1});`, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: '${name}', offset: ${spacing}n}, + value: 1});`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', { + bucket: {baseValue: '${name}', offset: 2n * ${spacing}n}, + value: 1});`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', { + bucket: {baseValue: '${name}', offset: 3n * ${spacing}n}, + value: 1});` + }; + + await joinNegativeInterestGroup( + test, MAIN_ORIGIN, 'some negative group', ADDITIONAL_BID_PUBLIC_KEY); + await joinNegativeInterestGroup( + test, MAIN_ORIGIN, 'some negative group 2', ADDITIONAL_BID_PUBLIC_KEY); + await joinCrossOriginInterestGroup( + test, uuid, MAIN_ORIGIN, + {ads: [], name: 'Big group w/o ads'.padEnd(50000)}); + + const samples = await runPrivateAggregationTest(test, uuid, fragments, 5); + + // Sellers stuff is just 0s (so 1 to the base bucket offset). + expectAndConsume(samples, 2n * spacing, 1n); + expectAndConsume(samples, 3n * spacing, 1n); + + assert_equals(samples.size, 2, 'buyer samples'); + + let generateBidVal = -1; + let reportWinVal = -1; + + for (let [bucket, val] of samples.entries()) { + assert_equals(val, 1n, 'bucket val'); + if (0n <= bucket && bucket < spacing) { + generateBidVal = bucket; + } else if (spacing <= bucket && bucket < 2n * spacing) { + reportWinVal = bucket - spacing; + } else { + assert_unreached('Unexpected bucket number ' + bucket); + } + } + + assert_equals( + generateBidVal, reportWinVal, 'same value in generateBid and reportWin'); + + assert_true( + generateBidVal >= BigInt(min), + 'reported value should be at least ' + min + ' but is ' + generateBidVal); +} + +subsetTest(promise_test, async test => { + // 5 regular Igs + one ad less. + await testStorageUsageMetric(test, 'regular-igs-count', 6); +}, 'regular-igs-count'); + +subsetTest(promise_test, async test => { + // 2 negative IGs + await testStorageUsageMetric(test, 'negative-igs-count', 2); +}, 'negative-igs-count'); + +subsetTest(promise_test, async test => { + // The big group has a 50,000 character name + await testStorageUsageMetric(test, 'ig-storage-used', 50000); +}, 'ig-storage-used'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await resetReports(MAIN_ORIGIN + MAIN_PATH); + await resetReports(MAIN_ORIGIN + DEBUG_PATH); + await resetReports(ALT_ORIGIN + MAIN_PATH); + await resetReports(ALT_ORIGIN + DEBUG_PATH); + + const fragments = { + generateBidFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', + { bucket: 1n, value: 2 });`, + + reportWinFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', + { bucket: 2n, value: 3 });`, + + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', + { bucket: 3n, value: 4 });`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', + { bucket: 4n, value: 5 });` + }; + + // 4 IGs in main origin, 2 in alt origin. + for (let i = 1; i <= 4; ++i) { + await joinCrossOriginInterestGroup( + test, uuid, MAIN_ORIGIN, createIgOverrides(i, fragments)); + } + + for (let i = 1; i <= 2; ++i) { + await joinCrossOriginInterestGroup( + test, uuid, ALT_ORIGIN, createIgOverrides(i, fragments, ALT_ORIGIN)); + } + + // Both groups in component auction 1, only alt group in component auction 2. + const subAuction1 = createAuctionConfigOverrides( + uuid, fragments, {interestGroupBuyers: [MAIN_ORIGIN, ALT_ORIGIN]}); + const subAuction2 = createAuctionConfigOverrides( + uuid, fragments, {interestGroupBuyers: [ALT_ORIGIN]}); + + const topFragments = { + scoreAdFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.once', + { bucket: 5n, value: 6 });`, + + reportResultFragment: ` + privateAggregation.contributeToHistogramOnEvent( + 'reserved.always', + { bucket: 6n, value: 7 });` + }; + const mainAuction = createAuctionConfigOverrides( + uuid, topFragments, + {interestGroupBuyers: [], componentAuctions: [subAuction1, subAuction2]}); + + await runBasicFledgeAuctionAndNavigate(test, uuid, mainAuction); + let samples = await getDebugSamples(DEBUG_PATH); + let otherSamples = await getDebugSamples(ALT_ORIGIN + DEBUG_PATH); + let expected = [ + '1 => 2', // generateBid only in first component, so happens 1. + '2 => 3', // reportWin once. + '3 => 8', // Once per each component auction (out of total 6 scored). + '4 => 5', // component reportResult once. + '5 => 6', // top-level scoreAd once. + '6 => 7', // top-level reportResult. + ].sort(); + let otherExpected = [ + '1 => 4', // generateBid in each components, so twice, out of 4 executions. + ].sort(); + assert_array_equals(stringifySamples(samples), expected); + assert_array_equals(stringifySamples(otherSamples), otherExpected); +}, 'report.once in a component auction'); diff --git a/tests/wpt/tests/fledge/tentative/resources/fledge-util.sub.js b/tests/wpt/tests/fledge/tentative/resources/fledge-util.sub.js index 8e387588aa9..a209adbf2f3 100644 --- a/tests/wpt/tests/fledge/tentative/resources/fledge-util.sub.js +++ b/tests/wpt/tests/fledge/tentative/resources/fledge-util.sub.js @@ -328,7 +328,7 @@ async function joinNegativeInterestGroup( `await joinInterestGroupWithoutDefaults(` + `test_instance, ${JSON.stringify(interestGroup)})`); } else { - await joinInterestGroupWithoutDefaults(test_instance, interestGroup); + await joinInterestGroupWithoutDefaults(test, interestGroup); } } diff --git a/tests/wpt/tests/html/canvas/element/manual/layers/unclosed-layers.html b/tests/wpt/tests/html/canvas/element/manual/layers/unclosed-layers.html index afb53cfbebc..1e6f4797107 100644 --- a/tests/wpt/tests/html/canvas/element/manual/layers/unclosed-layers.html +++ b/tests/wpt/tests/html/canvas/element/manual/layers/unclosed-layers.html @@ -13,7 +13,7 @@ ctx.fillStyle = 'purple'; ctx.fillRect(60, 60, 75, 50); - ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}}); + ctx.beginLayer(); ctx.fillRect(40, 40, 75, 50); ctx.fillStyle = 'grey'; ctx.fillRect(50, 50, 75, 50); diff --git a/tests/wpt/tests/html/canvas/element/text/2d.text.measure.actualBoundingBox.whitespace.html b/tests/wpt/tests/html/canvas/element/text/2d.text.measure.actualBoundingBox.whitespace.html new file mode 100644 index 00000000000..1e389a19264 --- /dev/null +++ b/tests/wpt/tests/html/canvas/element/text/2d.text.measure.actualBoundingBox.whitespace.html @@ -0,0 +1,54 @@ + + + +Canvas test: 2d.text.measure.actualBoundingBox.whitespace + + + + + + + +

2d.text.measure.actualBoundingBox.whitespace

+

Testing actualBoundingBox with leading/trailing whitespace

+ + +A +

Actual output:

+

FAIL (fallback content)

+ +
    + + diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/layers/unclosed-layers.html b/tests/wpt/tests/html/canvas/offscreen/manual/layers/unclosed-layers.html index 4fee600d6cb..715a39080cb 100644 --- a/tests/wpt/tests/html/canvas/offscreen/manual/layers/unclosed-layers.html +++ b/tests/wpt/tests/html/canvas/offscreen/manual/layers/unclosed-layers.html @@ -16,7 +16,7 @@ ctx.fillStyle = 'purple'; ctx.fillRect(60, 60, 75, 50); - ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}}); + ctx.beginLayer(); ctx.fillRect(40, 40, 75, 50); ctx.fillStyle = 'grey'; ctx.fillRect(50, 50, 75, 50); diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/layers/unclosed-layers.w.html b/tests/wpt/tests/html/canvas/offscreen/manual/layers/unclosed-layers.w.html index a0014bb5976..df810398b77 100644 --- a/tests/wpt/tests/html/canvas/offscreen/manual/layers/unclosed-layers.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/manual/layers/unclosed-layers.w.html @@ -16,7 +16,7 @@ ctx.fillStyle = 'purple'; ctx.fillRect(60, 60, 75, 50); - ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}}); + ctx.beginLayer(); ctx.fillRect(40, 40, 75, 50); ctx.fillStyle = 'grey'; ctx.fillRect(50, 50, 75, 50); diff --git a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.measure.actualBoundingBox.whitespace.html b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.measure.actualBoundingBox.whitespace.html new file mode 100644 index 00000000000..5895e6360a0 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.measure.actualBoundingBox.whitespace.html @@ -0,0 +1,43 @@ + + + +OffscreenCanvas test: 2d.text.measure.actualBoundingBox.whitespace + + + + +

    2d.text.measure.actualBoundingBox.whitespace

    +

    Testing actualBoundingBox with leading/trailing whitespace

    + + + diff --git a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.measure.actualBoundingBox.whitespace.worker.js b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.measure.actualBoundingBox.whitespace.worker.js new file mode 100644 index 00000000000..e3b74443e42 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.measure.actualBoundingBox.whitespace.worker.js @@ -0,0 +1,36 @@ +// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. +// OffscreenCanvas test in a worker:2d.text.measure.actualBoundingBox.whitespace +// Description:Testing actualBoundingBox with leading/trailing whitespace +// Note: + +importScripts("/resources/testharness.js"); +importScripts("/html/canvas/resources/canvas-tests.js"); + +promise_test(async t => { + var canvas = new OffscreenCanvas(100, 50); + var ctx = canvas.getContext('2d'); + + var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')"); + f.load(); + self.fonts.add(f); + await self.fonts.ready; + ctx.font = '50px CanvasTest'; + ctx.direction = 'ltr'; + ctx.align = 'left' + ctx.baseline = 'alphabetic' + // Different platforms may render text slightly different. + // Values that are nominally expected to be zero might actually vary by a + // pixel or so if the UA accounts for antialiasing at glyph edges, so we + // allow a slight deviation. + var whitespaces = [0x9, 0xa, 0xc, 0xd, 0x20, 0x3000]; + for (var codepoint of whitespaces) { + let whitespace = String.fromCharCode(codepoint); + + _assert(Math.abs(ctx.measureText('A' + whitespace).actualBoundingBoxLeft) <= 1, "Math.abs(ctx.measureText('A' + whitespace).actualBoundingBoxLeft) <= 1"); + _assert(ctx.measureText('A' + whitespace).actualBoundingBoxRight >= 50, "ctx.measureText('A' + whitespace).actualBoundingBoxRight >= 50"); + + _assert(Math.abs(ctx.measureText(whitespace + 'A').actualBoundingBoxLeft) >= 49, "Math.abs(ctx.measureText(whitespace + 'A').actualBoundingBoxLeft) >= 49"); + _assert(ctx.measureText(whitespace + 'A').actualBoundingBoxRight <= 101, "ctx.measureText(whitespace + 'A').actualBoundingBoxRight <= 101"); + } +}, "Testing actualBoundingBox with leading/trailing whitespace"); +done(); diff --git a/tests/wpt/tests/html/canvas/tools/yaml-new/text.yaml b/tests/wpt/tests/html/canvas/tools/yaml-new/text.yaml index 7fe59a91a35..38630509bf2 100644 --- a/tests/wpt/tests/html/canvas/tools/yaml-new/text.yaml +++ b/tests/wpt/tests/html/canvas/tools/yaml-new/text.yaml @@ -1082,6 +1082,34 @@ variants: - *load-font-variant-definition +- name: 2d.text.measure.actualBoundingBox.whitespace + desc: Testing actualBoundingBox with leading/trailing whitespace + test_type: promise + fonts: + - CanvasTest + code: | + {{ load_font }} + ctx.font = '50px CanvasTest'; + ctx.direction = 'ltr'; + ctx.align = 'left' + ctx.baseline = 'alphabetic' + // Different platforms may render text slightly different. + // Values that are nominally expected to be zero might actually vary by a + // pixel or so if the UA accounts for antialiasing at glyph edges, so we + // allow a slight deviation. + var whitespaces = [0x9, 0xa, 0xc, 0xd, 0x20, 0x3000]; + for (var codepoint of whitespaces) { + let whitespace = String.fromCharCode(codepoint); + + @assert Math.abs(ctx.measureText('A' + whitespace).actualBoundingBoxLeft) <= 1; + @assert ctx.measureText('A' + whitespace).actualBoundingBoxRight >= 50; + + @assert Math.abs(ctx.measureText(whitespace + 'A').actualBoundingBoxLeft) >= 49; + @assert ctx.measureText(whitespace + 'A').actualBoundingBoxRight <= 101; + } + variants: + - *load-font-variant-definition + - name: 2d.text.measure.fontBoundingBox desc: Testing fontBoundingBox measurements test_type: promise diff --git a/tests/wpt/tests/html/dom/elements/the-innertext-and-outertext-properties/getter-tests.js b/tests/wpt/tests/html/dom/elements/the-innertext-and-outertext-properties/getter-tests.js index d3eca406fd8..d9b5b063732 100644 --- a/tests/wpt/tests/html/dom/elements/the-innertext-and-outertext-properties/getter-tests.js +++ b/tests/wpt/tests/html/dom/elements/the-innertext-and-outertext-properties/getter-tests.js @@ -100,6 +100,7 @@ testText("
    Hello
    K /**** first-line/first-letter ****/ +testText("
    abc", "ABC", "::first-line styles applied"); testText("
    abc def", "ABC def", "::first-line styles applied"); testText("
    abc def", "Abc def", "::first-letter styles applied"); testText("
    abc def", "abc def", "::first-letter float ignored"); diff --git a/tests/wpt/tests/html/semantics/forms/the-select-element/select-pseudo-light-dismiss-invalidation.tentative.html b/tests/wpt/tests/html/semantics/forms/the-select-element/select-pseudo-light-dismiss-invalidation.tentative.html index c9631d92e12..749fd8cf275 100644 --- a/tests/wpt/tests/html/semantics/forms/the-select-element/select-pseudo-light-dismiss-invalidation.tentative.html +++ b/tests/wpt/tests/html/semantics/forms/the-select-element/select-pseudo-light-dismiss-invalidation.tentative.html @@ -14,7 +14,7 @@ select { background-color: rgb(0, 0, 255); } -select:closed { +select:not(:open) { background-color: rgb(0, 255, 0); } select:open { @@ -29,7 +29,7 @@ select, ::picker(select) { diff --git a/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/WEB_FEATURES.yml b/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/WEB_FEATURES.yml index f270236cff5..bf15e99b65b 100644 --- a/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/WEB_FEATURES.yml +++ b/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/WEB_FEATURES.yml @@ -1,3 +1,7 @@ features: - name: dialog files: "**" +- name: closewatcher + files: + - "dialog-cancel-events.html" + - "dialog-canceling.html" diff --git a/tests/wpt/tests/html/semantics/popovers/WEB_FEATURES.yml b/tests/wpt/tests/html/semantics/popovers/WEB_FEATURES.yml index e1b9f82de37..c1175ff23c5 100644 --- a/tests/wpt/tests/html/semantics/popovers/WEB_FEATURES.yml +++ b/tests/wpt/tests/html/semantics/popovers/WEB_FEATURES.yml @@ -1,3 +1,6 @@ features: - name: popover files: "**" +- name: closewatcher + files: + - "popover-close-request.html" diff --git a/tests/wpt/tests/inert/inert-form-control.html b/tests/wpt/tests/inert/inert-form-control.html new file mode 100644 index 00000000000..b8d17d2b0d0 --- /dev/null +++ b/tests/wpt/tests/inert/inert-form-control.html @@ -0,0 +1,34 @@ + + + + + + + + +Inert doesn't prevent initiated click from changing form control + +
    + + +
    + diff --git a/tests/wpt/tests/interfaces/gpc.idl b/tests/wpt/tests/interfaces/gpc.idl new file mode 100644 index 00000000000..9a16904ce1e --- /dev/null +++ b/tests/wpt/tests/interfaces/gpc.idl @@ -0,0 +1,10 @@ +// GENERATED CONTENT - DO NOT EDIT +// Content was automatically extracted by Reffy into webref +// (https://github.com/w3c/webref) +// Source: Global Privacy Control (GPC) (https://w3c.github.io/gpc/) + +interface mixin GlobalPrivacyControl { + readonly attribute boolean globalPrivacyControl; +}; +Navigator includes GlobalPrivacyControl; +WorkerNavigator includes GlobalPrivacyControl; diff --git a/tests/wpt/tests/interfaces/mediacapture-surface-control.idl b/tests/wpt/tests/interfaces/mediacapture-surface-control.idl new file mode 100644 index 00000000000..b0bbd22304f --- /dev/null +++ b/tests/wpt/tests/interfaces/mediacapture-surface-control.idl @@ -0,0 +1,16 @@ +// GENERATED CONTENT - DO NOT EDIT +// Content was automatically extracted by Reffy into webref +// (https://github.com/w3c/webref) +// Source: Captured Surface Control (https://w3c.github.io/mediacapture-surface-control/) + +partial interface CaptureController { + sequence getSupportedZoomLevels(); + long getZoomLevel(); + Promise setZoomLevel(long zoomLevel); + attribute EventHandler oncapturedzoomlevelchange; +}; + +partial interface CaptureController { + constructor(); + Promise forwardWheel(HTMLElement element); +}; diff --git a/tests/wpt/tests/interfaces/sanitizer-api.idl b/tests/wpt/tests/interfaces/sanitizer-api.idl index 8f5c667973a..47c6d12fab0 100644 --- a/tests/wpt/tests/interfaces/sanitizer-api.idl +++ b/tests/wpt/tests/interfaces/sanitizer-api.idl @@ -9,9 +9,22 @@ dictionary SetHTMLOptions { [Exposed=(Window,Worker)] interface Sanitizer { - constructor(optional SanitizerConfig config = {}); + constructor(optional SanitizerConfig configuration = {}); + + // Query configuration: SanitizerConfig get(); - SanitizerConfig getUnsafe(); + + // Modify a Sanitizer’s lists and fields: + undefined allowElement(SanitizerElementWithAttributes element); + undefined removeElement(SanitizerElement element); + undefined replaceElementWithChildren(SanitizerElement element); + undefined allowAttribute(SanitizerAttribute attribute); + undefined removeAttribute(SanitizerAttribute attribute); + undefined setComments(boolean allow); + undefined setDataAttributes(boolean allow); + + // Remove markup that executes script. May modify multiple lists: + undefined removeUnsafe(); }; dictionary SanitizerElementNamespace { diff --git a/tests/wpt/tests/interfaces/vibration.idl b/tests/wpt/tests/interfaces/vibration.idl index 22ab1c47df0..175d240d10d 100644 --- a/tests/wpt/tests/interfaces/vibration.idl +++ b/tests/wpt/tests/interfaces/vibration.idl @@ -1,7 +1,7 @@ // GENERATED CONTENT - DO NOT EDIT // Content was automatically extracted by Reffy into webref // (https://github.com/w3c/webref) -// Source: Vibration API (Second Edition) (https://w3c.github.io/vibration/) +// Source: Vibration API (https://w3c.github.io/vibration/) typedef (unsigned long or sequence) VibratePattern; diff --git a/tests/wpt/tests/interfaces/webnn.idl b/tests/wpt/tests/interfaces/webnn.idl index 9f17b6ceb71..132280b05f8 100644 --- a/tests/wpt/tests/interfaces/webnn.idl +++ b/tests/wpt/tests/interfaces/webnn.idl @@ -32,19 +32,10 @@ interface ML { Promise createContext(GPUDevice gpuDevice); }; -typedef record MLNamedArrayBufferViews; typedef record MLNamedTensors; -dictionary MLComputeResult { - MLNamedArrayBufferViews inputs; - MLNamedArrayBufferViews outputs; -}; - [SecureContext, Exposed=(Window, DedicatedWorker)] interface MLContext { - // ISSUE(791): compute() will soon be removed in favor of dispatch(). - Promise compute( - MLGraph graph, MLNamedArrayBufferViews inputs, MLNamedArrayBufferViews outputs); undefined dispatch(MLGraph graph, MLNamedTensors inputs, MLNamedTensors outputs); Promise createTensor(MLTensorDescriptor descriptor); @@ -141,7 +132,8 @@ interface MLGraphBuilder { MLOperand input(USVString name, MLOperandDescriptor descriptor); // Create an operand for a graph constant. - MLOperand constant(MLOperandDescriptor descriptor, ArrayBufferView bufferView); + MLOperand constant(MLOperandDescriptor descriptor, + AllowSharedBufferSource buffer); // Create a scalar operand from the specified number of the specified type. MLOperand constant(MLOperandDataType type, MLNumber value); diff --git a/tests/wpt/tests/navigation-api/navigation-history-entry/entries-after-blob-navigation.html b/tests/wpt/tests/navigation-api/navigation-history-entry/entries-after-blob-navigation.html index 67611f4d446..0ad2b059697 100644 --- a/tests/wpt/tests/navigation-api/navigation-history-entry/entries-after-blob-navigation.html +++ b/tests/wpt/tests/navigation-api/navigation-history-entry/entries-after-blob-navigation.html @@ -19,7 +19,7 @@ async_test(t => { assert_true(isUUID(entries[1].key)); assert_true(isUUID(entries[1].id)); }); - i.src = URL.createObjectURL(new Blob([""])); + i.src = URL.createObjectURL(new Blob([""], { type: "text/html" })); }); }, "entries() after navigation to a blob: URL"); diff --git a/tests/wpt/tests/pointerlock/pointerlock_promise.html b/tests/wpt/tests/pointerlock/pointerlock_promise.html new file mode 100644 index 00000000000..81cdb784959 --- /dev/null +++ b/tests/wpt/tests/pointerlock/pointerlock_promise.html @@ -0,0 +1,37 @@ + + + + + + + + + + + +

    Description

    +

    This test validates that pointer lock returns a Promise.

    +
    + + + +
    Target
    + + + + diff --git a/tests/wpt/tests/pointerlock/pointerlock_unadjustedMovement.html b/tests/wpt/tests/pointerlock/pointerlock_unadjustedMovement.html new file mode 100644 index 00000000000..691f16f61fd --- /dev/null +++ b/tests/wpt/tests/pointerlock/pointerlock_unadjustedMovement.html @@ -0,0 +1,42 @@ + + + + + + + + + + +

    Description

    +

    This test validates that pointer lock accepts the unadjustedMovement option.

    +
    + + +
    Target
    + + + + diff --git a/tests/wpt/tests/pointerlock/pointerlock_without_gesture.html b/tests/wpt/tests/pointerlock/pointerlock_without_gesture.html new file mode 100644 index 00000000000..37245061c79 --- /dev/null +++ b/tests/wpt/tests/pointerlock/pointerlock_without_gesture.html @@ -0,0 +1,34 @@ + + + + + + + + + + + +

    Description

    +

    This test validates that pointer lock does not work without user activation.

    +
    + +
    Target
    + + + + diff --git a/tests/wpt/tests/reporting/resources/comment.js b/tests/wpt/tests/reporting/resources/comment.js new file mode 100644 index 00000000000..7fa15a06da7 --- /dev/null +++ b/tests/wpt/tests/reporting/resources/comment.js @@ -0,0 +1 @@ +// Ceci n'est pas un commentaire diff --git a/tests/wpt/tests/reporting/resources/comment.js.headers b/tests/wpt/tests/reporting/resources/comment.js.headers new file mode 100644 index 00000000000..cb762eff806 --- /dev/null +++ b/tests/wpt/tests/reporting/resources/comment.js.headers @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/tests/wpt/tests/reporting/resources/report-helper.js b/tests/wpt/tests/reporting/resources/report-helper.js index 4d3c3fbdee8..5b5438903de 100644 --- a/tests/wpt/tests/reporting/resources/report-helper.js +++ b/tests/wpt/tests/reporting/resources/report-helper.js @@ -36,3 +36,12 @@ function checkReportExists(reports, type, url) { } assert_unreached(`A report of ${type} from ${url} is not found.`); } + +function getReport(reports, type, document_url, subresource_url) { + for (const report of reports) { + if (report.type !== type) continue; + if (report.body.documentURL === document_url && report.body.subresourceURL == subresource_url) return report; + } + return null; +} + diff --git a/tests/wpt/tests/resources/testharness.js b/tests/wpt/tests/resources/testharness.js index 04c65eb2e9d..81cf6175588 100644 --- a/tests/wpt/tests/resources/testharness.js +++ b/tests/wpt/tests/resources/testharness.js @@ -1094,7 +1094,7 @@ { if (typeof func !== "function") { tests.set_status(tests.status.ERROR, - "promise_test invoked without a function"); + "`promise_setup` invoked without a function"); tests.complete(); return; } diff --git a/tests/wpt/tests/subresource-integrity/signatures/tentative/script.window.js b/tests/wpt/tests/subresource-integrity/signatures/tentative/script.window.js new file mode 100644 index 00000000000..df855954c4b --- /dev/null +++ b/tests/wpt/tests/subresource-integrity/signatures/tentative/script.window.js @@ -0,0 +1,174 @@ +// +// Validate signature-based SRI's interaction between signed script responses +// and ` - - - -
    - - diff --git a/tests/wpt/tests/wasm/jsapi/memory/to-fixed-length-buffer-shared.any.js b/tests/wpt/tests/wasm/jsapi/memory/to-fixed-length-buffer-shared.any.js new file mode 100644 index 00000000000..ddaab236f41 --- /dev/null +++ b/tests/wpt/tests/wasm/jsapi/memory/to-fixed-length-buffer-shared.any.js @@ -0,0 +1,17 @@ +// META: global=window,dedicatedworker,jsshell +// META: script=/wasm/jsapi/wasm-module-builder.js + +test(() => { + const memory = new WebAssembly.Memory({ initial: 0, maximum: 4, shared: true }); + const buffer1 = memory.buffer; + + assert_false(buffer1.growable, "By default the SAB is initially not growable"); + + const buffer2 = memory.toFixedLengthBuffer(); + assert_equals(buffer1, buffer2, "Not changing resizability does not make a new object"); + + const buffer3 = memory.toResizableBuffer(); + assert_not_equals(buffer2, buffer3, "Changing resizability makes a new object"); + assert_true(buffer3.growable); + assert_equals(memory.buffer, buffer3); +}, "toFixedLengthBuffer caching behavior"); diff --git a/tests/wpt/tests/wasm/jsapi/memory/to-fixed-length-buffer.any.js b/tests/wpt/tests/wasm/jsapi/memory/to-fixed-length-buffer.any.js new file mode 100644 index 00000000000..196324960ec --- /dev/null +++ b/tests/wpt/tests/wasm/jsapi/memory/to-fixed-length-buffer.any.js @@ -0,0 +1,42 @@ +// META: global=window,dedicatedworker,jsshell +// META: script=/wasm/jsapi/wasm-module-builder.js + +test(() => { + const thisValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + WebAssembly.Memory, + WebAssembly.Memory.prototype, + ]; + + const desc = Object.getOwnPropertyDescriptor(WebAssembly.Memory.prototype, "toFixedLengthBuffer"); + assert_equals(typeof desc, "object"); + + const fun = desc.value; + assert_equals(typeof desc.value, "function"); + + for (const thisValue of thisValues) { + assert_throws_js(TypeError, () => fun.call(thisValue), `this=${format_value(thisValue)}`); + } +}, "API surface"); + +test(() => { + const memory = new WebAssembly.Memory({ initial: 0 }); + const buffer1 = memory.buffer; + + assert_false(buffer1.resizable, "By default the AB is initially not resizable"); + + const buffer2 = memory.toFixedLengthBuffer(); + assert_equals(buffer1, buffer2, "Not changing resizability does not make a new object"); + + const buffer3 = memory.toResizableBuffer(); + assert_not_equals(buffer2, buffer3, "Changing resizability makes a new object"); + assert_true(buffer3.resizable); + assert_true(buffer2.detached); + assert_equals(memory.buffer, buffer3); +}, "toFixedLengthBuffer caching behavior"); diff --git a/tests/wpt/tests/wasm/jsapi/memory/to-resizable-buffer-shared.any.js b/tests/wpt/tests/wasm/jsapi/memory/to-resizable-buffer-shared.any.js new file mode 100644 index 00000000000..3ef0e809957 --- /dev/null +++ b/tests/wpt/tests/wasm/jsapi/memory/to-resizable-buffer-shared.any.js @@ -0,0 +1,36 @@ +// META: global=window,dedicatedworker,jsshell +// META: script=/wasm/jsapi/wasm-module-builder.js + +test(() => { + const memory = new WebAssembly.Memory({ initial: 0, maximum: 4, shared: true }); + const buffer1 = memory.buffer; + + assert_false(buffer1.growable, "By default the SAB is initially not growable"); + + const buffer2 = memory.toResizableBuffer(); + assert_true(buffer2.growable); + assert_not_equals(buffer1, buffer2, "Changing resizability makes a new object"); + assert_equals(memory.buffer, buffer2, "The buffer created by the most recent toFooBuffer call is cached"); + + const buffer3 = memory.toResizableBuffer(); + assert_equals(buffer2, buffer3, "toResizableBuffer does nothing if buffer is already resizable") + assert_equals(memory.buffer, buffer3); +}, "toResizableBuffer caching behavior"); + +test(() => { + const maxNumPages = 4; + const memory = new WebAssembly.Memory({ initial: 0, maximum: maxNumPages, shared: true }); + const buffer = memory.toResizableBuffer(); + assert_equals(buffer.maxByteLength, kPageSize * maxNumPages, "Memory maximum is same as maxByteLength"); +}, "toResizableBuffer max size"); + +test(() => { + const memory = new WebAssembly.Memory({ initial: 0, maximum: 4, shared: true }); + const buffer = memory.toResizableBuffer(); + + assert_equals(buffer.byteLength, 0); + buffer.grow(2 * kPageSize); + assert_equals(buffer.byteLength, 2 * kPageSize); + + assert_throws_js(RangeError, () => buffer.grow(3 * kPageSize - 1), "Can only grow by page multiples"); +}, "Resizing a Memory's resizable buffer"); diff --git a/tests/wpt/tests/wasm/jsapi/memory/to-resizable-buffer.any.js b/tests/wpt/tests/wasm/jsapi/memory/to-resizable-buffer.any.js new file mode 100644 index 00000000000..270151460eb --- /dev/null +++ b/tests/wpt/tests/wasm/jsapi/memory/to-resizable-buffer.any.js @@ -0,0 +1,78 @@ +// META: global=window,dedicatedworker,jsshell +// META: script=/wasm/jsapi/wasm-module-builder.js + +test(() => { + const thisValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + WebAssembly.Memory, + WebAssembly.Memory.prototype, + ]; + + const desc = Object.getOwnPropertyDescriptor(WebAssembly.Memory.prototype, "toResizableBuffer"); + assert_equals(typeof desc, "object"); + + const fun = desc.value; + assert_equals(typeof desc.value, "function"); + + for (const thisValue of thisValues) { + assert_throws_js(TypeError, () => fun.call(thisValue), `this=${format_value(thisValue)}`); + } +}, "API surface"); + +test(() => { + const memory = new WebAssembly.Memory({ initial: 0 }); + const buffer1 = memory.buffer; + + assert_false(buffer1.resizable, "By default the AB is initially not resizable"); + + const buffer2 = memory.toResizableBuffer(); + assert_true(buffer2.resizable); + assert_not_equals(buffer1, buffer2, "Changing resizability makes a new object"); + assert_true(buffer1.detached); + assert_equals(memory.buffer, buffer2, "The buffer created by the most recent toFooBuffer call is cached"); + + const buffer3 = memory.toResizableBuffer(); + assert_equals(buffer2, buffer3, "toResizableBuffer does nothing if buffer is already resizable") + assert_equals(memory.buffer, buffer3); + +}, "toResizableBuffer caching behavior"); + +test(() => { + { + const maxNumPages = 4; + const memory = new WebAssembly.Memory({ initial: 0, maximum: maxNumPages }); + const buffer = memory.toResizableBuffer(); + assert_equals(buffer.maxByteLength, kPageSize * maxNumPages, "Memory maximum is same as maxByteLength"); + } + + { + const memory = new WebAssembly.Memory({ initial: 0 }); + const buffer = memory.toResizableBuffer(); + assert_equals(buffer.maxByteLength, kPageSize * kSpecMaxPages, "Default max size is 65536 * 65536"); + } +}, "toResizableBuffer max size"); + +test(() => { + const maxNumPages = 4; + const memory = new WebAssembly.Memory({ initial: 0, maximum: maxNumPages }); + const buffer = memory.toResizableBuffer(); + + assert_equals(buffer.byteLength, 0); + buffer.resize(2 * kPageSize); + assert_equals(buffer.byteLength, 2 * kPageSize); + + assert_throws_js(RangeError, () => buffer.resize(3 * kPageSize - 1), "Can only grow by page multiples"); + assert_throws_js(RangeError, () => buffer.resize(1 * kPageSize), "Cannot shrink"); +}, "Resizing a Memory's resizable buffer"); + +test(() => { + const memory = new WebAssembly.Memory({ initial: 0 }); + const buffer = memory.toResizableBuffer(); + assert_throws_js(TypeError, () => buffer.transfer(), "Cannot be detached by JS"); +}, "Resizable buffers from Memory cannot be detached by JS"); diff --git a/tests/wpt/tests/wasm/jsapi/wasm-module-builder.js b/tests/wpt/tests/wasm/jsapi/wasm-module-builder.js index 7fa196c58c1..e8c65ed8c12 100644 --- a/tests/wpt/tests/wasm/jsapi/wasm-module-builder.js +++ b/tests/wpt/tests/wasm/jsapi/wasm-module-builder.js @@ -45,7 +45,7 @@ var kWasmV3 = 0; var kHeaderSize = 8; var kPageSize = 65536; -var kSpecMaxPages = 65535; +var kSpecMaxPages = 65536; var kMaxVarInt32Size = 5; var kMaxVarInt64Size = 10; diff --git a/tests/wpt/tests/webnn/conformance_tests/lstm.https.any.js b/tests/wpt/tests/webnn/conformance_tests/lstm.https.any.js index 13bf49261c1..e52add43f94 100644 --- a/tests/wpt/tests/webnn/conformance_tests/lstm.https.any.js +++ b/tests/wpt/tests/webnn/conformance_tests/lstm.https.any.js @@ -70,22 +70,26 @@ const lstmTests = [ }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true } }, 'operators': [{ @@ -126,26 +130,31 @@ const lstmTests = [ }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmPeepholeWeight': { 'data': [0, 0, 0, 0, 0, 0], - 'descriptor': {shape: [1, 6], dataType: 'float32'} + 'descriptor': {shape: [1, 6], dataType: 'float32'}, + 'constant': true } }, 'operators': [{ @@ -183,26 +192,31 @@ const lstmTests = [ 'inputs': { 'lstmInput': { 'data': [1, 2, 2, 1], - 'descriptor': {shape: [1, 2, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 2, 2], dataType: 'float32'}, + 'constant': true }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmInitialHiddenState': { 'data': [0, 0, 0, 0], @@ -248,26 +262,31 @@ const lstmTests = [ }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmInitialCellState': { 'data': [0, 0, 0, 0], - 'descriptor': {shape: [1, 2, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 2, 2], dataType: 'float32'}, + 'constant': true } }, 'operators': [{ @@ -309,22 +328,26 @@ const lstmTests = [ }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true } }, 'operators': [{ @@ -366,22 +389,26 @@ const lstmTests = [ }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true } }, 'operators': [{ @@ -427,22 +454,26 @@ const lstmTests = [ }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true } }, 'operators': [{ @@ -484,22 +515,26 @@ const lstmTests = [ }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true } }, 'operators': [{ @@ -541,22 +576,26 @@ const lstmTests = [ }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true } }, 'operators': [{ @@ -597,26 +636,31 @@ const lstmTests = [ }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmPeepholeWeight': { 'data': [0, 0, 0, 0, 0, 0], - 'descriptor': {shape: [1, 6], dataType: 'float32'} + 'descriptor': {shape: [1, 6], dataType: 'float32'}, + 'constant': true }, 'lstmInitialHiddenState': { 'data': [0, 0, 0, 0], @@ -675,22 +719,26 @@ const lstmTests = [ }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true } }, 'operators': [{ @@ -737,26 +785,31 @@ const lstmTests = [ }, 'lstmWeight': { 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentWeight': { 'data': [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], - 'descriptor': {shape: [1, 8, 2], dataType: 'float32'} + 'descriptor': {shape: [1, 8, 2], dataType: 'float32'}, + 'constant': true }, 'lstmBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmRecurrentBias': { 'data': [1, 2, 1, 2, 1, 2, 1, 2], - 'descriptor': {shape: [1, 8], dataType: 'float32'} + 'descriptor': {shape: [1, 8], dataType: 'float32'}, + 'constant': true }, 'lstmPeepholeWeight': { 'data': [0, 0, 0, 0, 0, 0], - 'descriptor': {shape: [1, 6], dataType: 'float32'} + 'descriptor': {shape: [1, 6], dataType: 'float32'}, + 'constant': true }, 'lstmInitialHiddenState': { 'data': [0, 0, 0, 0],