| Index: chrome/test/data/indexeddb/cursor_prefetch.js
|
| diff --git a/chrome/test/data/indexeddb/cursor_prefetch.js b/chrome/test/data/indexeddb/cursor_prefetch.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..927461f677be55085a62ce2278330c85252730c6
|
| --- /dev/null
|
| +++ b/chrome/test/data/indexeddb/cursor_prefetch.js
|
| @@ -0,0 +1,394 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +// These constants should match the ones in renderer_webidbcursor_impl.h
|
| +// to make sure the test hits the right code paths.
|
| +var kPrefetchThreshold = 2;
|
| +var kMinPrefetchAmount = 5;
|
| +
|
| +var kNumberOfItems = 200;
|
| +
|
| +function test() {
|
| + indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
|
| + IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction
|
| + IDBCursor = window.IDBCursor || window.webkitIDBCursor;
|
| + IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;
|
| +
|
| + request = indexedDB.open('cursor-prefetch');
|
| + request.onsuccess = openSuccess;
|
| + request.onerror = unexpectedErrorCallback;
|
| +}
|
| +
|
| +function openSuccess() {
|
| + window.db = event.target.result;
|
| +
|
| + request = db.setVersion('new version');
|
| + request.onsuccess = setVersionSuccess;
|
| + request.onerror = unexpectedErrorCallback;
|
| +}
|
| +
|
| +function setVersionSuccess() {
|
| + debug("setVersionSuccess():");
|
| + window.trans = event.target.result;
|
| + shouldBeTrue("trans !== null");
|
| + trans.onabort = unexpectedAbortCallback;
|
| + trans.oncomplete = fillObjectStore;
|
| +
|
| + deleteAllObjectStores(db);
|
| + var store = db.createObjectStore('store');
|
| + store.createIndex('index', '');
|
| +}
|
| +
|
| +function fillObjectStore() {
|
| + debug("fillObjectStore()");
|
| + var trans = db.transaction(['store'], IDBTransaction.READ_WRITE);
|
| + trans.onabort = unexpectedAbortCallback;
|
| + trans.oncomplete = firstTest;
|
| +
|
| + var store = trans.objectStore('store');
|
| + debug("Storing " + kNumberOfItems + " object in the object store.");
|
| + for (var i = 0; i < kNumberOfItems; ++i) {
|
| + var req = store.put(i, i);
|
| + req.onerror = unexpectedErrorCallback;
|
| + }
|
| +
|
| + // Let the transaction finish.
|
| +}
|
| +
|
| +function firstTest() {
|
| + debug("firstTest()");
|
| +
|
| + // Test iterating straight through the object store.
|
| +
|
| + var trans = db.transaction(['store'], IDBTransaction.READ_WRITE);
|
| + trans.onabort = unexpectedAbortCallback;
|
| + trans.oncomplete = secondTest;
|
| +
|
| + var store = trans.objectStore('store');
|
| + var cursorReq = store.openCursor();
|
| + cursorReq.onerror = unexpectedErrorCallback;
|
| +
|
| + count = 0;
|
| + cursorReq.onsuccess = function() {
|
| + cursor = event.target.result;
|
| + if (cursor === null) {
|
| + shouldBe("count", "kNumberOfItems");
|
| + return; // Let the transaction finish.
|
| + }
|
| +
|
| + if (cursor.key !== count)
|
| + shouldBe("cursor.key", "count");
|
| + if (cursor.value !== count)
|
| + shouldBe("cursor.value", "count");
|
| +
|
| + ++count;
|
| +
|
| + cursor.continue();
|
| + }
|
| +}
|
| +
|
| +function secondTest() {
|
| + debug("secondTest()");
|
| +
|
| + // Test iterating through the object store, intermixed with
|
| + // continue calls to specific keys.
|
| +
|
| + var trans = db.transaction(['store'], IDBTransaction.READ_WRITE);
|
| + trans.onabort = unexpectedAbortCallback;
|
| + trans.oncomplete = thirdTest;
|
| +
|
| + var store = trans.objectStore('store');
|
| + var cursorReq = store.openCursor();
|
| + cursorReq.onerror = unexpectedErrorCallback;
|
| +
|
| + var jumpTable = [{from: 5, to: 17},
|
| + {from: 25, to: 30},
|
| + {from: 31, to: 35},
|
| + {from: 70, to: 80},
|
| + {from: 98, to: 99}];
|
| +
|
| + count = 0;
|
| + expectedKey = 0;
|
| +
|
| + cursorReq.onsuccess = function() {
|
| + cursor = event.target.result;
|
| + if (cursor === null) {
|
| + debug("Finished iterating after " + count + " steps.");
|
| + return; // Let the transaction finish.
|
| + }
|
| +
|
| + if (cursor.key !== expectedKey)
|
| + shouldBe("cursor.key", "expectedKey");
|
| + if (cursor.value !== expectedKey)
|
| + shouldBe("cursor.value", "expectedKey");
|
| +
|
| + ++count;
|
| +
|
| + for (var i = 0; i < jumpTable.length; ++i) {
|
| + if (jumpTable[i].from === cursor.key) {
|
| + expectedKey = jumpTable[i].to;
|
| + debug("Jumping from "+ cursor.key + " to " + expectedKey);
|
| + cursor.continue(expectedKey);
|
| + return;
|
| + }
|
| + }
|
| +
|
| + ++expectedKey;
|
| + cursor.continue();
|
| + }
|
| +}
|
| +
|
| +function thirdTest() {
|
| + debug("thirdTest()");
|
| +
|
| + // Test iterating straight through the object store in reverse.
|
| +
|
| + var trans = db.transaction(['store'], IDBTransaction.READ_WRITE);
|
| + trans.onabort = unexpectedAbortCallback;
|
| + trans.oncomplete = fourthTest;
|
| +
|
| + var store = trans.objectStore('store');
|
| + var cursorReq = store.openCursor(
|
| + IDBKeyRange.upperBound(kNumberOfItems-1), IDBCursor.PREV);
|
| + cursorReq.onerror = unexpectedErrorCallback;
|
| +
|
| + count = 0;
|
| + cursorReq.onsuccess = function() {
|
| + cursor = event.target.result;
|
| + if (cursor === null) {
|
| + shouldBe("count", "kNumberOfItems");
|
| + return; // Let the transaction finish.
|
| + }
|
| +
|
| + expectedKey = kNumberOfItems - count - 1;
|
| +
|
| + if (cursor.key !== expectedKey)
|
| + shouldBe("cursor.key", "expectedKey");
|
| + if (cursor.value !== expectedKey)
|
| + shouldBe("cursor.value", "expectedKey");
|
| +
|
| + ++count;
|
| +
|
| + cursor.continue();
|
| + }
|
| +}
|
| +
|
| +function fourthTest() {
|
| + debug("fourthTest()");
|
| +
|
| + // Test iterating, and then stopping before reaching the end.
|
| + // Make sure transaction terminates anyway.
|
| +
|
| + var trans = db.transaction(['store'], IDBTransaction.READ_WRITE);
|
| + trans.onabort = unexpectedAbortCallback;
|
| + trans.oncomplete = function() {
|
| + debug("fourthTest() transaction completed");
|
| + fifthTest();
|
| + }
|
| +
|
| + var store = trans.objectStore('store');
|
| + var cursorReq = store.openCursor();
|
| + cursorReq.onerror = unexpectedErrorCallback;
|
| +
|
| + count = 0;
|
| + cursorReq.onsuccess = function() {
|
| + cursor = event.target.result;
|
| +
|
| + if (cursor.key !== count)
|
| + shouldBe("cursor.key", "count");
|
| + if (cursor.value !== count)
|
| + shouldBe("cursor.value", "count");
|
| +
|
| + ++count;
|
| +
|
| + if (count === 25) {
|
| + // Schedule some other request.
|
| + var otherReq = store.get(42);
|
| + otherReq.onerror = unexpectedErrorCallback;
|
| + otherReq.onsuccess = function() {
|
| + if (count === 25) {
|
| + debug("Other request fired before continue, as expected.");
|
| + } else {
|
| + debug("Other request fired out-of-order!");
|
| + fail();
|
| + }
|
| + }
|
| +
|
| + cursor.continue();
|
| + return;
|
| + }
|
| +
|
| + if (count === 30) {
|
| + // Do a continue first, then another request.
|
| + cursor.continue();
|
| +
|
| + var otherReq = store.get(42);
|
| + otherReq.onerror = unexpectedErrorCallback;
|
| + otherReq.onsuccess = function() {
|
| + if (count === 31) {
|
| + debug("Other request fired right after continue as expected.");
|
| + } else {
|
| + debug("Other request didn't fire right after continue as expected.");
|
| + fail();
|
| + }
|
| + }
|
| +
|
| + return;
|
| + }
|
| +
|
| + if (count === 75) {
|
| + return; // Sudden stop.
|
| + }
|
| +
|
| + cursor.continue();
|
| + }
|
| +}
|
| +
|
| +function fifthTest() {
|
| + debug("fifthTest()");
|
| +
|
| + // Test iterating over the pre-fetch threshold, but make sure the
|
| + // cursor is positioned so that it is actually at the last element
|
| + // in the range when pre-fetch fires, and make sure a null cursor
|
| + // is the result as expected.
|
| +
|
| + var trans = db.transaction(['store'], IDBTransaction.READ_WRITE);
|
| + trans.onabort = unexpectedAbortCallback;
|
| + trans.oncomplete = sixthTest;
|
| +
|
| + var store = trans.objectStore('store');
|
| +
|
| + var startKey = kNumberOfItems - 1 - kPrefetchThreshold;
|
| + var cursorReq = store.openCursor(IDBKeyRange.lowerBound(startKey));
|
| + cursorReq.onerror = unexpectedErrorCallback;
|
| +
|
| + count = 0;
|
| + cursorReq.onsuccess = function() {
|
| + cursor = event.target.result;
|
| +
|
| + if (cursor === null) {
|
| + debug("cursor is null");
|
| + shouldBe("count", "kPrefetchThreshold + 1");
|
| + return;
|
| + }
|
| +
|
| + debug("count: " + count);
|
| + ++count;
|
| + cursor.continue();
|
| + }
|
| +}
|
| +
|
| +function sixthTest() {
|
| + debug("sixthTest()");
|
| +
|
| + // Test stepping two cursors simultaneously. First cursor1 steps
|
| + // for a while, then cursor2, then back to cursor1, etc.
|
| +
|
| + var trans = db.transaction(['store'], IDBTransaction.READ_WRITE);
|
| + trans.onabort = unexpectedAbortCallback;
|
| + trans.oncomplete = seventhTest;
|
| + var store = trans.objectStore('store');
|
| +
|
| + cursor1 = null;
|
| + cursor2 = null;
|
| +
|
| + count1 = 0;
|
| + count2 = 0;
|
| +
|
| + var cursor1func = function() {
|
| + var cursor = event.target.result;
|
| + if (cursor === null) {
|
| + shouldBe("count1", "kNumberOfItems");
|
| + cursor2.continue();
|
| + return;
|
| + }
|
| +
|
| + if (cursor1 === null) {
|
| + cursor1 = cursor;
|
| + }
|
| +
|
| + if (cursor1.key !== count1)
|
| + shouldBe("cursor1.key", "count1");
|
| + if (cursor1.value !== count1)
|
| + shouldBe("cursor1.value", "count1");
|
| +
|
| + ++count1;
|
| +
|
| + if (count1 % 20 === 0) {
|
| + if (cursor2 !== null) {
|
| + cursor2.continue();
|
| + } else {
|
| + var req = store.openCursor();
|
| + req.onerror = unexpectedErrorCallback;
|
| + req.onsuccess = cursor2func;
|
| + }
|
| + } else {
|
| + cursor1.continue();
|
| + }
|
| + }
|
| +
|
| + var cursor2func = function() {
|
| + var cursor = event.target.result;
|
| + if (cursor === null) {
|
| + shouldBe("count2", "kNumberOfItems");
|
| + return;
|
| + }
|
| +
|
| + if (cursor2 === null) {
|
| + cursor2 = cursor;
|
| + }
|
| +
|
| + if (cursor2.key !== count2)
|
| + shouldBe("cursor2.key", "count2");
|
| + if (cursor2.value !== count2)
|
| + shouldBe("cursor2.value", "count2");
|
| +
|
| + ++count2;
|
| +
|
| + if (count2 % 20 === 0) {
|
| + cursor1.continue();
|
| + } else {
|
| + cursor2.continue();
|
| + }
|
| + }
|
| +
|
| + var req = store.openCursor();
|
| + req.onerror = unexpectedErrorCallback;
|
| + req.onsuccess = cursor1func;
|
| +}
|
| +
|
| +function seventhTest() {
|
| + debug("seventhTest()");
|
| +
|
| + // Test iterating straight through an index.
|
| +
|
| + var trans = db.transaction(['store'], IDBTransaction.READ_WRITE);
|
| + trans.onabort = unexpectedAbortCallback;
|
| + trans.oncomplete = done;
|
| +
|
| + var store = trans.objectStore('store');
|
| + var index = store.index('index');
|
| +
|
| + var cursorReq = index.openCursor();
|
| + cursorReq.onerror = unexpectedErrorCallback;
|
| + count = 0;
|
| +
|
| + cursorReq.onsuccess = function() {
|
| + cursor = event.target.result;
|
| + if (cursor === null) {
|
| + shouldBe("count", "kNumberOfItems");
|
| + return;
|
| + }
|
| +
|
| + if (cursor.key !== count)
|
| + shouldBe("cursor.key", "count");
|
| + if (cursor.primaryKey !== count)
|
| + shouldBe("cursor.primaryKey", "count");
|
| + if (cursor.value !== count)
|
| + shouldBe("cursor.value", "count");
|
| +
|
| + ++count;
|
| + cursor.continue();
|
| + }
|
| +}
|
|
|