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