forked from web-platform-tests/wpt
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WPT: Upstream and add some transaction scheduling tests (web-platform…
…-tests#22027) In service of w3c/IndexedDB#253 move some transaction scheduling tests from Blink to WPT. This involved converting them from js-test.js to testharness.js, but the overall logic of each test was retained. This also adds one new test which verifies the change described in w3c/IndexedDB#319 - all browsers implicitly block R-O transactions behind overlapping R/W transactions. Change-Id: I596aaa75b79bf3bf3e17a2553abb4e11329d59ab Bug: 921193 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2081237 Reviewed-by: Daniel Murphy <[email protected]> Commit-Queue: Joshua Bell <[email protected]> Auto-Submit: Joshua Bell <[email protected]> Cr-Commit-Position: refs/heads/master@{#746553} Co-authored-by: Joshua Bell <[email protected]>
- Loading branch information
1 parent
96e3597
commit 5e1160e
Showing
8 changed files
with
411 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
IndexedDB/transaction-scheduling-across-connections.any.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// META: script=support.js | ||
|
||
indexeddb_test( | ||
(t, db) => { | ||
const store = db.createObjectStore('store'); | ||
}, | ||
|
||
(t, db1) => { | ||
// Open a second connection to the same database. | ||
const open_request = indexedDB.open(db1.name); | ||
open_request.onerror = t.unreached_func('open() should succeed'); | ||
open_request.onupgradeneeded = | ||
t.unreached_func('second connection should not upgrade'); | ||
open_request.onsuccess = t.step_func(() => { | ||
const db2 = open_request.result; | ||
t.add_cleanup(() => { db2.close(); }); | ||
|
||
const transaction1 = db1.transaction('store', 'readwrite'); | ||
transaction1.onabort = t.unreached_func('transaction1 should complete'); | ||
|
||
const transaction2 = db2.transaction('store', 'readwrite'); | ||
transaction2.onabort = t.unreached_func('transaction2 should complete'); | ||
|
||
let transaction1PutSuccess = false; | ||
let transaction1Complete = false; | ||
let transaction2PutSuccess = false; | ||
|
||
// Keep transaction1 alive for a while and ensure transaction2 | ||
// doesn't start. | ||
|
||
let count = 0; | ||
(function doTransaction1Put() { | ||
const request = transaction1.objectStore('store').put(1, count++); | ||
request.onerror = t.unreached_func('request should succeed'); | ||
request.onsuccess = t.step_func(evt => { | ||
transaction1PutSuccess = true; | ||
if (count < 5) { | ||
doTransaction1Put(); | ||
} | ||
}); | ||
}()); | ||
|
||
transaction1.oncomplete = t.step_func(evt => { | ||
transaction1Complete = true; | ||
assert_false( | ||
transaction2PutSuccess, | ||
'transaction1 should complete before transaction2 put succeeds'); | ||
}); | ||
|
||
const request = transaction2.objectStore('store').put(2, 0); | ||
request.onerror = t.unreached_func('request should succeed'); | ||
request.onsuccess = t.step_func(evt => { | ||
transaction2PutSuccess = true; | ||
assert_true( | ||
transaction1Complete, | ||
'transaction2 put should not succeed before transaction1 completes'); | ||
}); | ||
|
||
transaction2.oncomplete = t.step_func_done(evt => { | ||
assert_true( | ||
transaction1PutSuccess, | ||
'transaction1 put should succeed before transaction2 runs'); | ||
assert_true( | ||
transaction1Complete, | ||
'transaction1 should complete before transaction2 runs'); | ||
assert_true( | ||
transaction2PutSuccess, | ||
'transaction2 put should succeed before transaction2 completes'); | ||
}); | ||
}); | ||
}, | ||
"Check that readwrite transactions with overlapping scopes do not run in parallel."); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// META: script=support.js | ||
|
||
indexeddb_test( | ||
(t, db) => { | ||
const store = db.createObjectStore('store'); | ||
}, | ||
|
||
(t, db1) => { | ||
// Open a second database. | ||
const db2name = db1.name + '-2'; | ||
const delete_request = indexedDB.deleteDatabase(db2name); | ||
delete_request.onerror = t.unreached_func('deleteDatabase() should succeed'); | ||
const open_request = indexedDB.open(db2name, 1); | ||
open_request.onerror = t.unreached_func('open() should succeed'); | ||
open_request.onupgradeneeded = t.step_func(() => { | ||
const db2 = open_request.result; | ||
const store = db2.createObjectStore('store'); | ||
}); | ||
open_request.onsuccess = t.step_func(() => { | ||
const db2 = open_request.result; | ||
t.add_cleanup(() => { | ||
db2.close(); | ||
indexedDB.deleteDatabase(db2.name); | ||
}); | ||
|
||
let transaction1PutSuccess = false; | ||
let transaction2PutSuccess = false; | ||
|
||
const onTransactionComplete = barrier_func(2, t.step_func_done(() => { | ||
assert_true(transaction1PutSuccess, | ||
'transaction1 should have executed at least one request'); | ||
assert_true(transaction2PutSuccess, | ||
'transaction1 should have executed at least one request'); | ||
})); | ||
|
||
|
||
const transaction1 = db1.transaction('store', 'readwrite'); | ||
transaction1.onabort = t.unreached_func('transaction1 should complete'); | ||
transaction1.oncomplete = t.step_func(onTransactionComplete); | ||
|
||
const transaction2 = db2.transaction('store', 'readwrite'); | ||
transaction2.onabort = t.unreached_func('transaction2 should complete'); | ||
transaction2.oncomplete = t.step_func(onTransactionComplete); | ||
|
||
// Keep both transactions alive until each has reported at least one | ||
// successful operation. | ||
|
||
function doTransaction1Put() { | ||
const request = transaction1.objectStore('store').put(0, 0); | ||
request.onerror = t.unreached_func('put request should succeed'); | ||
request.onsuccess = t.step_func(() => { | ||
transaction1PutSuccess = true; | ||
if (!transaction2PutSuccess) | ||
doTransaction1Put(); | ||
}); | ||
} | ||
|
||
function doTransaction2Put() { | ||
const request = transaction2.objectStore('store').put(0, 0); | ||
request.onerror = t.unreached_func('put request should succeed'); | ||
request.onsuccess = t.step_func(() => { | ||
transaction2PutSuccess = true; | ||
if (!transaction1PutSuccess) | ||
doTransaction2Put(); | ||
}); | ||
} | ||
|
||
doTransaction1Put(); | ||
doTransaction2Put(); | ||
}); | ||
}, | ||
"Check that transactions in different databases can run in parallel."); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// META: script=support.js | ||
|
||
indexeddb_test( | ||
(t, db) => { | ||
const store = db.createObjectStore('store'); | ||
db.createObjectStore('a'); | ||
db.createObjectStore('b'); | ||
db.createObjectStore('c'); | ||
}, | ||
|
||
(t, db) => { | ||
let transaction1Started = false; | ||
let transaction1Complete = false; | ||
let transaction2Started = false; | ||
let transaction2Complete = false; | ||
let transaction3Started = false; | ||
let transaction3Complete = false; | ||
|
||
const transaction1 = db.transaction(['a'], 'readonly'); | ||
let request = transaction1.objectStore('a').get(0); | ||
request.onerror = t.unreached_func('request should succeed'); | ||
request.onsuccess = t.step_func(() => { | ||
transaction1Started = true; | ||
}); | ||
transaction1.onabort = t.unreached_func('transaction1 should complete'); | ||
transaction1.oncomplete = t.step_func(() => { | ||
transaction1Complete = true; | ||
assert_false(transaction2Started); | ||
assert_false(transaction3Started); | ||
}); | ||
|
||
|
||
// transaction2 overlaps with transaction1, so must wait until transaction1 | ||
// completes. | ||
const transaction2 = db.transaction(['a', 'b'], 'readwrite'); | ||
request = transaction2.objectStore('a').get(0); | ||
request.onerror = t.unreached_func('request should succeed'); | ||
request.onsuccess = t.step_func(() => { | ||
assert_true(transaction1Complete); | ||
transaction2Started = true; | ||
}); | ||
transaction2.onabort = t.unreached_func('transaction2 should complete'); | ||
transaction2.oncomplete = t.step_func(() => { | ||
transaction2Complete = true; | ||
assert_false(transaction3Started); | ||
}); | ||
|
||
// transaction3 overlaps with transaction2, so must wait until transaction2 | ||
// completes even though it does not overlap with transaction1. | ||
const transaction3 = db.transaction(['b', 'c'], 'readonly'); | ||
request = transaction3.objectStore('b').get(0); | ||
request.onerror = t.unreached_func('request should succeed'); | ||
request.onsuccess = t.step_func(() => { | ||
assert_true(transaction1Complete); | ||
assert_true(transaction2Complete); | ||
transaction3Started = true; | ||
}); | ||
transaction3.onabort = t.unreached_func('transaction3 should complete'); | ||
transaction3.oncomplete = t.step_func_done(() => { | ||
transaction3Complete = true; | ||
}); | ||
}, | ||
"Check that scope restrictions on mixed transactions are enforced."); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// META: script=support.js | ||
|
||
indexeddb_test( | ||
(t, db) => { | ||
const store = db.createObjectStore('store'); | ||
}, | ||
|
||
(t, db) => { | ||
// Create in order tx1, tx2. | ||
const tx1 = db.transaction('store', 'readwrite'); | ||
const tx2 = db.transaction('store', 'readwrite'); | ||
|
||
// Use in order tx2, tx1. | ||
tx2.objectStore('store').get(0); | ||
tx1.objectStore('store').get(0); | ||
|
||
const order = []; | ||
const done = barrier_func(2, t.step_func_done(() => { | ||
// IndexedDB Spec: | ||
// https://w3c.github.io/IndexedDB/#transaction-scheduling | ||
// | ||
// If multiple "readwrite" transactions are attempting to | ||
// access the same object store (i.e. if they have overlapping | ||
// scope), the transaction that was created first must be the | ||
// transaction which gets access to the object store first. | ||
// | ||
assert_array_equals(order, [1, 2]); | ||
})); | ||
|
||
tx1.oncomplete = t.step_func(e => { | ||
order.push(1); | ||
done(); | ||
}); | ||
|
||
tx2.oncomplete = t.step_func(e => { | ||
order.push(2); | ||
done(); | ||
}); | ||
}, | ||
"Verify Indexed DB transactions are ordered per spec"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// META: script=support.js | ||
|
||
indexeddb_test( | ||
(t, db) => { | ||
const store = db.createObjectStore('store'); | ||
store.put('value', 'key'); | ||
}, | ||
|
||
(t, db) => { | ||
const transaction1 = db.transaction('store', 'readwrite'); | ||
transaction1.onabort = t.unreached_func('transaction1 should not abort'); | ||
|
||
const transaction2 = db.transaction('store', 'readonly'); | ||
transaction2.onabort = t.unreached_func('transaction2 should not abort'); | ||
|
||
const request = transaction1.objectStore('store').put('new value', 'key'); | ||
request.onerror = t.unreached_func('request should not fail'); | ||
|
||
const request2 = transaction2.objectStore('store').get('key'); | ||
request2.onerror = t.unreached_func('request2 should not fail'); | ||
request2.onsuccess = t.step_func_done(evt => { | ||
assert_equals(request2.result, 'new value', | ||
'Request should see new value.'); | ||
}); | ||
}, | ||
"readonly transaction should see the result of a previous readwrite transaction"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// META: script=support.js | ||
|
||
indexeddb_test( | ||
(t, db) => { | ||
const store = db.createObjectStore('store'); | ||
db.createObjectStore('a'); | ||
db.createObjectStore('b'); | ||
db.createObjectStore('c'); | ||
}, | ||
|
||
(t, db) => { | ||
let transaction1Started = false; | ||
let transaction1Complete = false; | ||
let transaction2Started = false; | ||
let transaction2Complete = false; | ||
let transaction3Started = false; | ||
let transaction3Complete = false; | ||
|
||
const transaction1 = db.transaction(['a'], 'readwrite'); | ||
let request = transaction1.objectStore('a').get(0); | ||
request.onerror = t.unreached_func('request should succeed'); | ||
request.onsuccess = t.step_func(() => { | ||
transaction1Started = true; | ||
}); | ||
transaction1.onabort = t.unreached_func('transaction1 should complete'); | ||
transaction1.oncomplete = t.step_func(() => { | ||
transaction1Complete = true; | ||
assert_false(transaction2Started); | ||
assert_false(transaction3Started); | ||
}); | ||
|
||
|
||
// transaction2 overlaps with transaction1, so must wait until transaction1 | ||
// completes. | ||
const transaction2 = db.transaction(['a', 'b'], 'readwrite'); | ||
request = transaction2.objectStore('a').get(0); | ||
request.onerror = t.unreached_func('request should succeed'); | ||
request.onsuccess = t.step_func(() => { | ||
assert_true(transaction1Complete); | ||
transaction2Started = true; | ||
}); | ||
transaction2.onabort = t.unreached_func('transaction2 should complete'); | ||
transaction2.oncomplete = t.step_func(() => { | ||
transaction2Complete = true; | ||
assert_false(transaction3Started); | ||
}); | ||
|
||
// transaction3 overlaps with transaction2, so must wait until transaction2 | ||
// completes even though it does not overlap with transaction1. | ||
const transaction3 = db.transaction(['b', 'c'], 'readwrite'); | ||
request = transaction3.objectStore('b').get(0); | ||
request.onerror = t.unreached_func('request should succeed'); | ||
request.onsuccess = t.step_func(() => { | ||
assert_true(transaction1Complete); | ||
assert_true(transaction2Complete); | ||
transaction3Started = true; | ||
}); | ||
transaction3.onabort = t.unreached_func('transaction3 should complete'); | ||
transaction3.oncomplete = t.step_func_done(() => { | ||
transaction3Complete = true; | ||
}); | ||
}, | ||
"Check that scope restrictions on read-write transactions are enforced."); |
Oops, something went wrong.