1 if (this.importScripts) {
2 importScripts('../../../resources/js-test.js');
3 importScripts('shared.js');
6 description("Test IndexedDB cursor.advance().");
8 var objectStoreData = [
9 { key: "237-23-7732", value: { name: "Bob", height: 60, weight: 120 } },
10 { key: "237-23-7733", value: { name: "Ann", height: 52, weight: 110 } },
11 { key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } },
12 { key: "237-23-7735", value: { name: "Sue", height: 58, weight: 130 } },
13 { key: "237-23-7736", value: { name: "Joe", height: 65, weight: 150 } },
14 { key: "237-23-7737", value: { name: "Pat", height: 65, weight: 100 } },
15 { key: "237-23-7738", value: { name: "Leo", height: 65, weight: 180 } },
16 { key: "237-23-7739", value: { name: "Jef", height: 65, weight: 120 } },
17 { key: "237-23-7740", value: { name: "Sam", height: 71, weight: 110 } },
18 { key: "237-23-7741", value: { name: "Bug", height: 63, weight: 100 } },
19 { key: "237-23-7742", value: { name: "Tub", height: 69, weight: 180 } },
20 { key: "237-23-7743", value: { name: "Rug", height: 77, weight: 120 } },
21 { key: "237-23-7744", value: { name: "Pug", height: 66, weight: 110 } },
25 { name: "name", keyPath: "name", options: { unique: true } },
26 { name: "height", keyPath: "height", options: { } },
27 { name: "weight", keyPath: "weight", options: { unique: false } }
30 indexedDBTest(prepareDatabase, onOpen);
31 function prepareDatabase(evt)
34 db = event.target.result;
35 objectStoreName = "People";
36 objectStore = evalAndLog("objectStore = db.createObjectStore(objectStoreName);");
42 evalAndLog("trans = db.transaction(objectStoreName, 'readwrite')");
43 evalAndLog("objectStore = trans.objectStore(objectStoreName)");
44 populateObjectStore();
47 function populateObjectStore()
49 debug("First, add all our data to the object store.");
51 for (i in objectStoreData) {
52 request = evalAndLog("request = objectStore.add(objectStoreData[i].value, objectStoreData[i].key);");
53 request.onerror = unexpectedErrorCallback;
55 trans.oncomplete = testSimple;
58 function createIndexes()
60 debug("Now create the indexes.");
61 for (i in indexData) {
62 evalAndLog("objectStore.createIndex(indexData[i].name, indexData[i].keyPath, indexData[i].options);");
66 // Make a test that uses continue() to get to startPos, then passes
67 // 'count' to get to a position.
68 function makeAdvanceTest(startPos, direction, count, expectedValue, indexName)
71 evalAndLog("trans = db.transaction(objectStoreName)");
72 store = evalAndLog("store = trans.objectStore(objectStoreName)");
74 store = store.index(indexName);
77 evalAndLog("request = store.openCursor(null, " + direction + ")");
79 evalAndLog("request = store.openCursor()");
81 function continueToTest(event)
83 cursor = event.target.result;
84 if (currentPos == startPos) {
85 evalAndLog("cursor.advance(" + count + ")");
86 } else if (currentPos == startPos + 1) {
87 runTest(cursor, expectedValue);
93 evalAndLog("cursor.continue();");
99 request.onsuccess = continueToTest;
100 request.onerror = function(e)
108 function simplifyCursor(cursor)
111 if (cursor === null) {
114 if ('key' in cursor) {
115 obj.key = cursor.key;
118 if ('value' in cursor) {
119 obj.value = cursor.value;
122 if ('primaryKey' in cursor) {
123 obj.primaryKey = cursor.primaryKey;
128 function runTest(cursor, expectedValue)
130 expected = JSON.stringify(expectedValue);
131 shouldBeEqualToString("expected", JSON.stringify(simplifyCursor(cursor)));
135 function testSimple()
137 debug("testSimple()");
138 makeAdvanceTest(0, null, 1,
139 {key: objectStoreData[1].key,
140 value: objectStoreData[1].value,
141 primaryKey: objectStoreData[1].key})
142 .onsuccess= testContinueThenAdvance;
145 function testContinueThenAdvance()
147 debug("testContinueThenAdvance()");
148 makeAdvanceTest(3, null, 1,
150 {key: objectStoreData[4].key,
151 value: objectStoreData[4].value,
152 primaryKey: objectStoreData[4].key})
153 .onsuccess= testAdvanceMultiple;
156 function testAdvanceMultiple()
158 debug("testAdvanceMultiple()");
159 makeAdvanceTest(0, null, 3,
160 {key: objectStoreData[3].key,
161 value: objectStoreData[3].value,
162 primaryKey: objectStoreData[3].key})
163 .onsuccess = testAdvanceIndex;
166 function testAdvanceIndex()
168 debug("testAdvanceIndex()");
169 makeAdvanceTest(0, null, 3,
171 {key: objectStoreData[7].value.name,
172 value: objectStoreData[7].value,
173 primaryKey: objectStoreData[7].key},
174 "name").onsuccess = testAdvanceIndexNoDupe;
177 function testAdvanceIndexNoDupe()
179 debug("testAdvanceIndexNoDupe()");
180 makeAdvanceTest(0, "'nextunique'", 3,
181 // Sue (weight 130 - skipping weight 100, 110, 120)
182 {key: objectStoreData[3].value.weight,
183 value: objectStoreData[3].value,
184 primaryKey: objectStoreData[3].key},
185 "weight").onsuccess = testAdvanceIndexPrev;
188 function testAdvanceIndexPrev()
190 debug("testAdvanceIndexPrev()");
191 makeAdvanceTest(0, "'prev'", 3,
192 // Joe (weight 150 - skipping 180, 180, 180)
193 {key: objectStoreData[4].value.weight,
194 value: objectStoreData[4].value,
195 primaryKey: objectStoreData[4].key},
196 "weight").onsuccess = testAdvanceIndexPrevNoDupe;
199 function testAdvanceIndexPrevNoDupe()
201 debug("testAdvanceIndexPrevNoDupe()");
202 makeAdvanceTest(0, "'prevunique'", 3,
203 // Bob (weight 120 - skipping weights 180, 150, 130)
204 {key: objectStoreData[0].value.weight,
205 value: objectStoreData[0].value,
206 primaryKey: objectStoreData[0].key},
207 "weight").onsuccess = testAdvanceToEnd;
210 function testAdvanceToEnd()
212 debug("testAdvanceToEnd()");
213 makeAdvanceTest(0, null, 100, null)
214 .onsuccess = testPrefetchInRange;
217 // Make sure the prefetching that exists on some platforms (chromium)
218 // doesn't mess with advance(), or vice versa.
219 function testPrefetchInRange()
221 debug("testPrefetchInRange()");
222 var kPrefetchContinueThreshold = 2;
223 evalAndLog("trans = db.transaction(objectStoreName)");
224 objectStore = evalAndLog("objectStore = trans.objectStore(objectStoreName)");
226 evalAndLog("request = objectStore.openCursor()");
229 function prefetch(evt)
232 cursor = event.target.result;
235 testPrefetchOutOfRange();
239 runTest(cursor, {key: objectStoreData[currentPos].key,
240 value: objectStoreData[currentPos].value,
241 primaryKey: objectStoreData[currentPos].key});
243 // force some prefetching,
244 if (currentPos < (kPrefetchContinueThreshold+1)) {
245 evalAndLog("cursor.continue()");
247 } else if (currentPos == (kPrefetchContinueThreshold+1)) {
248 // stay within the prefetch range
249 evalAndLog("cursor.advance(2)");
252 // we're just past the threshold
253 evalAndLog("cursor.continue()");
257 request.onsuccess = prefetch;
258 request.onerror = unexpectedErrorCallback;
261 // Make sure the prefetching that exists on some platforms (chromium)
262 // doesn't mess with advance(), or vice versa.
263 function testPrefetchOutOfRange()
265 debug("testPrefetchOutOfRange()");
266 var kPrefetchContinueThreshold = 2;
267 evalAndLog("trans = db.transaction(objectStoreName)");
268 objectStore = evalAndLog("objectStore = trans.objectStore(objectStoreName)");
270 evalAndLog("request = objectStore.openCursor()");
273 function prefetch(evt)
276 cursor = event.target.result;
283 runTest(cursor, {key: objectStoreData[currentPos].key,
284 value: objectStoreData[currentPos].value,
285 primaryKey: objectStoreData[currentPos].key});
287 // force some prefetching,
288 if (currentPos < (kPrefetchContinueThreshold+1)) {
289 evalAndLog("cursor.continue()");
291 } else if (currentPos == (kPrefetchContinueThreshold+1)) {
292 // advance past the prefetch range
293 evalAndLog("cursor.advance(7)");
296 // we're past the threshold
297 evalAndLog("cursor.continue()");
301 request.onsuccess = prefetch;
302 request.onerror = unexpectedErrorCallback;
305 function testBadAdvance()
307 debug("testBadAdvance()");
308 evalAndLog("trans = db.transaction(objectStoreName, 'readwrite')");
309 objectStore = evalAndLog("objectStore = trans.objectStore(objectStoreName)");
311 evalAndLog("request = objectStore.openCursor()");
313 function advanceBadly(evt)
316 cursor = event.target.result;
318 evalAndExpectExceptionClass("cursor.advance(0)", "TypeError");
319 evalAndExpectExceptionClass("cursor.advance(-1)", "TypeError");
320 evalAndExpectExceptionClass("cursor.advance(0x100000000)", "TypeError");
321 evalAndExpectExceptionClass("cursor.advance(0x20000000000000)", "TypeError");
324 request.onsuccess = advanceBadly;
325 request.onerror = unexpectedErrorCallback;
331 evalAndLog("trans = db.transaction(objectStoreName, 'readonly')");
332 trans.onabort = unexpectedAbortCallback;
334 objectStore = evalAndLog("objectStore = trans.objectStore(objectStoreName)");
335 evalAndLog("request = objectStore.openCursor()");
336 request.onerror = unexpectedErrorCallback;
339 request.onsuccess = function onSuccess(evt) {
341 evalAndLog("cursor = event.target.result");
343 shouldBeNonNull("cursor");
344 firstSuccess = false;
345 evalAndLog("cursor.advance(0xffffffff)");
347 shouldBeNull("cursor");
351 trans.oncomplete = testDelete;
354 function testDelete()
356 debug("testDelete()");
357 evalAndLog("trans = db.transaction(objectStoreName, 'readwrite')");
358 objectStore = evalAndLog("objectStore = trans.objectStore(objectStoreName)");
360 evalAndLog("request = objectStore.openCursor()");
363 function deleteSecond(evt)
366 cursor = event.target.result;
373 runTest(cursor, {key: objectStoreData[currentPos].key,
374 value: objectStoreData[currentPos].value,
375 primaryKey: objectStoreData[currentPos].key});
378 // this is in the middle of the data, so it will test validity
379 if (currentPos == 2) {
380 evalAndLog("cursor.delete()");
384 evalAndLog("cursor.advance(1)");
389 request.onsuccess = deleteSecond;
390 request.onerror = unexpectedErrorCallback;