- add sources.
[platform/framework/web/crosswalk.git] / src / content / test / data / indexeddb / cursor_prefetch.js
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // These constants should match the ones in renderer_webidbcursor_impl.h
6 // to make sure the test hits the right code paths.
7 var kPrefetchThreshold = 2;
8 var kMinPrefetchAmount = 5;
9
10 var kNumberOfItems = 200;
11
12 function test() {
13   indexedDBTest(setVersionSuccess, fillObjectStore);
14 }
15
16 function setVersionSuccess() {
17   debug("setVersionSuccess():");
18   window.db = event.target.result;
19   window.trans = event.target.transaction;
20   shouldBeTrue("trans !== null");
21   var store = db.createObjectStore('store');
22   store.createIndex('index', '');
23 }
24
25 function fillObjectStore() {
26   debug("fillObjectStore()");
27   var trans = db.transaction(['store'], 'readwrite');
28   trans.onabort = unexpectedAbortCallback;
29   trans.oncomplete = firstTest;
30
31   var store = trans.objectStore('store');
32   debug("Storing " + kNumberOfItems + " object in the object store.");
33   for (var i = 0; i < kNumberOfItems; ++i) {
34     var req = store.put(i, i);
35     req.onerror = unexpectedErrorCallback;
36   }
37
38   // Let the transaction finish.
39 }
40
41 function firstTest() {
42   debug("firstTest()");
43
44   // Test iterating straight through the object store.
45
46   var trans = db.transaction(['store'], 'readwrite');
47   trans.onabort = unexpectedAbortCallback;
48   trans.oncomplete = secondTest;
49
50   var store = trans.objectStore('store');
51   var cursorReq = store.openCursor();
52   cursorReq.onerror = unexpectedErrorCallback;
53
54   count = 0;
55   cursorReq.onsuccess = function() {
56     cursor = event.target.result;
57     if (cursor === null) {
58       shouldBe("count", "kNumberOfItems");
59       return; // Let the transaction finish.
60     }
61
62     if (cursor.key !== count)
63       shouldBe("cursor.key", "count");
64     if (cursor.value !== count)
65       shouldBe("cursor.value", "count");
66
67     ++count;
68
69     cursor.continue();
70   }
71 }
72
73 function secondTest() {
74   debug("secondTest()");
75
76   // Test iterating through the object store, intermixed with
77   // continue calls to specific keys.
78
79   var trans = db.transaction(['store'], 'readwrite');
80   trans.onabort = unexpectedAbortCallback;
81   trans.oncomplete = thirdTest;
82
83   var store = trans.objectStore('store');
84   var cursorReq = store.openCursor();
85   cursorReq.onerror = unexpectedErrorCallback;
86
87   var jumpTable = [{from: 5,   to: 17},
88                    {from: 25,  to: 30},
89                    {from: 31,  to: 35},
90                    {from: 70,  to: 80},
91                    {from: 98,  to: 99}];
92
93   count = 0;
94   expectedKey = 0;
95
96   cursorReq.onsuccess = function() {
97     cursor = event.target.result;
98     if (cursor === null) {
99       debug("Finished iterating after " + count + " steps.");
100       return; // Let the transaction finish.
101     }
102
103     if (cursor.key !== expectedKey)
104       shouldBe("cursor.key", "expectedKey");
105     if (cursor.value !== expectedKey)
106       shouldBe("cursor.value", "expectedKey");
107
108     ++count;
109
110     for (var i = 0; i < jumpTable.length; ++i) {
111       if (jumpTable[i].from === cursor.key) {
112         expectedKey = jumpTable[i].to;
113         debug("Jumping from "+ cursor.key + " to " + expectedKey);
114         cursor.continue(expectedKey);
115         return;
116       }
117     }
118
119     ++expectedKey;
120     cursor.continue();
121   }
122 }
123
124 function thirdTest() {
125   debug("thirdTest()");
126
127   // Test iterating straight through the object store in reverse.
128
129   var trans = db.transaction(['store'], 'readwrite');
130   trans.onabort = unexpectedAbortCallback;
131   trans.oncomplete = fourthTest;
132
133   var store = trans.objectStore('store');
134   var cursorReq = store.openCursor(
135       IDBKeyRange.upperBound(kNumberOfItems-1), 'prev');
136   cursorReq.onerror = unexpectedErrorCallback;
137
138   count = 0;
139   cursorReq.onsuccess = function() {
140     cursor = event.target.result;
141     if (cursor === null) {
142       shouldBe("count", "kNumberOfItems");
143       return; // Let the transaction finish.
144     }
145
146     expectedKey = kNumberOfItems - count - 1;
147
148     if (cursor.key !== expectedKey)
149       shouldBe("cursor.key", "expectedKey");
150     if (cursor.value !== expectedKey)
151       shouldBe("cursor.value", "expectedKey");
152
153     ++count;
154
155     cursor.continue();
156   }
157 }
158
159 function fourthTest() {
160   debug("fourthTest()");
161
162   // Test iterating, and then stopping before reaching the end.
163   // Make sure transaction terminates anyway.
164
165   var trans = db.transaction(['store'], 'readwrite');
166   trans.onabort = unexpectedAbortCallback;
167   trans.oncomplete = function() {
168     debug("fourthTest() transaction completed");
169     fifthTest();
170   }
171
172   var store = trans.objectStore('store');
173   var cursorReq = store.openCursor();
174   cursorReq.onerror = unexpectedErrorCallback;
175
176   count = 0;
177   cursorReq.onsuccess = function() {
178     cursor = event.target.result;
179
180     if (cursor.key !== count)
181       shouldBe("cursor.key", "count");
182     if (cursor.value !== count)
183       shouldBe("cursor.value", "count");
184
185     ++count;
186
187     if (count === 25) {
188       // Schedule some other request.
189       var otherReq = store.get(42);
190       otherReq.onerror = unexpectedErrorCallback;
191       otherReq.onsuccess = function() {
192         if (count === 25) {
193           debug("Other request fired before continue, as expected.");
194         } else {
195           debug("Other request fired out-of-order!");
196           fail();
197         }
198       }
199
200       cursor.continue();
201       return;
202     }
203
204     if (count === 30) {
205       // Do a continue first, then another request.
206       cursor.continue();
207
208       var otherReq = store.get(42);
209       otherReq.onerror = unexpectedErrorCallback;
210       otherReq.onsuccess = function() {
211         if (count === 31) {
212           debug("Other request fired right after continue as expected.");
213         } else {
214           debug("Other request didn't fire right after continue as expected.");
215           fail();
216         }
217       }
218
219       return;
220     }
221
222     if (count === 75) {
223       return;  // Sudden stop.
224     }
225
226     cursor.continue();
227   }
228 }
229
230 function fifthTest() {
231   debug("fifthTest()");
232
233   // Test iterating over the pre-fetch threshold, but make sure the
234   // cursor is positioned so that it is actually at the last element
235   // in the range when pre-fetch fires, and make sure a null cursor
236   // is the result as expected.
237
238   var trans = db.transaction(['store'], 'readwrite');
239   trans.onabort = unexpectedAbortCallback;
240   trans.oncomplete = sixthTest;
241
242   var store = trans.objectStore('store');
243
244   var startKey = kNumberOfItems - 1 - kPrefetchThreshold;
245   var cursorReq = store.openCursor(IDBKeyRange.lowerBound(startKey));
246   cursorReq.onerror = unexpectedErrorCallback;
247
248   count = 0;
249   cursorReq.onsuccess = function() {
250     cursor = event.target.result;
251
252     if (cursor === null) {
253       debug("cursor is null");
254       shouldBe("count", "kPrefetchThreshold + 1");
255       return;
256     }
257
258     debug("count: " + count);
259     ++count;
260     cursor.continue();
261   }
262 }
263
264 function sixthTest() {
265   debug("sixthTest()");
266
267   // Test stepping two cursors simultaneously. First cursor1 steps
268   // for a while, then cursor2, then back to cursor1, etc.
269
270   var trans = db.transaction(['store'], 'readwrite');
271   trans.onabort = unexpectedAbortCallback;
272   trans.oncomplete = seventhTest;
273   var store = trans.objectStore('store');
274
275   cursor1 = null;
276   cursor2 = null;
277
278   count1 = 0;
279   count2 = 0;
280
281   var cursor1func = function() {
282     var cursor = event.target.result;
283     if (cursor === null) {
284       shouldBe("count1", "kNumberOfItems");
285       cursor2.continue();
286       return;
287     }
288
289     if (cursor1 === null) {
290       cursor1 = cursor;
291     }
292
293     if (cursor1.key !== count1)
294       shouldBe("cursor1.key", "count1");
295     if (cursor1.value !== count1)
296       shouldBe("cursor1.value", "count1");
297
298     ++count1;
299
300     if (count1 % 20 === 0) {
301       if (cursor2 !== null) {
302         cursor2.continue();
303       } else {
304         var req = store.openCursor();
305         req.onerror = unexpectedErrorCallback;
306         req.onsuccess = cursor2func;
307       }
308     } else {
309       cursor1.continue();
310     }
311   }
312
313   var cursor2func = function() {
314     var cursor = event.target.result;
315     if (cursor === null) {
316       shouldBe("count2", "kNumberOfItems");
317       return;
318     }
319
320     if (cursor2 === null) {
321       cursor2 = cursor;
322     }
323
324     if (cursor2.key !== count2)
325       shouldBe("cursor2.key", "count2");
326     if (cursor2.value !== count2)
327       shouldBe("cursor2.value", "count2");
328
329     ++count2;
330
331     if (count2 % 20 === 0) {
332       cursor1.continue();
333     } else {
334       cursor2.continue();
335     }
336   }
337
338   var req = store.openCursor();
339   req.onerror = unexpectedErrorCallback;
340   req.onsuccess = cursor1func;
341 }
342
343 function seventhTest() {
344   debug("seventhTest()");
345
346   // Test iterating straight through an index.
347
348   var trans = db.transaction(['store'], 'readwrite');
349   trans.onabort = unexpectedAbortCallback;
350   trans.oncomplete = eighthTest;
351
352   var store = trans.objectStore('store');
353   var index = store.index('index');
354
355   var cursorReq = index.openCursor();
356   cursorReq.onerror = unexpectedErrorCallback;
357   count = 0;
358
359   cursorReq.onsuccess = function() {
360     cursor = event.target.result;
361     if (cursor === null) {
362       shouldBe("count", "kNumberOfItems");
363       return;
364     }
365
366     if (cursor.key !== count)
367       shouldBe("cursor.key", "count");
368     if (cursor.primaryKey !== count)
369       shouldBe("cursor.primaryKey", "count");
370     if (cursor.value !== count)
371       shouldBe("cursor.value", "count");
372
373     ++count;
374     cursor.continue();
375   }
376 }
377
378 function eighthTest() {
379   debug("eighthTest()");
380
381   // Run a key cursor over an index.
382
383   var trans = db.transaction(['store'], 'readwrite');
384   trans.onabort = unexpectedAbortCallback;
385   trans.oncomplete = done;
386
387   var store = trans.objectStore('store');
388   var index = store.index('index');
389
390   var cursorReq = index.openKeyCursor();
391   cursorReq.onerror = unexpectedErrorCallback;
392   count = 0;
393
394   cursorReq.onsuccess = function() {
395     cursor = event.target.result;
396     if (cursor === null) {
397       shouldBe("count", "kNumberOfItems");
398       return;
399     }
400
401     if (cursor.key !== count)
402       shouldBe("cursor.key", "count");
403     if (cursor.primaryKey !== count)
404       shouldBe("cursor.primaryKey", "count");
405
406     ++count;
407     cursor.continue();
408   }
409 }