if (this.importScripts) { importScripts('../../../resources/js-test.js'); importScripts('shared.js'); } description("Test IndexedDB behavior when iterating backwards with and without NO_DUPLICATE"); indexedDBTest(prepareDatabase, populateStore); function prepareDatabase() { db = event.target.result; store = evalAndLog("store = db.createObjectStore('store')"); evalAndLog("store.createIndex('index', 'sorted')"); } function populateStore() { debug(""); debug("populating store..."); evalAndLog("trans = db.transaction('store', 'readwrite')"); evalAndLog("store = trans.objectStore('store');"); trans.onerror = unexpectedErrorCallback; trans.onabort = unexpectedAbortCallback; evalAndLog("store.put({sorted: 3, value: 111}, 1)"); evalAndLog("store.put({sorted: 2, value: 222}, 2)"); evalAndLog("store.put({sorted: 1, value: 333}, 3)"); evalAndLog("store.put({sorted: 10, value: 444}, 17)"); evalAndLog("store.put({sorted: 10, value: 555}, 16)"); evalAndLog("store.put({sorted: 10, value: 666}, 15)"); trans.oncomplete = testFarRangeCursor_closed; } function testFarRangeCursor_closed() { debug(""); debug("testFarRangeCursor: upper bound is well out of range, results always the same, whether open or closed"); runTest(makeOpenCursor("store", 7, false, "'prev'"), { expectedValue: 333, expectedKey: 3}, testFarRangeCursor_open); } function testFarRangeCursor_open() { runTest(makeOpenCursor("store", 7, true, "'prev'"), { expectedValue: 333, expectedKey: 3}, testFarRangeCursor_indexClosed); } function testFarRangeCursor_indexClosed() { // here '7' refers to the 'sorted' value runTest(makeOpenCursor("index", 7, false, "'prev'"), { expectedValue: 111, expectedKey: 3, expectedPrimaryKey: 1}, testFarRangeCursor_indexOpen); } function testFarRangeCursor_indexOpen() { runTest(makeOpenCursor("index", 7, true, "'prev'"), { expectedValue: 111, expectedKey: 3, expectedPrimaryKey: 1}, testFarRangeCursor_indexKeyOpen); } function testFarRangeCursor_indexKeyOpen() { // here '7' refers to the sorted value runTest(makeOpenKeyCursor("index", 7, false, "'prev'"), { expectedKey: 3, expectedPrimaryKey: 1}, testFarRangeCursor_indexKeyClosed); } function testFarRangeCursor_indexKeyClosed() { runTest(makeOpenKeyCursor("index", 7, true, "'prev'"), { expectedKey: 3, expectedPrimaryKey: 1}, testBoundaryCursor_closed); } function testBoundaryCursor_closed() { runTest(makeOpenCursor("store", 3, false, "'prev'"), { expectedValue: 333, expectedKey: 3}, testBoundaryCursor_open); }; function testBoundaryCursor_open() { runTest(makeOpenCursor("store", 3, true, "'prev'"), { expectedValue: 222, expectedKey: 2}, testBoundaryCursor_indexClosed); } function testBoundaryCursor_indexClosed() { // by index sort order, we should return them in a different order runTest(makeOpenCursor("index", 3, false, "'prev'"), { expectedValue: 111, expectedKey: 3, expectedPrimaryKey: 1}, testBoundaryCursor_indexOpen); } function testBoundaryCursor_indexOpen() { runTest(makeOpenCursor("index", 3, true, "'prev'"), { expectedValue: 222, expectedKey: 2, expectedPrimaryKey: 2}, testBoundaryCursor_indexKeyClosed); } function testBoundaryCursor_indexKeyClosed() { // now the value doesn't matter, just the primary key runTest(makeOpenKeyCursor("index", 3, false, "'prev'"), { expectedKey: 3, expectedPrimaryKey: 1}, testBoundaryCursor_indexKeyOpen); } function testBoundaryCursor_indexKeyOpen() { runTest(makeOpenKeyCursor("index", 3, true, "'prev'"), { expectedKey: 2, expectedPrimaryKey: 2}, testNoDuplicate_closed); } function testNoDuplicate_closed() { debug("testNoDuplicate: there are 3 values, but we should return always the first one"); // PREV_NO_DUPLICATE doesn't really affect non-indexed // cursors, but we should make sure we get the right one // anyway runTest(makeOpenCursor("store", 15, false, "'prevunique'"), { expectedValue: 666, expectedKey: 15, expectedPrimaryKey: 15 }, testNoDuplicate_open); } function testNoDuplicate_open() { // still three values, but now the index says we should return the // second one runTest(makeOpenCursor("index", 15, false, "'prevunique'"), { expectedValue: 666, expectedKey: 10, expectedPrimaryKey: 15}, testNoDuplicate_indexKeyClosed); } function testNoDuplicate_indexKeyClosed() { // same behavior as above, without a value runTest(makeOpenKeyCursor("index", 15, false, "'prevunique'"), { expectedKey: 10, expectedPrimaryKey: 15}, finishJSTest); } function makeOpenCursor(obj, upperBound, open, direction) { return obj + ".openCursor(IDBKeyRange.upperBound(" + upperBound + ", " + open + "), " + direction + ")"; } function makeOpenKeyCursor(obj, upperBound, open, direction) { return obj + ".openKeyCursor(IDBKeyRange.upperBound(" + upperBound + ", " + open + "), " + direction + ")"; } function runTest(openCursor, expectation, callback) { trans = db.transaction('store', 'readonly'); // expose these for code in openCursor store = trans.objectStore('store'); index = store.index('index'); trans.onerror = unexpectedErrorCallback; trans.onabort = unexpectedAbortCallback; trans.oncomplete = function() { debug("DONE"); debug(""); callback(); }; storeReq = evalAndLog("storeReq = " + openCursor); storeReq.onsuccess = function() { cursor = event.target.result; if (cursor === null) { testFailed("null cursor"); return; } shouldBe("cursor.key", JSON.stringify(expectation.expectedKey)); if ("value" in cursor) { shouldBe("cursor.value.value", JSON.stringify(expectation.expectedValue)); } else if ("expectedValue" in expectation) testFailed("Test broken: shouldn't have expectedValue"); if ("expectedPrimaryKey" in expectation) { shouldBe("cursor.primaryKey", JSON.stringify(expectation.expectedPrimaryKey)); } }; }