diff options
Diffstat (limited to 'testing/web-platform/tests/compute-pressure')
32 files changed, 1129 insertions, 0 deletions
diff --git a/testing/web-platform/tests/compute-pressure/README.md b/testing/web-platform/tests/compute-pressure/README.md new file mode 100644 index 0000000000..7695c4a33e --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/README.md @@ -0,0 +1,2 @@ +This directory contains (tentative) tests for the +[Compute Pressure](https://w3c.github.io/compute-pressure/) specification. diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_basic.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_basic.tentative.https.any.js new file mode 100644 index 0000000000..28322ced72 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_basic.tentative.https.any.js @@ -0,0 +1,93 @@ +// META: timeout=long +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +pressure_test((t, mockPressureService) => { + const observer = new PressureObserver(() => { + assert_unreached('The observer callback should not be called'); + }); + + mockPressureService.setExpectedFailure( + new DOMException('', 'NotSupportedError')); + return promise_rejects_dom(t, 'NotSupportedError', observer.observe('cpu')); +}, 'Return NotSupportedError when calling observer()'); + +pressure_test(async (t, mockPressureService) => { + const changes = await new Promise(resolve => { + const observer = new PressureObserver(resolve); + t.add_cleanup(() => observer.disconnect()); + observer.observe('cpu'); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + }); + assert_true(changes.length === 1); + assert_equals(changes[0].state, 'critical'); + assert_equals(changes[0].source, 'cpu'); + assert_equals(typeof changes[0].time, 'number'); +}, 'Basic functionality test'); + +pressure_test((t, mockPressureService) => { + const observer = new PressureObserver(() => { + assert_unreached('The observer callback should not be called'); + }); + + const promise = observer.observe('cpu'); + observer.unobserve('cpu'); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + + return promise_rejects_dom(t, 'AbortError', promise); +}, 'Removing observer before observe() resolves works'); + +pressure_test(async (t, mockPressureService) => { + const callbackPromises = []; + const observePromises = []; + + for (let i = 0; i < 2; i++) { + callbackPromises.push(new Promise(resolve => { + const observer = new PressureObserver(resolve); + t.add_cleanup(() => observer.disconnect()); + observePromises.push(observer.observe('cpu')); + })); + } + + await Promise.all(observePromises); + + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + + return Promise.all(callbackPromises); +}, 'Calling observe() multiple times works'); + +pressure_test(async (t, mockPressureService) => { + const observer1_changes = []; + await new Promise(resolve => { + const observer1 = new PressureObserver(changes => { + observer1_changes.push(changes); + resolve(); + }); + t.add_cleanup(() => observer1.disconnect()); + observer1.observe('cpu'); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + }); + assert_true(observer1_changes.length === 1); + assert_equals(observer1_changes[0][0].source, 'cpu'); + assert_equals(observer1_changes[0][0].state, 'critical'); + + const observer2_changes = []; + await new Promise(resolve => { + const observer2 = new PressureObserver(changes => { + observer2_changes.push(changes); + resolve(); + }); + t.add_cleanup(() => observer2.disconnect()); + observer2.observe('cpu'); + }); + assert_true(observer2_changes.length === 1); + assert_equals(observer2_changes[0][0].source, 'cpu'); + assert_equals(observer2_changes[0][0].state, 'critical'); +}, 'Starting a new observer after an observer has started works'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_detached_iframe.tentative.https.html b/testing/web-platform/tests/compute-pressure/compute_pressure_detached_iframe.tentative.https.html new file mode 100644 index 0000000000..5511a14704 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_detached_iframe.tentative.https.html @@ -0,0 +1,95 @@ +<!doctype html> +<meta charset="utf-8"> +<title>PressureObserver on DOMWindow of detached iframe</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/test-only-api.js"></script> +<script src="resources/pressure-helpers.js"></script> +<body> +<script> +'use strict'; + +test(() => { + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + const frame_window = iframe.contentWindow; + + iframe.remove(); + assert_equals(undefined, frame_window.PressureObserver); +}, 'PressureObserver constructor does not exist in detached iframes'); + +promise_test(async t => { + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + const frame_window = iframe.contentWindow; + + const observer = new frame_window.PressureObserver(() => {}); + const iframe_DOMException = frame_window.DOMException; + + iframe.remove(); + + // Calling observe() from a detached iframe should fail but not crash. + await promise_rejects_dom(t, 'NotSupportedError', iframe_DOMException, + observer.observe('cpu')); +}, 'PressureObserver.observe() on detached frame rejects'); + +promise_test(async t => { + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + const frame_window = iframe.contentWindow; + + const observer = new frame_window.PressureObserver(() => {}); + + await observer.observe('cpu'); + + iframe.remove(); + + // Calling disconnect() from a detached iframe should not crash. + observer.disconnect(); +}, 'PressureObserver.disconnect() on detached frame returns'); + +pressure_test(async (t, mockPressureService) => { + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + const frame_window = iframe.contentWindow; + + const observer = new frame_window.PressureObserver(() => {}); + const iframe_DOMException = frame_window.DOMException; + + // await is intentionally not used here. We want to remove the iframe while + // the returned Promise settles. + observer.observe('cpu'); + iframe.remove(); + + // Establish an observer and wait for changes in the main frame. This should + // keep the test running long enough to catch any crash from the observe() + // call in the removed iframe's PressureObserver. + const changes = await new Promise((resolve, reject) => { + const observer = new PressureObserver(resolve); + t.add_cleanup(() => observer.disconnect()); + observer.observe('cpu').catch(reject); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + }); + assert_equals(changes[0].state, 'critical'); +}, 'Detaching frame while PressureObserver.observe() settles'); + +pressure_test(async (t, mockPressureService) => { + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + const frame_window = iframe.contentWindow; + const observer = new frame_window.PressureObserver(() => { + assert_unreached('The observer callback should not be called'); + }); + + await observer.observe('cpu'); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + + iframe.remove(); + + return new Promise(resolve => t.step_timeout(resolve, 1000)); +}, 'PressureObserver on detached frame returns with no callback'); + +</script> +</body> diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_disconnect.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_disconnect.tentative.https.any.js new file mode 100644 index 0000000000..1d188fad8b --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_disconnect.tentative.https.any.js @@ -0,0 +1,44 @@ +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +test(t => { + const observer = new PressureObserver(() => { + assert_unreached('The observer callback should not be called'); + }); + t.add_cleanup(() => observer.disconnect()); + observer.disconnect(); +}, 'Call disconnect() directly should not crash'); + +pressure_test(async (t, mockPressureService) => { + const observer1_changes = []; + const observer1 = new PressureObserver(change => { + observer1_changes.push(change); + }); + t.add_cleanup(() => observer1.disconnect()); + // Ensure that observer1's schema gets registered before observer2 starts. + await observer1.observe('cpu'); + observer1.disconnect(); + + const observer2_changes = []; + await new Promise((resolve, reject) => { + const observer2 = new PressureObserver(change => { + observer2_changes.push(change); + resolve(); + }); + t.add_cleanup(() => observer2.disconnect()); + observer2.observe('cpu').catch(reject); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + }); + + assert_equals( + observer1_changes.length, 0, + 'disconnected observers should not receive callbacks'); + + assert_equals(observer2_changes.length, 1); + assert_equals(observer2_changes[0].length, 1); + assert_equals(observer2_changes[0][0].state, 'critical'); +}, 'Stopped PressureObserver do not receive changes'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.any.js new file mode 100644 index 0000000000..74d37bd6e5 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_disconnect_idempotent.tentative.https.any.js @@ -0,0 +1,37 @@ +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +pressure_test(async (t, mockPressureService) => { + const observer1_changes = []; + const observer1 = new PressureObserver(changes => { + observer1_changes.push(changes); + }); + t.add_cleanup(() => observer1.disconnect()); + // Ensure that observer1's schema gets registered before observer2 starts. + const promise = observer1.observe('cpu'); + observer1.disconnect(); + observer1.disconnect(); + await promise_rejects_dom(t, 'AbortError', promise); + + const observer2_changes = []; + await new Promise((resolve, reject) => { + const observer2 = new PressureObserver(changes => { + observer2_changes.push(changes); + resolve(); + }); + t.add_cleanup(() => observer2.disconnect()); + observer2.observe('cpu').catch(reject); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + }); + + assert_equals( + observer1_changes.length, 0, + 'stopped observers should not receive callbacks'); + + assert_equals(observer2_changes.length, 1); + assert_equals(observer2_changes[0][0].state, 'critical'); +}, 'Stopped PressureObserver do not receive changes'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_disconnect_immediately.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_disconnect_immediately.tentative.https.any.js new file mode 100644 index 0000000000..9b545fbe1c --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_disconnect_immediately.tentative.https.any.js @@ -0,0 +1,67 @@ +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +pressure_test(async (t, mockPressureService) => { + const observer1_changes = []; + const observer1 = new PressureObserver(changes => { + observer1_changes.push(changes); + }); + t.add_cleanup(() => observer1.disconnect()); + // Ensure that observer1's schema gets registered before observer2 starts. + const promise = observer1.observe('cpu'); + observer1.disconnect(); + await promise_rejects_dom(t, 'AbortError', promise); + + const observer2_changes = []; + await new Promise((resolve, reject) => { + const observer2 = new PressureObserver(changes => { + observer2_changes.push(changes); + resolve(); + }); + t.add_cleanup(() => observer2.disconnect()); + observer2.observe('cpu').catch(reject); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + }); + + assert_equals( + observer1_changes.length, 0, + 'stopped observers should not receive callbacks'); + + assert_equals(observer2_changes.length, 1); + assert_equals(observer2_changes[0].length, 1); + assert_equals(observer2_changes[0][0].state, 'critical'); +}, 'Stopped PressureObserver do not receive changes'); + +pressure_test(async (t, mockPressureService) => { + const observer1_changes = []; + const observer1 = new PressureObserver(changes => { + observer1_changes.push(changes); + }); + t.add_cleanup(() => observer1.disconnect()); + + const observer2_changes = []; + await new Promise(async resolve => { + const observer2 = new PressureObserver(changes => { + observer2_changes.push(changes); + resolve(); + }); + t.add_cleanup(() => observer2.disconnect()); + const promise = observer1.observe('cpu'); + observer2.observe('cpu'); + observer1.disconnect(); + await promise_rejects_dom(t, 'AbortError', promise); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + }); + + assert_equals( + observer1_changes.length, 0, + 'stopped observers should not receive callbacks'); + + assert_equals(observer2_changes.length, 1); + assert_equals(observer2_changes[0][0].state, 'critical'); +}, 'Removing observer before observe() resolves does not affect other observers'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_duplicate_updates.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_duplicate_updates.tentative.https.any.js new file mode 100644 index 0000000000..dde92932dd --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_duplicate_updates.tentative.https.any.js @@ -0,0 +1,32 @@ +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +pressure_test(async (t, mockPressureService) => { + const pressureChanges = await new Promise(async resolve => { + const observer_changes = []; + let n = 0; + const observer = new PressureObserver(changes => { + observer_changes.push(changes); + if (++n === 2) + resolve(observer_changes); + }, {sampleRate: 5.0}); + observer.observe('cpu'); + const updatesDelivered = mockPressureService.updatesDelivered(); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate*/ 5.0); + // Deliver 2 updates. + await t.step_wait( + () => mockPressureService.updatesDelivered() >= (updatesDelivered + 2), + 'Wait for more than one update to be delivered to the observer'); + mockPressureService.setPressureUpdate('cpu', 'nominal'); + // Deliver more updates, |resolve()| will be called when the new pressure + // state reaches PressureObserver and its callback is invoked + // for the second time. + }); + assert_equals(pressureChanges.length, 2); + assert_equals(pressureChanges[0][0].state, 'critical'); + assert_equals(pressureChanges[1][0].state, 'nominal'); +}, 'Changes that fail the "has change in data" test are discarded.'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_multiple.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_multiple.tentative.https.any.js new file mode 100644 index 0000000000..c8cef5beca --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_multiple.tentative.https.any.js @@ -0,0 +1,35 @@ +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +pressure_test(async (t, mockPressureService) => { + const changes1_promise = new Promise((resolve, reject) => { + const observer = new PressureObserver(resolve); + t.add_cleanup(() => observer.disconnect()); + observer.observe('cpu').catch(reject); + }); + + const changes2_promise = new Promise((resolve, reject) => { + const observer = new PressureObserver(resolve); + t.add_cleanup(() => observer.disconnect()); + observer.observe('cpu').catch(reject); + }); + + const changes3_promise = new Promise((resolve, reject) => { + const observer = new PressureObserver(resolve); + t.add_cleanup(() => observer.disconnect()); + observer.observe('cpu').catch(reject); + }); + + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + + const [changes1, changes2, changes3] = + await Promise.all([changes1_promise, changes2_promise, changes3_promise]); + + for (const changes of [changes1, changes2, changes3]) { + assert_equals(changes[0].state, 'critical'); + } +}, 'Three PressureObserver instances receive changes'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_observe_idempotent.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_observe_idempotent.tentative.https.any.js new file mode 100644 index 0000000000..5dc3804b2f --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_observe_idempotent.tentative.https.any.js @@ -0,0 +1,19 @@ +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +pressure_test(async (t, mockPressureService) => { + const update = await new Promise((resolve, reject) => { + const observer = new PressureObserver(resolve); + t.add_cleanup(() => observer.disconnect()); + observer.observe('cpu').catch(reject); + observer.observe('cpu').catch(reject); + observer.observe('cpu').catch(reject); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + }); + + assert_equals(update[0].state, 'critical'); +}, 'PressureObserver.observe() is idempotent'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.any.js new file mode 100644 index 0000000000..8eafeb356d --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_observe_unobserve_failure.tentative.https.any.js @@ -0,0 +1,19 @@ +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +promise_test(async t => { + const observer = + new PressureObserver(t.unreached_func('oops should not end up here')); + t.add_cleanup(() => observer.disconnect()); + await promise_rejects_js(t, TypeError, observer.observe('random')); +}, 'PressureObserver.observe() requires a valid source'); + +test(t => { + const observer = + new PressureObserver(t.unreached_func('oops should not end up here')); + t.add_cleanup(() => observer.disconnect()); + assert_throws_js(TypeError, () => { + observer.unobserve('random'); + }); +}, 'PressureObserver.unobserve() requires a valid source'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_options.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_options.tentative.https.any.js new file mode 100644 index 0000000000..69999819d9 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_options.tentative.https.any.js @@ -0,0 +1,25 @@ +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +test(t => { + assert_throws_js(RangeError, () => { + new PressureObserver(() => {}, {sampleRate: 0}); + }); +}, 'PressureObserver constructor requires a non-zero sampleRate'); + +test(t => { + assert_throws_js(RangeError, () => { + new PressureObserver(() => {}, {sampleRate: -2}); + }); +}, 'PressureObserver constructor requires a positive sampleRate'); + +test(t => { + const observer = new PressureObserver(() => {}, {sampleRate: 0.5}); + assert_equals(typeof observer, 'object'); +}, 'PressureObserver constructor doesnt throw error on positive sampleRate'); + +test(t => { + const observer = new PressureObserver(() => {}, {}); + assert_equals(typeof observer, 'object'); +}, 'PressureObserver constructor succeeds on empty sampleRate'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_rate_obfuscation_mitigation_not_triggered.tentative.https.window.js b/testing/web-platform/tests/compute-pressure/compute_pressure_rate_obfuscation_mitigation_not_triggered.tentative.https.window.js new file mode 100644 index 0000000000..cb1aa432ce --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_rate_obfuscation_mitigation_not_triggered.tentative.https.window.js @@ -0,0 +1,50 @@ +// META: timeout=long +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +pressure_test(async (t, mockPressureService) => { + const sampleRateInHz = 10; + const readings = ['nominal', 'fair', 'serious', 'critical']; + // Normative values for rate obfuscation parameters. + // https://w3c.github.io/compute-pressure/#rate-obfuscation-normative-parameters. + const minPenaltyTimeInMs = 5000; + const minChangesThreshold = 50; + + const changes = await new Promise(async resolve => { + const observerChanges = []; + const observer = new PressureObserver(changes => { + observerChanges.push(changes); + }, {sampleRate: sampleRateInHz}); + + observer.observe('cpu'); + mockPressureService.startPlatformCollector(sampleRateInHz); + let i = 0; + // mockPressureService.updatesDelivered() does not necessarily match + // pressureChanges.length, as system load and browser optimizations can + // cause the actual timer used by mockPressureService to deliver readings + // to be a bit slower or faster than requested. + while (observerChanges.length < minChangesThreshold) { + mockPressureService.setPressureUpdate( + 'cpu', readings[i++ % readings.length]); + // Allow tasks to run (avoid a micro-task loop). + await new Promise((resolve) => t.step_timeout(resolve, 0)); + await t.step_wait( + () => mockPressureService.updatesDelivered() >= i, + `At least ${i} readings have been delivered`); + } + observer.disconnect(); + resolve(observerChanges); + }); + assert_equals(changes.length, minChangesThreshold); + + for (let i = 0; i < (changes.length - 1); i++) { + // Because no penalty should be triggered, the timestamp difference + // between samples should be less than the minimum penalty. + assert_less_than( + changes[i + 1][0].time - changes[i][0].time, minPenaltyTimeInMs, + 'Not in sample time boundaries'); + } +}, 'No rate obfuscation mitigation should happen, when number of changes is below minimum changes before penalty'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_rate_obfuscation_mitigation_triggered.tentative.https.window.js b/testing/web-platform/tests/compute-pressure/compute_pressure_rate_obfuscation_mitigation_triggered.tentative.https.window.js new file mode 100644 index 0000000000..11dcc3c70a --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_rate_obfuscation_mitigation_triggered.tentative.https.window.js @@ -0,0 +1,56 @@ +// META: timeout=long +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +pressure_test(async (t, mockPressureService) => { + const sampleRateInHz = 25; + const readings = ['nominal', 'fair', 'serious', 'critical']; + // Normative values for rate obfuscation parameters. + // https://w3c.github.io/compute-pressure/#rate-obfuscation-normative-parameters. + const minPenaltyTimeInMs = 5000; + const maxChangesThreshold = 100; + const minChangesThreshold = 50; + let gotPenalty = false; + await new Promise(async resolve => { + const observerChanges = []; + const observer = new PressureObserver(changes => { + if (observerChanges.length >= (minChangesThreshold - 1)) { + const lastSample = observerChanges.at(-1); + if ((changes[0].time - lastSample[0].time) >= minPenaltyTimeInMs) { + // The update delivery might still be working even if + // maxChangesThreshold have been reached and before disconnect() is + // processed. + // Therefore we are adding a flag to dismiss any updates after the + // penalty is detected, which is the condition for the test to pass. + gotPenalty = true; + observer.disconnect(); + resolve(); + } + } + observerChanges.push(changes); + }, {sampleRate: sampleRateInHz}); + + observer.observe('cpu'); + mockPressureService.startPlatformCollector(sampleRateInHz); + let i = 0; + // mockPressureService.updatesDelivered() does not necessarily match + // pressureChanges.length, as system load and browser optimizations can + // cause the actual timer used by mockPressureService to deliver readings + // to be a bit slower or faster than requested. + while (observerChanges.length <= maxChangesThreshold || !gotPenalty) { + mockPressureService.setPressureUpdate( + 'cpu', readings[i++ % readings.length]); + // Allow tasks to run (avoid a micro-task loop). + await new Promise((resolve) => t.step_timeout(resolve, 0)); + await t.step_wait( + () => mockPressureService.updatesDelivered() >= i, + `At least ${i} readings have been delivered`); + } + + assert_true(gotPenalty, 'Penalty not triggered'); + + }); +}, 'Rate obfuscation mitigation should have been triggered, when changes is higher than minimum changes before penalty'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_supported_sources.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_supported_sources.tentative.https.any.js new file mode 100644 index 0000000000..63f2666cca --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_supported_sources.tentative.https.any.js @@ -0,0 +1,21 @@ +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +test(() => { + // Compute Pressure should support at least "cpu" + const sources = PressureObserver.supportedSources; + assert_in_array('cpu', sources); +}, 'PressureObserver should support at least "cpu"'); + +test(() => { + // Compute Pressure should be frozen array + const sources = PressureObserver.supportedSources; + assert_equals(sources, PressureObserver.supportedSources); +}, 'PressureObserver must return always the same array'); + +test(() => { + // Compute Pressure should be frozen array + let sources = PressureObserver.supportedSources; + assert_equals(Object.isFrozen(), true); +}, 'PressureObserver must return a frozen array'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_take_records.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_take_records.tentative.https.any.js new file mode 100644 index 0000000000..d93c9b5c88 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_take_records.tentative.https.any.js @@ -0,0 +1,29 @@ +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +test(t => { + const observer = new PressureObserver( + t.unreached_func('This callback should not have been called.')); + + const records = observer.takeRecords(); + assert_equals(records.length, 0, 'No record before observe'); +}, 'Calling takeRecords() before observe()'); + +pressure_test(async (t, mockPressureService) => { + let observer; + const changes = await new Promise(resolve => { + observer = new PressureObserver(resolve); + t.add_cleanup(() => observer.disconnect()); + + observer.observe('cpu'); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + }); + assert_equals(changes[0].state, 'critical'); + + const records = observer.takeRecords(); + assert_equals(records.length, 0, 'No record available'); +}, 'takeRecords() returns empty record after callback invoke'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_timestamp.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_timestamp.tentative.https.any.js new file mode 100644 index 0000000000..f283caa6ba --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_timestamp.tentative.https.any.js @@ -0,0 +1,79 @@ +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +'use strict'; + +pressure_test(async (t, mockPressureService) => { + const readings = ['nominal', 'fair', 'serious', 'critical']; + + const sampleRate = 4.0; + const pressureChanges = await new Promise(async resolve => { + const observerChanges = []; + const observer = new PressureObserver(changes => { + observerChanges.push(changes); + }, {sampleRate}); + observer.observe('cpu'); + + mockPressureService.startPlatformCollector(sampleRate * 2); + let i = 0; + // mockPressureService.updatesDelivered() does not necessarily match + // pressureChanges.length, as system load and browser optimizations can + // cause the actual timer used by mockPressureService to deliver readings + // to be a bit slower or faster than requested. + while (observerChanges.length < 4) { + mockPressureService.setPressureUpdate( + 'cpu', readings[i++ % readings.length]); + await t.step_wait( + () => mockPressureService.updatesDelivered() >= i, + `At least ${i} readings have been delivered`); + } + observer.disconnect(); + resolve(observerChanges); + }); + + assert_equals(pressureChanges.length, 4); + assert_greater_than_equal( + pressureChanges[1][0].time - pressureChanges[0][0].time, + (1 / sampleRate * 1000)); + assert_greater_than_equal( + pressureChanges[2][0].time - pressureChanges[1][0].time, + (1 / sampleRate * 1000)); + assert_greater_than_equal( + pressureChanges[3][0].time - pressureChanges[2][0].time, + (1 / sampleRate * 1000)); +}, 'Faster collector: Timestamp difference between two changes should be higher or equal to the observer sample rate'); + +pressure_test(async (t, mockPressureService) => { + const pressureChanges = []; + const sampleRate = 1.0; + const observer = new PressureObserver(changes => { + pressureChanges.push(changes); + }, {sampleRate}); + + await new Promise(async resolve => { + observer.observe('cpu'); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(sampleRate); + await t.step_wait(() => pressureChanges.length == 1); + observer.disconnect(); + resolve(); + }); + + await new Promise(async resolve => { + observer.observe('cpu'); + mockPressureService.setPressureUpdate('cpu', 'serious'); + mockPressureService.startPlatformCollector(sampleRate * 4); + await t.step_wait(() => pressureChanges.length == 2); + observer.disconnect(); + resolve(); + }); + + assert_equals(pressureChanges.length, 2); + // When disconnect() is called, PressureRecord in [[LastRecordMap]] for cpu + // should be deleted. So the second PressureRecord is not discarded even + // though the time interval does not meet the requirement. + assert_less_than( + pressureChanges[1][0].time - pressureChanges[0][0].time, + (1 / sampleRate * 1000)); +}, 'disconnect() should update [[LastRecordMap]]'); diff --git a/testing/web-platform/tests/compute-pressure/compute_pressure_update_toJSON.tentative.https.any.js b/testing/web-platform/tests/compute-pressure/compute_pressure_update_toJSON.tentative.https.any.js new file mode 100644 index 0000000000..0024d69754 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/compute_pressure_update_toJSON.tentative.https.any.js @@ -0,0 +1,17 @@ +// META: script=/resources/test-only-api.js +// META: script=resources/pressure-helpers.js +// META: global=window,dedicatedworker,sharedworker + +pressure_test(async (t, mockPressureService) => { + const changes = await new Promise(resolve => { + const observer = new PressureObserver(resolve); + observer.observe('cpu'); + mockPressureService.setPressureUpdate('cpu', 'critical'); + mockPressureService.startPlatformCollector(/*sampleRate=*/ 5.0); + }); + assert_true(changes.length === 1); + const json = changes[0].toJSON(); + assert_equals(json.state, 'critical'); + assert_equals(json.source, 'cpu'); + assert_equals(typeof json.time, 'number'); +}, 'Basic functionality test'); diff --git a/testing/web-platform/tests/compute-pressure/idlharness.https.any.js b/testing/web-platform/tests/compute-pressure/idlharness.https.any.js new file mode 100644 index 0000000000..e828996232 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/idlharness.https.any.js @@ -0,0 +1,15 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: global=window,dedicatedworker,sharedworker + +// https://w3c.github.io/compute-pressure/ + +'use strict'; + +idl_test(['compute-pressure'], ['dom', 'html'], async idl_array => { + idl_array.add_objects({ + PressureObserver: ['observer'], + }); + + self.observer = new PressureObserver(() => {}, {sampleRate: 1.0}); +}); diff --git a/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy-attribute-redirect-on-load.https.html b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy-attribute-redirect-on-load.https.html new file mode 100644 index 0000000000..ec5b464461 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy-attribute-redirect-on-load.https.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/permissions-policy/resources/permissions-policy.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script> +"use strict"; + +const relative_path = + '/permissions-policy/resources/permissions-policy-compute-pressure.html'; +const base_src = '/permissions-policy/resources/redirect-on-load.html#'; +const same_origin_src = base_src + relative_path; +const cross_origin_src = + base_src + get_host_info().HTTPS_REMOTE_ORIGIN + relative_path; +const header = 'permissions policy allow="compute-pressure"'; + +async_test(t => { + test_feature_availability( + 'PressureObserver.observe()', + t, + same_origin_src, + expect_feature_available_default, + 'compute-pressure' + ); +}, `${header} allows same-origin navigation in an iframe.`); + +async_test(t => { + test_feature_availability( + 'PressureObserver.observe()', + t, + cross_origin_src, + expect_feature_unavailable_default, + 'compute-pressure' + ); +}, `${header} disallows cross-origin navigation in an iframe.`); + +</script> +</body> diff --git a/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy-attribute.https.html b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy-attribute.https.html new file mode 100644 index 0000000000..d6dfcfc191 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy-attribute.https.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/permissions-policy/resources/permissions-policy.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script> +"use strict"; + +const same_origin_src = + '/permissions-policy/resources/permissions-policy-compute-pressure.html'; +const cross_origin_src = get_host_info().HTTPS_REMOTE_ORIGIN + same_origin_src; +const feature_name = 'permissions policy "compute-pressure"'; +const attribute = 'allow="compute-pressure" attribute'; + +async_test(t => { + test_feature_availability( + 'PressureObserver.observe()', + t, + same_origin_src, + expect_feature_available_default, + 'compute-pressure' + ); +}, `${feature_name} can be enabled in same-origin iframe using ${attribute}`); + +async_test(t => { + test_feature_availability( + 'PressureObserver.observe()', + t, + cross_origin_src, + expect_feature_available_default, + 'compute-pressure' + ); +}, `${feature_name} can be enabled in cross-origin iframe using ${attribute}`); + +</script> +</body> diff --git a/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy.https.html b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy.https.html new file mode 100644 index 0000000000..643e672949 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy.https.html @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/permissions-policy/resources/permissions-policy.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script> +"use strict"; + +const same_origin_src = + '/permissions-policy/resources/permissions-policy-compute-pressure.html'; +const cross_origin_src = get_host_info().HTTPS_REMOTE_ORIGIN + same_origin_src; +const header = 'permissions policy header "compute-pressure=*"'; +const attribute = 'allow="compute-pressure" attribute'; + +promise_test(async () => { + try { + const observer = new PressureObserver(() => {}); + await observer.observe("cpu"); + observer.disconnect(); + } catch (e) { + assert_unreached("expected promise to resolve."); + } +}, `${header} allows the top-level document.`); + +async_test(t => { + test_feature_availability( + 'ComputePressure.observe()', + t, + same_origin_src, + expect_feature_available_default + ); +}, `${header} allows same-origin iframes.`); + +async_test(t => { + test_feature_availability( + 'ComputePressure.observe()', + t, + cross_origin_src, + expect_feature_unavailable_default + ); +}, `${header} disallows cross-origin iframes.`); + +async_test(t => { + test_feature_availability( + 'ComputePressure.observe()', + t, + cross_origin_src, + expect_feature_available_default, + 'compute-pressure' + ); +}, `${header} allows cross-origin iframes with ${attribute}.`); + +fetch_tests_from_worker(new Worker( +'/compute-pressure/resources/compute-pressure-allowed-by-permissions-policy-worker.js')); +</script> +</body> diff --git a/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy.https.html.headers b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy.https.html.headers new file mode 100644 index 0000000000..76185cbb2d --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-by-permissions-policy.https.html.headers @@ -0,0 +1 @@ +Permissions-Policy: compute-pressure=* diff --git a/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-on-self-origin-by-permissions-policy.https.html b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-on-self-origin-by-permissions-policy.https.html new file mode 100644 index 0000000000..98450b91a7 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-on-self-origin-by-permissions-policy.https.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/permissions-policy/resources/permissions-policy.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script> +"use strict"; + +const same_origin_src = + '/permissions-policy/resources/permissions-policy-compute-pressure.html'; +const cross_origin_src = get_host_info().HTTPS_REMOTE_ORIGIN + same_origin_src; +const header = 'permissions policy header "compute-pressure=self"'; + +promise_test(async () => { + try { + const observer = new PressureObserver(() => {}); + await observer.observe("cpu"); + observer.disconnect(); + } catch (e) { + assert_unreached('expected promise to resolve.'); + } +}, `${header} allows the top-level document.`); + +async_test(t => { + test_feature_availability( + 'ComputePressure.observe()', + t, + same_origin_src, + expect_feature_available_default + ); +}, `${header} allows same-origin iframes.`); + +async_test(t => { + test_feature_availability( + 'ComputePressure.observe()', + t, + cross_origin_src, + expect_feature_unavailable_default + ); +}, `${header} disallows cross-origin iframes.`); + +</script> +</body> diff --git a/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-on-self-origin-by-permissions-policy.https.html.headers b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-on-self-origin-by-permissions-policy.https.html.headers new file mode 100644 index 0000000000..6852f871bb --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-allowed-on-self-origin-by-permissions-policy.https.html.headers @@ -0,0 +1 @@ +Permissions-Policy: compute-pressure=self diff --git a/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-default-permissions-policy.https.html b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-default-permissions-policy.https.html new file mode 100644 index 0000000000..5a7c77264e --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-default-permissions-policy.https.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/permissions-policy/resources/permissions-policy.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script> +"use strict"; + +const same_origin_src = + '/permissions-policy/resources/permissions-policy-compute-pressure.html'; +const cross_origin_src = get_host_info().HTTPS_REMOTE_ORIGIN + same_origin_src; +const header = 'Default "compute-pressure" permissions policy'; + +async_test(t => { + test_feature_availability( + 'ComputePressure.observe()', + t, + same_origin_src, + expect_feature_available_default + ); +}, `${header} allows same-origin iframes.`); + +async_test(t => { + test_feature_availability( + 'ComputePressure.observe()', + t, + cross_origin_src, + expect_feature_unavailable_default + ); +}, `${header} disallows cross-origin iframes.`); + +</script> +</body> diff --git a/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-disabled-by-permissions-policy.https.html b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-disabled-by-permissions-policy.https.html new file mode 100644 index 0000000000..55a997283b --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-disabled-by-permissions-policy.https.html @@ -0,0 +1,64 @@ +<!DOCTYPE html> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/permissions-policy/resources/permissions-policy.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script> +"use strict"; + +const same_origin_src = + '/permissions-policy/resources/permissions-policy-compute-pressure.html'; +const cross_origin_src = get_host_info().HTTPS_REMOTE_ORIGIN + same_origin_src; +const header = 'permissions policy header "compute-pressure=()"'; +const attribute = 'allow="compute-pressure" attribute'; + +promise_test(async t => { + const observer = new PressureObserver( + t.unreached_func('oops should not end up here') + ); + await promise_rejects_dom(t, 'NotAllowedError', observer.observe("cpu")); +}, `${header} disallows the top-level document.`); + +async_test(t => { + test_feature_availability( + 'ComputePressure.observe()', + t, + same_origin_src, + expect_feature_unavailable_default + ); +}, `${header} disallows same-origin iframes.`); + +async_test(t => { + test_feature_availability( + 'ComputePressure.observe()', + t, + cross_origin_src, + expect_feature_unavailable_default + ); +}, `${header} disallows cross-origin iframes.`); + +async_test(t => { + test_feature_availability( + 'ComputePressure.observe()', + t, + same_origin_src, + expect_feature_unavailable_default, + 'compute-pressure' + ); +}, `${header} disallows same-origin iframes despite the ${attribute}.`); + +async_test(t => { + test_feature_availability( + 'ComputePressure.observe()', + t, + cross_origin_src, + expect_feature_unavailable_default, + 'compute-pressure' + ); +}, `${header} disallows cross-origin iframes despite the ${attribute}.`); + +fetch_tests_from_worker(new Worker( + '/compute-pressure/resources/compute-pressure-disabled-by-permissions-policy-worker.js')); +</script> +</body> diff --git a/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-disabled-by-permissions-policy.https.html.headers b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-disabled-by-permissions-policy.https.html.headers new file mode 100644 index 0000000000..2e9f2ecce0 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-disabled-by-permissions-policy.https.html.headers @@ -0,0 +1 @@ +Permissions-Policy: compute-pressure=() diff --git a/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-supported-by-permissions-policy.html b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-supported-by-permissions-policy.html new file mode 100644 index 0000000000..35f09b7b07 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/permissions-policy/compute-pressure-supported-by-permissions-policy.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<title>Test that compute-pressure is advertised in the feature list</title> +<link rel="help" href="https://w3c.github.io/webappsec-permissions-policy/#dom-permissions-policy-features"> +<link rel="help" href="https://w3c.github.io/compute-pressure/#policy-control"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(() => { + assert_in_array('compute-pressure', document.featurePolicy.features()); +}, 'document.featurePolicy.features should advertise compute-pressure.'); +</script> diff --git a/testing/web-platform/tests/compute-pressure/resources/compute-pressure-allowed-by-permissions-policy-worker.js b/testing/web-platform/tests/compute-pressure/resources/compute-pressure-allowed-by-permissions-policy-worker.js new file mode 100644 index 0000000000..590ac52cfd --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/resources/compute-pressure-allowed-by-permissions-policy-worker.js @@ -0,0 +1,22 @@ +'use strict'; + +importScripts('/resources/testharness.js'); + +const header = 'permissions policy header "compute-pressure=*"'; +let workerType; + +if (typeof postMessage === 'function') { + workerType = 'dedicated'; +} + +promise_test(async () => { + try { + const observer = new PressureObserver(() => {}); + await observer.observe('cpu'); + observer.disconnect(); + } catch (e) { + assert_unreached('expected promise to resolve.'); + } +}, `$Inherited ${header} allows ${workerType} workers.`); + +done(); diff --git a/testing/web-platform/tests/compute-pressure/resources/compute-pressure-disabled-by-permissions-policy-worker.js b/testing/web-platform/tests/compute-pressure/resources/compute-pressure-disabled-by-permissions-policy-worker.js new file mode 100644 index 0000000000..90ed0a7857 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/resources/compute-pressure-disabled-by-permissions-policy-worker.js @@ -0,0 +1,18 @@ +'use strict'; + +importScripts('/resources/testharness.js'); + +const header = 'Permissions-Policy header compute-pressure=()'; +let workerType; + +if (typeof postMessage === 'function') { + workerType = 'dedicated'; +} + +promise_test(async t => { + const observer = + new PressureObserver(t.unreached_func('oops should not end up here')); + await promise_rejects_dom(t, 'NotAllowedError', observer.observe('cpu')); +}, `$Inherited ${header} disallows ${workerType} workers.`); + +done(); diff --git a/testing/web-platform/tests/compute-pressure/resources/pressure-helpers.js b/testing/web-platform/tests/compute-pressure/resources/pressure-helpers.js new file mode 100644 index 0000000000..5234cf2d78 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/resources/pressure-helpers.js @@ -0,0 +1,35 @@ +'use strict'; + +// These tests rely on the User Agent providing an implementation of +// platform compute pressure backends. +// +// In Chromium-based browsers this implementation is provided by a polyfill +// in order to reduce the amount of test-only code shipped to users. To enable +// these tests the browser must be run with these options: +// +// --enable-blink-features=MojoJS,MojoJSTest + +let mockPressureService = undefined; + +function pressure_test(func, name, properties) { + promise_test(async t => { + if (mockPressureService === undefined) { + if (isChromiumBased) { + const mocks = + await import('/resources/chromium/mock-pressure-service.js'); + mockPressureService = mocks.mockPressureService; + } + } + assert_implements( + mockPressureService, + 'missing mockPressureService after initialization'); + + mockPressureService.start(); + + t.add_cleanup(() => { + mockPressureService.reset(); + return mockPressureService.stop(); + }); + return func(t, mockPressureService); + }, name, properties); +} diff --git a/testing/web-platform/tests/compute-pressure/resources/support-iframe.html b/testing/web-platform/tests/compute-pressure/resources/support-iframe.html new file mode 100644 index 0000000000..6b2b309792 --- /dev/null +++ b/testing/web-platform/tests/compute-pressure/resources/support-iframe.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<meta charset="utf-8"> +<title>compute pressure iframe tester</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +async function messageHandler(e) { + if (e.data.command === 'start') { + return new Promise((resolve, reject) => { + const observer = new PressureObserver(()=> { + resolve('success'); + }); + observer.observe('cpu'); + window.setTimeout(() => { reject('timeout'); }, 1000); + }); + } else { + return Promise.reject(`unknown command "${e.data.command}"`); + } +} + +window.onmessage = async (e) => { + let reply; + try { + reply = await messageHandler(e); + } catch (error) { + reply = error; + } + e.source.postMessage({ command: e.data.command, result: reply }, '*'); +} +</script> |