Chromium Code Reviews| Index: third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interleaved-cursors.html |
| diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interleaved-cursors.html b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interleaved-cursors.html |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7de7f470cdc70560d15f4bd976b964bb1594349c |
| --- /dev/null |
| +++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interleaved-cursors.html |
| @@ -0,0 +1,108 @@ |
| +<!doctype html> |
|
jsbell
2017/03/22 22:35:33
I don't think this is appropriate for wpt - it's n
pwnall
2017/03/23 03:18:57
I thought it would be useful to contribute this to
|
| +<meta charset="utf-8"> |
| +<title>IndexedDB: Interleaved iteration of multiple cursors</title> |
| +<script src="/resources/testharness.js"></script> |
| +<script src="/resources/testharnessreport.js"></script> |
| +<script src="support-promises.js"></script> |
| +<script> |
| +// Number of objects that each iterator goes over. |
| +const itemCount = 10; |
| +// Ratio of small objects to large objects. |
| +const largeObjectRatio = 5; |
| +// Size of large objects. This should be big enough to force the next object to |
| +// spill to a different block. |
|
jsbell
2017/03/22 22:35:33
This is a very implementation-specific assumption.
pwnall
2017/03/23 03:18:57
I meant "block in the backend used by IndexedDB".
|
| +const largeObjectSize = 48 * 1024; |
| + |
| +function objectKey(cursorIndex, itemIndex) { |
| + return `${cursorIndex}-key-${itemIndex}`; |
| +} |
| + |
| +function objectValue(cursorIndex, itemIndex) { |
| + if (itemIndex % 2 === 0) { |
| + const char = String.fromCharCode( |
|
jsbell
2017/03/22 22:35:33
WDTY about using a Uint8Array() to get an exact by
pwnall
2017/03/23 03:18:57
Done.
I didn't use crypto.getRandomValues() becau
|
| + 32 + (cursorIndex * itemCount + itemIndex) % (128 - 32)); |
| + return new Array(largeObjectSize + 1).join(char); |
| + } |
| + return `${cursorIndex}-small-${itemIndex}`; |
| +} |
| + |
| +function writeObjects(testCase, database, cursorCount, cursorIndex) { |
| + if (cursorCount == cursorIndex) |
| + return Promise.resolve(); |
| + |
| + return new Promise((resolve, reject) => { |
| + const transaction = database.transaction('cache', 'readwrite'); |
|
jsbell
2017/03/22 22:35:33
Can you explain/document why we're writing the obj
pwnall
2017/03/23 03:18:57
Done.
I don't have an explanation for the promise
|
| + const store = transaction.objectStore('cache'); |
| + for (let i = 0; i < itemCount; ++i) { |
| + store.put({ |
| + key: objectKey(cursorIndex, i), value: objectValue(cursorIndex, i)}); |
| + } |
| + transaction.oncomplete = resolve; |
| + transaction.onerror = testCase.unreached_func( |
| + 'write transaction should not fail'); |
| + }).then(() => { |
| + return writeObjects(testCase, database, cursorCount, cursorIndex + 1); |
| + }); |
| +} |
| + |
| +function readObjects(testCase, store, cursorCount) { |
| + const cursors = new Array(cursorCount); |
|
jsbell
2017/03/22 22:35:33
I'd just use `cursors = []` - the Array constructo
jsbell
2017/03/22 22:35:33
Also, you may as well pull this and itemIndex into
pwnall
2017/03/23 03:18:57
Done.
pwnall
2017/03/23 03:18:57
Done.
|
| + |
| + let itemIndex = 0; |
| + |
| + return new Promise((resolve, reject) => { |
| + const startCursor = (cursorIndex) => { |
| + const request = store.openCursor( |
| + IDBKeyRange.lowerBound(objectKey(cursorIndex, 0))); |
| + |
| + request.onsuccess = testCase.step_func(() => { |
| + const cursor = request.result; |
| + cursors[cursorIndex] = cursor; |
| + |
| + assert_equals(cursor.key, objectKey(cursorIndex, itemIndex)); |
| + assert_equals(cursor.value.key, objectKey(cursorIndex, itemIndex)); |
| + assert_equals(cursor.value.value, objectValue(cursorIndex, itemIndex)); |
| + |
|
dmurph
2017/03/22 23:34:54
I'm really confused about what's happening here...
pwnall
2017/03/23 03:18:57
I split up the logic so it's clearer what the curr
|
| + let nextCursorIndex = cursorIndex + 1; |
| + if (nextCursorIndex == cursorCount) { |
| + nextCursorIndex = 0; |
| + itemIndex += 1; |
| + } |
| + |
| + if (!itemIndex) { |
| + startCursor(nextCursorIndex); |
| + } else if (itemIndex == itemCount) { |
| + resolve(); |
| + } else { |
| + cursors[nextCursorIndex].continue(); |
| + } |
| + }); |
| + }; |
| + |
| + startCursor(0); |
| + }); |
| +} |
| + |
| +for (let i of [1, 10, 100, 500]) { |
| + const cursorCount = i; |
|
jsbell
2017/03/22 22:35:33
I don't think this extra const adds a lot here. (A
pwnall
2017/03/23 03:18:57
Done.
|
| + promise_test(testCase => { |
| + return createDatabase(testCase, (database, transaction) => { |
| + const store = database.createObjectStore('cache', |
| + { keyPath: 'key', autoIncrement: true }); |
| + }).then(database => { |
| + return writeObjects(testCase, database, cursorCount, 0).then( |
| + () => database); |
|
jsbell
2017/03/22 22:35:33
(rant: someday we'll be able to use async/await...
pwnall
2017/03/23 03:18:57
Done.
pwnall
2017/03/23 22:09:30
I think I meant to "Done" the above comment. Whoop
|
| + }).then(database => { |
| + database.close(); |
| + }).then(() => { |
| + return openDatabase(testCase); |
| + }).then(database => { |
| + const transaction = database.transaction('cache', 'readonly'); |
| + const store = transaction.objectStore('cache'); |
| + return readObjects(testCase, store, cursorCount).then(() => database); |
| + }).then(database => { |
| + database.close() |
|
jsbell
2017/03/22 22:35:33
Add a test cleanup step to delete the database? Pe
pwnall
2017/03/23 03:18:57
I fixed the helpers :D
|
| + }); |
| + }, `${cursorCount} cursors`); |
| +} |
| +</script> |