Chromium Code Reviews| Index: third_party/WebKit/LayoutTests/storage/indexeddb/upgrade-transaction-lifecycle-backend-aborted.html |
| diff --git a/third_party/WebKit/LayoutTests/storage/indexeddb/upgrade-transaction-lifecycle-backend-aborted.html b/third_party/WebKit/LayoutTests/storage/indexeddb/upgrade-transaction-lifecycle-backend-aborted.html |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d85321244ebfbd9fc88c5ed5412746a7e596b912 |
| --- /dev/null |
| +++ b/third_party/WebKit/LayoutTests/storage/indexeddb/upgrade-transaction-lifecycle-backend-aborted.html |
| @@ -0,0 +1,144 @@ |
| +<!doctype html> |
| +<title>IndexedDB: backend-aborted versionchange transaction lifecycle</title> |
| +<link rel="help" |
| + href="https://w3c.github.io/IndexedDB/#upgrade-transaction-steps"> |
| +<link rel="help" |
| + href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-createobjectstore"> |
| +<link rel="help" |
| + href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-deleteobjectstore"> |
| +<link rel="author" href="pwnall@chromium.org" title="Victor Costan"> |
| +<script src="../../resources/testharness.js"></script> |
| +<script src="../../resources/testharnessreport.js"></script> |
| +<script src="resources/support-promises.js"></script> |
| +<script> |
| +'use strict'; |
| + |
| +promise_test(t => { |
| + let timeoutPromise = null, abortPromise = null; |
| + return createDatabase(t, database => { |
| + createBooksStore(t, database); |
| + }).then(database => { |
| + database.close(); |
| + }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
| + createNotBooksStore(t, database); |
| + |
| + // Queue I/O operations to make sure the transaction does not complete |
|
jsbell
2016/12/19 18:01:30
This isn't guaranteed. The setTimeout(0) could fir
pwnall
2016/12/20 02:46:34
Yes :(
I don't know how to do better here, though.
|
| + // before setTimeout's callback is called. |
| + const store = transaction.objectStore('books'); |
| + for (let i = 0; i < 1000; ++i) |
| + store.put({ title: 'Bedrock Nights ' + i, author: 'Barney' }); |
| + |
| + let abortFired = false; |
| + abortPromise = new Promise((resolve, reject) => { |
| + transaction.addEventListener('abort', () => { |
| + abortFired = true; |
| + resolve(); |
| + }, false); |
| + }); |
| + |
| + timeoutPromise = new Promise((resolve, reject) => { |
| + setTimeout(() => { |
| + const testStepPromise = new Promise((resolve, reject) => { |
| + assert_false( |
| + abortFired, |
| + 'The abort event should fire after setTimeout expires'); |
| + assert_equals( |
| + request.transaction, transaction, |
| + "The open request's transaction should be reset after onabort"); |
| + assert_throws( |
| + 'TransactionInactiveError', |
| + () => { database.createObjectStore('books2'); }, |
| + 'createObjectStore exception should reflect that the ' + |
| + 'transaction is still running'); |
| + assert_throws( |
| + 'TransactionInactiveError', |
| + () => { database.deleteObjectStore('books'); }, |
| + 'deleteObjectStore exception should reflect that the ' + |
| + 'transaction is still running'); |
| + resolve(); |
| + }); |
| + resolve(testStepPromise); |
| + }, 0); |
| + }); |
| + |
| + transaction.objectStore('books').add(BOOKS_RECORD_DATA[0]); |
| + transaction._willBeAborted(); |
| + })).then(() => Promise.all([timeoutPromise, abortPromise])); |
| +}, 'in a setTimeout(0) callback after a failing request is issued, before ' + |
|
jsbell
2016/12/19 18:01:30
I'm not sure you'll be able to reliably test for t
pwnall
2016/12/20 02:46:34
Ack :(
I agree with the statements above. It's tem
|
| + 'the abort event is fired'); |
| + |
| +promise_test(t => { |
| + let abortPromise = null; |
| + return createDatabase(t, database => { |
| + createBooksStore(t, database); |
| + }).then(database => { |
| + database.close(); |
| + }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
|
jsbell
2016/12/19 18:01:30
I think the test would be more readable if this fu
pwnall
2016/12/20 02:46:34
Done.
I hadn't done that before because migrateDat
|
| + abortPromise = new Promise((resolve, reject) => { |
| + transaction.addEventListener('abort', () => { |
| + const testStepPromise = new Promise((resolve, reject) => { |
|
jsbell
2016/12/19 18:01:30
I don't think this Promise does anything useful he
pwnall
2016/12/20 02:46:34
Unfortunately, some sort of wrapping is required t
|
| + assert_equals( |
| + request.transaction, transaction, |
| + "The open request's transaction should be reset after onabort"); |
| + assert_throws( |
| + 'InvalidStateError', |
| + () => { database.createObjectStore('books2'); }, |
| + 'createObjectStore exception should reflect that the ' + |
| + 'transaction is no longer running'); |
| + assert_throws( |
| + 'InvalidStateError', |
| + () => { database.deleteObjectStore('books'); }, |
| + 'deleteObjectStore exception should reflect that the ' + |
| + 'transaction is no longer running'); |
| + |
| + resolve(); |
| + }); |
| + resolve(testStepPromise); |
| + }, false); |
| + transaction.objectStore('books').add(BOOKS_RECORD_DATA[0]); |
| + transaction._willBeAborted(); |
| + }); |
| + })).then(() => abortPromise); |
| +}, 'while the abort event is fired due to a bad request'); |
|
jsbell
2016/12/19 18:01:30
Can you reword this description? It looks like it'
pwnall
2016/12/20 02:46:34
Done.
I tried to use better descriptions.
|
| + |
| +promise_test(t => { |
| + let abortPromise = null; |
| + return createDatabase(t, database => { |
| + createBooksStore(t, database); |
| + }).then(database => { |
| + database.close(); |
| + }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
|
jsbell
2016/12/19 18:01:30
Same as above; this can just return abortPromise
pwnall
2016/12/20 02:46:34
Done.
|
| + abortPromise = new Promise((resolve, reject) => { |
| + transaction.addEventListener('abort', () => { |
| + const timeoutPromise = new Promise((resolve, reject) => { |
| + setTimeout(() => { |
| + const testStepPromise = new Promise((resolve, reject) => { |
|
jsbell
2016/12/19 18:01:30
Same comment here about testStepPromise above - it
pwnall
2016/12/20 02:46:34
Done.
|
| + assert_equals( |
| + request.transaction, null, |
| + "The open request's transaction should be reset after " + |
| + 'onabort microtasks'); |
| + assert_throws( |
| + 'InvalidStateError', |
| + () => { database.createObjectStore('books2'); }, |
| + 'createObjectStore exception should reflect that the ' + |
| + 'transaction is no longer running'); |
| + assert_throws( |
| + 'InvalidStateError', |
| + () => { database.deleteObjectStore('books'); }, |
| + 'deleteObjectStore exception should reflect that the ' + |
| + 'transaction is no longer running'); |
| + resolve(); |
| + }); |
| + resolve(testStepPromise); |
| + }, 0); |
| + }); |
| + resolve(timeoutPromise); |
| + }, false); |
| + transaction.objectStore('books').add(BOOKS_RECORD_DATA[0]); |
| + transaction._willBeAborted(); |
| + }); |
| + })).then(() => abortPromise); |
| +}, 'in a setTimeout(0) callback after the abort event is fired due to a bad ' + |
| + 'request'); |
| + |
| +</script> |