if (this.importScripts) {
importScripts('../../../resources/js-test.js');
importScripts('shared.js');
}
description("Test IndexedDB's cursor skips deleted entries.");
var names = ['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo', 'Foxtrot', 'Golf',
'Hotel', 'India', 'Juliet', 'Kilo', 'Lima', 'Mike', 'November',
'Oscar', 'Papa', 'Quebec', 'Romeo', 'Sierra', 'Tango', 'Uniform',
'Victor', 'Whiskey', 'X-ray', 'Yankee', 'Zulu'];
indexedDBTest(prepareDatabase, basicCursorTest);
function prepareDatabase()
{
db = event.target.result;
debug("setVersionSuccess():");
self.trans = evalAndLog("trans = event.target.transaction");
shouldBeNonNull("trans");
trans.onabort = unexpectedAbortCallback;
var objectStore = evalAndLog("objectStore = db.createObjectStore('store', {keyPath: 'id'})");
evalAndLog("objectStore.createIndex('nameIndex', 'name')");
resetObjectStore(function() {});
}
var silentErrorHandler = function() { event.preventDefault(); }
function resetObjectStore(callback)
{
debug("\nresetObjectStore():");
if (callback === undefined)
callback = function () {};
var objectStore = trans.objectStore('store');
for (var i = 0; i < names.length; i++)
objectStore.delete(i).onerror = silentErrorHandler;
for (var i = 0; i < names.length; i++)
objectStore.add({id: i, name: names[i]}).onerror = unexpectedErrorCallback;
debug("");
callback();
}
function contains(arr, obj)
{
for (var i = 0; i < arr.length; i++) {
if (arr[i] == obj)
return true;
}
return false;
}
var cursor;
var deleted;
var seen;
function testCursor(deleteList, createCursorCommand, callback)
{
debug("\ntestCursor():");
deleted = [];
seen = [];
// Create the cursor.
request = evalAndLog(createCursorCommand);
request.onerror = unexpectedErrorCallback;
request.onsuccess = function () {
if (event.target.result == null) {
// Make sure we have seen every non-deleted item.
for (var i = 0; i < names.length; i++) {
if (contains(deleted, i))
continue;
if (!contains(seen, i))
testFailed("Cursor did not see item with id: " + i);
}
// Make sure we used every rule in |deleteList|.
for (var i = 0; i < deleteList.length; i++) {
if (!contains(seen, deleteList[i].id))
testFailed("deleteList rule with id: " + deleteList[i].id + " was never used.");
}
debug("");
callback();
return;
}
cursor = event.target.result;
debug(event.target.result.value.id + ": " + event.target.result.value.name);
seen.push(event.target.result.value.id);
// Make sure we don't see any deleted items.
if (contains(deleted, event.target.result.value.id))
testFailed("Cursor hit previously deleted element.");
for (var i = 0; i < deleteList.length; i++) {
if (event.target.result.value.id == deleteList[i].id) {
// Delete objects targeted by this id.
var targets = deleteList[i].targets;
for (var j = 0; j < targets.length; j++) {
deleted.push(targets[j]);
request = evalAndLog("request = trans.objectStore('store').delete(" + targets[j] + ")");
request.onerror = unexpectedErrorCallback;
if (j == targets.length - 1)
request.onsuccess = function() { cursor.continue(); }
}
return;
}
}
cursor.continue();
}
}
function basicCursorTest()
{
debug("basicCursorTest()");
evalAndLog("trans = db.transaction(['store'], 'readwrite')");
trans.onabort = unexpectedAbortCallback;
trans.oncomplete = transactionComplete;
var deletes = [{id: 1, targets: [0]},
{id: 2, targets: [names.length - 1]},
{id: 3, targets: [5,6,7]},
{id: 10, targets: [10]},
{id: 12, targets: [13]},
{id: 15, targets: [14]},
{id: 20, targets: [17,18]}
];
testCursor(deletes, "trans.objectStore('store').openCursor(IDBKeyRange.lowerBound(0))", function() { resetObjectStore(reverseCursorTest); });
}
function reverseCursorTest()
{
debug("reverseCursorTest():");
var deletes = [{id: 24, targets: [names.length - 1]},
{id: 23, targets: [0]},
{id: 22, targets: [20, 19, 18]},
{id: 15, targets: [15]},
{id: 13, targets: [12]},
{id: 10, targets: [11]},
{id: 5, targets: [7,8]}
];
testCursor(deletes, "trans.objectStore('store').openCursor(IDBKeyRange.lowerBound(0), 'prev')", function() { resetObjectStore(indexCursorTest); });
}
function indexCursorTest()
{
debug("indexCursorTest():");
var deletes = [{id: 1, targets: [0]},
{id: 2, targets: [names.length - 1]},
{id: 3, targets: [5,6,7]},
{id: 10, targets: [10]},
{id: 12, targets: [13]},
{id: 15, targets: [14]},
{id: 20, targets: [17,18]}
];
testCursor(deletes, "trans.objectStore('store').index('nameIndex').openCursor(IDBKeyRange.lowerBound('Alpha'))", function() { });
}
function transactionComplete()
{
debug("transactionComplete():");
finishJSTest();
}