Home | History | Annotate | Download | only in indexeddb
      1 <html>
      2 <head>
      3 <link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
      4 <script src="../../fast/js/resources/js-test-pre.js"></script>
      5 <script src="../../fast/js/resources/js-test-post-function.js"></script>
      6 <script src="resources/shared.js"></script>
      7 </head>
      8 <body>
      9 <p id="description"></p>
     10 <div id="console"></div>
     11 <script>
     12 
     13 description("Test IndexedDB's cursor skips deleted entries.");
     14 if (window.layoutTestController)
     15     layoutTestController.waitUntilDone();
     16 
     17 var names = ['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo', 'Foxtrot', 'Golf',
     18              'Hotel', 'India', 'Juliet', 'Kilo', 'Lima', 'Mike', 'November',
     19              'Oscar', 'Papa', 'Quebec', 'Romeo', 'Sierra', 'Tango', 'Uniform',
     20              'Victor', 'Whiskey', 'X-ray', 'Yankee', 'Zulu'];
     21 
     22 test();
     23 
     24 function test()
     25 {
     26     request = evalAndLog("webkitIndexedDB.open('cursor-skip-deleted')");
     27     request.onsuccess = openSuccess;
     28     request.onerror = unexpectedErrorCallback;
     29 }
     30 
     31 function openSuccess()
     32 {
     33     var db = evalAndLog("db = event.target.result");
     34 
     35     request = evalAndLog("db.setVersion('new version')");
     36     request.onsuccess = setVersionSuccess;
     37     request.onerror = unexpectedErrorCallback;
     38 }
     39 
     40 function setVersionSuccess()
     41 {
     42     debug("setVersionSuccess():");
     43     window.trans = evalAndLog("trans = event.target.result");
     44     shouldBeTrue("trans !== null");
     45     trans.onabort = unexpectedAbortCallback;
     46     trans.oncomplete = basicCursorTest;
     47 
     48     deleteAllObjectStores(db);
     49 
     50     var objectStore = evalAndLog("objectStore = db.createObjectStore('store', {keyPath: 'id'})");
     51     evalAndLog("objectStore.createIndex('nameIndex', 'name')");
     52     resetObjectStore(function() {});
     53 }
     54 
     55 var silentErrorHandler = function() { event.preventDefault(); }
     56 
     57 function resetObjectStore(callback)
     58 {
     59     debug("\nresetObjectStore():");
     60     if (callback === undefined)
     61         callback = function () {};
     62 
     63     var objectStore = trans.objectStore('store');
     64     for (var i = 0; i < names.length; i++)
     65         objectStore.delete(i).onerror = silentErrorHandler;
     66     for (var i = 0; i < names.length; i++)
     67         objectStore.add({id: i, name: names[i]}).onerror = unexpectedErrorCallback;
     68 
     69     debug("");
     70     callback();
     71 }
     72 
     73 function contains(arr, obj)
     74 {
     75     for (var i = 0; i < arr.length; i++) {
     76         if (arr[i] == obj)
     77             return true;
     78     }
     79     return false;
     80 }
     81 
     82 var cursor;
     83 var deleted;
     84 var seen;
     85 
     86 function testCursor(deleteList, createCursorCommand, callback)
     87 {
     88     debug("\ntestCursor():");
     89     deleted = [];
     90     seen = [];
     91 
     92     // Create the cursor.
     93     request = evalAndLog(createCursorCommand);
     94 
     95     request.onerror = unexpectedErrorCallback;
     96     request.onsuccess = function () {
     97         if (event.target.result == null) {
     98             // Make sure we have seen every non-deleted item.
     99             for (var i = 0; i < names.length; i++) {
    100                 if (contains(deleted, i))
    101                     continue;
    102 
    103                 if (!contains(seen, i))
    104                     testFailed("Cursor did not see item with id: " + i);
    105             }
    106 
    107             // Make sure we used every rule in |deleteList|.
    108             for (var i = 0; i < deleteList.length; i++) {
    109                 if (!contains(seen, deleteList[i].id))
    110                     testFailed("deleteList rule with id: " + deleteList[i].id + " was never used.");
    111             }
    112 
    113             debug("");
    114             callback();
    115             return;
    116         }
    117 
    118         cursor = event.target.result;
    119         debug(event.target.result.value.id + ": " + event.target.result.value.name);
    120         seen.push(event.target.result.value.id);
    121 
    122         // Make sure we don't see any deleted items.
    123         if (contains(deleted, event.target.result.value.id))
    124             testFailed("Cursor hit previously deleted element.");
    125 
    126         for (var i = 0; i < deleteList.length; i++) {
    127             if (event.target.result.value.id == deleteList[i].id) {
    128                 // Delete objects targeted by this id.
    129                 var targets = deleteList[i].targets;
    130                 for (var j = 0; j < targets.length; j++) {
    131                     deleted.push(targets[j]);
    132                     request = evalAndLog("request = trans.objectStore('store').delete(" + targets[j] + ")");
    133                     request.onerror = unexpectedErrorCallback;
    134                     if (j == targets.length - 1)
    135                         request.onsuccess = function() { cursor.continue(); }
    136                 }
    137                 return;
    138             }
    139         }
    140 
    141         cursor.continue();
    142     }
    143 }
    144 
    145 function basicCursorTest()
    146 {
    147     debug("basicCursorTest()");
    148 
    149     evalAndLog("trans = db.transaction([], webkitIDBTransaction.READ_WRITE)");
    150     trans.onabort = unexpectedAbortCallback;
    151     trans.oncomplete = transactionComplete;
    152 
    153     var deletes = [{id: 1, targets: [0]},
    154                    {id: 2, targets: [names.length - 1]},
    155                    {id: 3, targets: [5,6,7]},
    156                    {id: 10, targets: [10]},
    157                    {id: 12, targets: [13]},
    158                    {id: 15, targets: [14]},
    159                    {id: 20, targets: [17,18]}
    160                    ];
    161 
    162     testCursor(deletes, "trans.objectStore('store').openCursor(webkitIDBKeyRange.lowerBound(0))", function() { resetObjectStore(reverseCursorTest); });
    163 }
    164 
    165 function reverseCursorTest()
    166 {
    167     debug("reverseCursorTest():");
    168 
    169     var deletes = [{id: 24, targets: [names.length - 1]},
    170                    {id: 23, targets: [0]},
    171                    {id: 22, targets: [20, 19, 18]},
    172                    {id: 15, targets: [15]},
    173                    {id: 13, targets: [12]},
    174                    {id: 10, targets: [11]},
    175                    {id: 5, targets: [7,8]}
    176                    ];
    177 
    178 
    179     testCursor(deletes, "trans.objectStore('store').openCursor(webkitIDBKeyRange.lowerBound(0), webkitIDBCursor.PREV)", function() { resetObjectStore(indexCursorTest); });
    180 }
    181 
    182 function indexCursorTest()
    183 {
    184     debug("indexCursorTest():");
    185 
    186     var deletes = [{id: 1, targets: [0]},
    187                    {id: 2, targets: [names.length - 1]},
    188                    {id: 3, targets: [5,6,7]},
    189                    {id: 10, targets: [10]},
    190                    {id: 12, targets: [13]},
    191                    {id: 15, targets: [14]},
    192                    {id: 20, targets: [17,18]}
    193                    ];
    194 
    195     testCursor(deletes, "trans.objectStore('store').index('nameIndex').openCursor(webkitIDBKeyRange.lowerBound('Alpha'))", function() { });
    196 }
    197 
    198 function transactionComplete()
    199 {
    200     debug("transactionComplete():");
    201     done();
    202 }
    203 
    204 var successfullyParsed = true;
    205 
    206 
    207 
    208 
    209