summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/web-locks/query-ordering.tentative.https.html
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /testing/web-platform/tests/web-locks/query-ordering.tentative.https.html
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/web-locks/query-ordering.tentative.https.html')
-rw-r--r--testing/web-platform/tests/web-locks/query-ordering.tentative.https.html131
1 files changed, 131 insertions, 0 deletions
diff --git a/testing/web-platform/tests/web-locks/query-ordering.tentative.https.html b/testing/web-platform/tests/web-locks/query-ordering.tentative.https.html
new file mode 100644
index 0000000000..d5e722baf7
--- /dev/null
+++ b/testing/web-platform/tests/web-locks/query-ordering.tentative.https.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Web Locks API: navigator.locks.query ordering</title>
+<link rel=help href="https://w3c.github.io/web-locks/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/helpers.js"></script>
+<style>iframe { display: none; }</style>
+<script>
+'use strict';
+
+// Grab a lock and hold until a release function is called. Resolves
+// to a release function.
+function getLockAndHoldUntilReleased(name, options) {
+ let release;
+ const promise = new Promise(resolve => { release = resolve; });
+ return new Promise(resolve => {
+ navigator.locks.request(name, options || {}, lock => {
+ resolve(release);
+ return promise;
+ }).catch(_ => {});
+ });
+}
+
+// Returns a promise resolved by the next message event.
+function nextMessage() {
+ return new Promise(resolve => {
+ window.addEventListener('message', event => {
+ resolve(event.data);
+ }, {once: true});
+ });
+}
+
+// Tests the ordering constraints on the requested lock state returned by
+// navigator.locks.query(). Three separate iframes are instantiated to make
+// lock requests on the same resource, first in one order and then in another,
+// different order. For each set of requests, it is verified that the requests
+// appear in the result of navigator.locks.query() in the same order in which
+// they were made.
+//
+// It is necessary to use separate iframes here so that the lock requests have
+// distinguishable client_ids (otherwise it would not be possible to
+// distinguish the requests and thus impossible to verify ordering).
+promise_test(async testCase => {
+ assert_implements(navigator.locks);
+ const resourceName = uniqueName(testCase);
+
+ // Set up clients.
+ const frame1 = await iframe('resources/iframe.html');
+ const frame2 = await iframe('resources/iframe.html');
+ const frame3 = await iframe('resources/iframe.html');
+ testCase.add_cleanup(() => { frame1.remove(); });
+ testCase.add_cleanup(() => { frame2.remove(); });
+ testCase.add_cleanup(() => { frame3.remove(); });
+
+ // Collect the client ids.
+ const clientId1 =
+ (await postToFrameAndWait(frame1, {op: 'client_id',
+ name: resourceName})).client_id;
+ const clientId2 =
+ (await postToFrameAndWait(frame2, {op: 'client_id',
+ name: resourceName})).client_id;
+ const clientId3 =
+ (await postToFrameAndWait(frame3, {op: 'client_id',
+ name: resourceName})).client_id;
+
+ // Preemptively take the lock.
+ const firstRequestGroupReleaseFunction =
+ await getLockAndHoldUntilReleased(resourceName);
+
+ // Queue the first group of lock requests from the different clients. These
+ // will be blocked until firstRequestGroupReleaseFunction() is called.
+ let lockId1;
+ let lockId2;
+ const lockPromise1 =
+ postToFrameAndWait(frame1, {op: 'request', name: resourceName})
+ .then(val => {lockId1 = val.lock_id;});
+ const lockPromise2 =
+ postToFrameAndWait(frame2, {op: 'request', name: resourceName})
+ .then(val => {lockId2 = val.lock_id;});
+
+ // This third request will later be granted and held in order to block a
+ // second group of requests to test a different client ordering. It is not
+ // meant to be released.
+ postToFrameAndWait(frame3, {op: 'request', name: resourceName});
+
+ // Request and wait for the release of a separate lock to ensure all previous
+ // requests are processed.
+ const checkpointName = uniqueName(testCase, 'checkpoint');
+ const checkpointId = (await postToFrameAndWait(
+ frame3,
+ {op: 'request', name: checkpointName})).lock_id;
+ await postToFrameAndWait(frame3, {op: 'release', lock_id: checkpointId});
+
+ // Query the state and test the ordering of requested locks.
+ const state = await navigator.locks.query();
+ const relevant_pending_ids = state.pending
+ .filter(lock => [clientId1, clientId2, clientId3].includes(lock.clientId))
+ .map(lock => lock.clientId);
+ assert_array_equals(
+ [clientId1, clientId2, clientId3],
+ relevant_pending_ids,
+ 'Querying the state should return requested locks in the order they were '
+ + 'requested.');
+
+ // Add the second group of requests from the clients in a new order.
+ postToFrameAndWait(frame3, {op: 'request', name: resourceName});
+ postToFrameAndWait(frame1, {op: 'request', name: resourceName});
+ postToFrameAndWait(frame2, {op: 'request', name: resourceName});
+
+ // Release locks such that only the newly added locks are requested. This
+ // acts like a checkpoint for the newly queued requests.
+ firstRequestGroupReleaseFunction();
+ await lockPromise1;
+ await postToFrameAndWait(frame1, {op: 'release', lock_id: lockId1});
+ await lockPromise2;
+ await postToFrameAndWait(frame2, {op: 'release', lock_id: lockId2});
+
+ // Query the state and test the new ordering.
+ const state2 = await navigator.locks.query();
+ const relevant_pending_ids2 = state2.pending
+ .filter(lock => [clientId1, clientId2, clientId3].includes(lock.clientId))
+ .map(lock => lock.clientId);
+ assert_array_equals(
+ [clientId3, clientId1, clientId2],
+ relevant_pending_ids2,
+ 'Querying the state should return requested locks in the order they were '
+ + 'requested.');
+
+}, 'Requests appear in state in order made.');
+</script>