2011-02-09 Hans Wennborg <hans@chromium.org>
[WebKit-https.git] / LayoutTests / storage / indexeddb / cursor-skip-deleted.html
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     result = evalAndLog("webkitIndexedDB.open('name')");
27     verifyResult(result);
28     result.onsuccess = openSuccess;
29     result.onerror = unexpectedErrorCallback;
30 }
31
32 function openSuccess()
33 {
34     verifySuccessEvent(event);
35     var db = evalAndLog("db = event.result");
36
37     result = evalAndLog("db.setVersion('new version')");
38     verifyResult(result);
39     result.onsuccess = setVersionSuccess;
40     result.onerror = unexpectedErrorCallback;
41 }
42
43 function setVersionSuccess()
44 {
45     debug("setVersionSuccess():");
46     verifySuccessEvent(event);
47     window.trans = evalAndLog("trans = event.result");
48     shouldBeTrue("trans !== null");
49     trans.onabort = unexpectedAbortCallback;
50     trans.oncomplete = basicCursorTest;
51
52     deleteAllObjectStores(db, createAndPopulateObjectStore);
53 }
54
55 function createAndPopulateObjectStore()
56 {
57     debug("createAndPopulateObjectStore():");
58
59     var objectStore = evalAndLog("objectStore = db.createObjectStore('store', {keyPath: 'id'})");
60     evalAndLog("objectStore.createIndex('nameIndex', 'name')");
61     resetObjectStore(function() {});
62 }
63
64 var silentErrorHandler = function() { event.preventDefault(); }
65
66 function resetObjectStore(callback)
67 {
68     debug("\nresetObjectStore():");
69     if (callback === undefined)
70         callback = function () {};
71
72     var objectStore = trans.objectStore('store');
73     for (var i = 0; i < names.length; i++)
74         objectStore.delete(i).onerror = silentErrorHandler;
75     for (var i = 0; i < names.length; i++)
76         objectStore.add({id: i, name: names[i]}).onerror = unexpectedErrorCallback;
77
78     debug("");
79     callback();
80 }
81
82 function contains(arr, obj)
83 {
84     for (var i = 0; i < arr.length; i++) {
85         if (arr[i] == obj)
86             return true;
87     }
88     return false;
89 }
90
91 var cursor;
92 var deleted;
93 var seen;
94
95 function testCursor(deleteList, createCursorCommand, callback)
96 {
97     debug("\ntestCursor():");
98     deleted = [];
99     seen = [];
100
101     // Create the cursor.
102     request = evalAndLog(createCursorCommand);
103     verifyResult(request);
104
105     request.onerror = unexpectedErrorCallback;
106     request.onsuccess = function () {
107         if (event.result == null) {
108             // Make sure we have seen every non-deleted item.
109             for (var i = 0; i < names.length; i++) {
110                 if (contains(deleted, i))
111                     continue;
112
113                 if (!contains(seen, i))
114                     testFailed("Cursor did not see item with id: " + i);
115             }
116
117             // Make sure we used every rule in |deleteList|.
118             for (var i = 0; i < deleteList.length; i++) {
119                 if (!contains(seen, deleteList[i].id))
120                     testFailed("deleteList rule with id: " + deleteList[i].id + " was never used.");
121             }
122
123             debug("");
124             callback();
125             return;
126         }
127
128         cursor = event.result;
129         debug(event.result.value.id + ": " + event.result.value.name);
130         seen.push(event.result.value.id);
131
132         // Make sure we don't see any deleted items.
133         if (contains(deleted, event.result.value.id))
134             testFailed("Cursor hit previously deleted element.");
135
136         for (var i = 0; i < deleteList.length; i++) {
137             if (event.result.value.id == deleteList[i].id) {
138                 // Delete objects targeted by this id.
139                 var targets = deleteList[i].targets;
140                 for (var j = 0; j < targets.length; j++) {
141                     deleted.push(targets[j]);
142                     request = evalAndLog("request = trans.objectStore('store').delete(" + targets[j] + ")");
143                     request.onerror = unexpectedErrorCallback;
144                     if (j == targets.length - 1)
145                         request.onsuccess = function() { cursor.continue(); }
146                 }
147                 return;
148             }
149         }
150
151         cursor.continue();
152     }
153 }
154
155 function basicCursorTest()
156 {
157     debug("basicCursorTest()");
158
159     evalAndLog("trans = db.transaction([], webkitIDBTransaction.READ_WRITE)");
160     trans.onabort = unexpectedAbortCallback;
161     trans.oncomplete = transactionComplete;
162
163     var deletes = [{id: 1, targets: [0]},
164                    {id: 2, targets: [names.length - 1]},
165                    {id: 3, targets: [5,6,7]},
166                    {id: 10, targets: [10]},
167                    {id: 12, targets: [13]},
168                    {id: 15, targets: [14]},
169                    {id: 20, targets: [17,18]}
170                    ];
171
172     testCursor(deletes, "trans.objectStore('store').openCursor(webkitIDBKeyRange.lowerBound(0))", function() { resetObjectStore(reverseCursorTest); });
173 }
174
175 function reverseCursorTest()
176 {
177     debug("reverseCursorTest():");
178
179     var deletes = [{id: 24, targets: [names.length - 1]},
180                    {id: 23, targets: [0]},
181                    {id: 22, targets: [20, 19, 18]},
182                    {id: 15, targets: [15]},
183                    {id: 13, targets: [12]},
184                    {id: 10, targets: [11]},
185                    {id: 5, targets: [7,8]}
186                    ];
187
188
189     testCursor(deletes, "trans.objectStore('store').openCursor(webkitIDBKeyRange.lowerBound(0), webkitIDBCursor.PREV)", function() { resetObjectStore(indexCursorTest); });
190 }
191
192 function indexCursorTest()
193 {
194     debug("indexCursorTest():");
195
196     var deletes = [{id: 1, targets: [0]},
197                    {id: 2, targets: [names.length - 1]},
198                    {id: 3, targets: [5,6,7]},
199                    {id: 10, targets: [10]},
200                    {id: 12, targets: [13]},
201                    {id: 15, targets: [14]},
202                    {id: 20, targets: [17,18]}
203                    ];
204
205     testCursor(deletes, "trans.objectStore('store').index('nameIndex').openCursor(webkitIDBKeyRange.lowerBound('Alpha'))", function() { });
206 }
207
208 function transactionComplete()
209 {
210     debug("transactionComplete():");
211     done();
212 }
213
214 var successfullyParsed = true;
215
216 </script>
217 </body>
218 </html>