| if (this.importScripts) { |
| importScripts('../../../resources/js-test.js'); |
| importScripts('shared.js'); |
| } |
| |
| description("Test IndexedDB's IDBCursor.continue() behavior when called beyond normal scope."); |
| |
| var date = new Date(); |
| |
| // we set this pretty high because we get different behavior depending |
| // if we're in a pre-fetched state or not |
| self.testLength = 25; |
| |
| indexedDBTest(prepareDatabase); |
| function prepareDatabase() |
| { |
| db = event.target.result; |
| self.trans = evalAndLog("trans = event.target.transaction"); |
| shouldBeNonNull("trans"); |
| trans.onabort = unexpectedAbortCallback; |
| |
| self.objectStore = evalAndLog("db.createObjectStore('someObjectStore')"); |
| self.indexObject = evalAndLog("objectStore.createIndex('someIndex', 'x')"); |
| self.nextToAdd = 0; |
| addData(); |
| } |
| |
| function addData() |
| { |
| for (var i=0; i<self.testLength; i++) { |
| evalAndLog("objectStore.add({'x': " + i + " }, " + i + ")"); |
| } |
| evalAndLog("continueTest()"); |
| } |
| |
| function continueTest() |
| { |
| debug(""); |
| debug("Checking objectStore"); |
| debug("===================="); |
| var request = evalAndLog("indexObject.openCursor(null, 'next')"); |
| evalAndLog("self.continueValue = 0"); |
| request.onsuccess = evalAndLogCallback("doubleContinueCallback()"); |
| request.onerror = unexpectedErrorCallback; |
| self.stage = 0; |
| } |
| |
| function doubleContinueCallback() |
| { |
| evalAndLog("cursor = event.target.result"); |
| if (cursor) { |
| debug("Checking value at " + self.continueValue); |
| // data should be valid before calling continue() |
| shouldBe("cursor.key", "" + self.continueValue); |
| shouldBe("cursor.value.x", "" + self.continueValue); |
| |
| // Data should not change during iteration, even if continue() is called and extra time. |
| evalAndLog("cursor.continue()"); |
| shouldBe("cursor.key", "" + self.continueValue); |
| shouldBe("cursor.value.x", "" + self.continueValue); |
| |
| // Even if continue is called more than once, the value still shouldn't change. |
| evalAndExpectException("cursor.continue()", "DOMException.INVALID_STATE_ERR"); |
| shouldBe("cursor.key", "" + self.continueValue); |
| shouldBe("cursor.value.x", "" + self.continueValue); |
| evalAndLog("self.continueValue++;"); |
| } else { |
| evalAndLog("continueIndexTest()"); |
| } |
| } |
| |
| function continueIndexTest() |
| { |
| debug(""); |
| debug("Checking index"); |
| debug("=============="); |
| var request = evalAndLog("indexObject.openCursor(null, 'next')"); |
| evalAndLog("self.continueValue = 0"); |
| request.onsuccess = doubleContinueIndexCallback; |
| request.onerror = unexpectedErrorCallback; |
| self.stage = 0; |
| } |
| |
| function doubleContinueIndexCallback() |
| { |
| evalAndLog("cursor = event.target.result"); |
| if (cursor) { |
| debug("Checking value at " + self.continueValue); |
| // data should be valid before calling continue() |
| shouldBe("cursor.key", "" + self.continueValue); |
| shouldBe("cursor.value.x", "" + self.continueValue); |
| |
| // Data should not change during iteration, even if continue() is called and extra time. |
| evalAndLog("cursor.continue()"); |
| shouldBe("cursor.key", "" + self.continueValue); |
| shouldBe("cursor.value.x", "" + self.continueValue); |
| |
| // Even if continue is called more than once, the value still shouldn't change. |
| evalAndExpectException("cursor.continue()", "DOMException.INVALID_STATE_ERR"); |
| shouldBe("cursor.key", "" + self.continueValue); |
| shouldBe("cursor.value.x", "" + self.continueValue); |
| evalAndLog("self.continueValue++;"); |
| } else { |
| evalAndLog("testModifyContinueOrder()"); |
| } |
| |
| } |
| |
| // Note: This mutates the data |
| function testModifyContinueOrder() |
| { |
| debug(""); |
| debug("Checking modification"); |
| debug("====================="); |
| var request = evalAndLog("indexObject.openCursor(null, 'next')"); |
| evalAndLog("self.continueValue = 0"); |
| request.onsuccess = modifyContinueOrderCallback; |
| request.onerror = unexpectedErrorCallback; |
| self.stage = 0; |
| } |
| |
| function modifyContinueOrderCallback() |
| { |
| cursor = evalAndLog("cursor = event.target.result"); |
| |
| self.continueValue++; |
| if (cursor) { |
| debug(""); |
| debug("Index key is: " + cursor.key); |
| debug("Primary key is: " + cursor.primaryKey); |
| debug("Value.x is: " + cursor.value.x); |
| debug("Continue value: " + self.continueValue); |
| |
| // we sprinkle these checks across the dataset, to sample |
| // behavior against pre-fetching. Make sure to use prime |
| // numbers for these checks to avoid overlap. |
| if (self.continueValue % 2 == 0) { |
| // it's ok to call update() and then continue.. |
| debug("New Index key for primary key " + cursor.primaryKey + " is " + (100 + self.continueValue)); |
| evalAndLog("cursor.update({ x: 100 + self.continueValue })"); |
| evalAndLog("cursor.continue()"); |
| } else if (self.continueValue % 3 == 0) { |
| // it's ok to call delete() and then continue |
| debug("Deleting primary key " + cursor.primaryKey + " which currently has Index key " + cursor.key); |
| evalAndLog("cursor.delete()"); |
| evalAndLog("cursor.continue()"); |
| } else if (self.continueValue % 5 == 0) { |
| // it's NOT ok to call continue and then update |
| evalAndLog("cursor.continue()"); |
| debug("Expecting exception setting new Index key for primary key " + cursor.primaryKey + " to " + (100 + self.continueValue)); |
| evalAndExpectException("cursor.update({ x: 100 + self.continueValue})", |
| "DOMException.INVALID_STATE_ERR"); |
| } else if (self.continueValue % 7 == 0) { |
| // it's NOT ok to call continue and then delete |
| evalAndLog("cursor.continue()"); |
| debug("Expecting exception deleting primary key " + cursor.primaryKey + " which currently has Index key " + cursor.key); |
| evalAndExpectException("cursor.delete()", |
| "DOMException.INVALID_STATE_ERR"); |
| } else { |
| evalAndLog("cursor.continue()"); |
| } |
| |
| } else { |
| finishJSTest(); |
| } |
| } |