|
1 /** |
|
2 * Any copyright is dedicated to the Public Domain. |
|
3 * http://creativecommons.org/publicdomain/zero/1.0/ |
|
4 */ |
|
5 |
|
6 if (!this.window) { |
|
7 this.runTest = function() { |
|
8 todo(false, "Test disabled in xpcshell test suite for now"); |
|
9 finishTest(); |
|
10 } |
|
11 } |
|
12 |
|
13 var testGenerator = testSteps(); |
|
14 |
|
15 function genCheck(key, value, test, options) { |
|
16 return function(event) { |
|
17 is(JSON.stringify(event.target.result), JSON.stringify(key), |
|
18 "correct returned key in " + test); |
|
19 if (options && options.store) { |
|
20 is(event.target.source, options.store, "correct store in " + test); |
|
21 } |
|
22 if (options && options.trans) { |
|
23 is(event.target.transaction, options.trans, "correct transaction in " + test); |
|
24 } |
|
25 |
|
26 event.target.source.get(key).onsuccess = function(event) { |
|
27 is(JSON.stringify(event.target.result), JSON.stringify(value), |
|
28 "correct stored value in " + test); |
|
29 continueToNextStepSync(); |
|
30 } |
|
31 } |
|
32 } |
|
33 |
|
34 function testSteps() |
|
35 { |
|
36 const dbname = this.window ? window.location.pathname : "Splendid Test"; |
|
37 const RW = "readwrite"; |
|
38 let c1 = 1; |
|
39 let c2 = 1; |
|
40 |
|
41 let openRequest = indexedDB.open(dbname, 1); |
|
42 openRequest.onerror = errorHandler; |
|
43 openRequest.onupgradeneeded = grabEventAndContinueHandler; |
|
44 openRequest.onsuccess = unexpectedSuccessHandler; |
|
45 let event = yield undefined; |
|
46 let db = event.target.result; |
|
47 let trans = event.target.transaction; |
|
48 |
|
49 // Create test stores |
|
50 let store1 = db.createObjectStore("store1", { autoIncrement: true }); |
|
51 let store2 = db.createObjectStore("store2", { autoIncrement: true, keyPath: "id" }); |
|
52 let store3 = db.createObjectStore("store3", { autoIncrement: false }); |
|
53 is(store1.autoIncrement, true, "store1 .autoIncrement"); |
|
54 is(store2.autoIncrement, true, "store2 .autoIncrement"); |
|
55 is(store3.autoIncrement, false, "store3 .autoIncrement"); |
|
56 |
|
57 store1.createIndex("unique1", "unique", { unique: true }); |
|
58 store2.createIndex("unique1", "unique", { unique: true }); |
|
59 |
|
60 // Test simple inserts |
|
61 let test = " for test simple insert" |
|
62 store1.add({ foo: "value1" }).onsuccess = |
|
63 genCheck(c1++, { foo: "value1" }, "first" + test); |
|
64 store1.add({ foo: "value2" }).onsuccess = |
|
65 genCheck(c1++, { foo: "value2" }, "second" + test); |
|
66 |
|
67 yield undefined; |
|
68 yield undefined; |
|
69 |
|
70 store2.put({ bar: "value1" }).onsuccess = |
|
71 genCheck(c2, { bar: "value1", id: c2 }, "first in store2" + test, |
|
72 { store: store2 }); |
|
73 c2++; |
|
74 store1.put({ foo: "value3" }).onsuccess = |
|
75 genCheck(c1++, { foo: "value3" }, "third" + test, |
|
76 { store: store1 }); |
|
77 |
|
78 yield undefined; |
|
79 yield undefined; |
|
80 |
|
81 store2.get(IDBKeyRange.lowerBound(c2)).onsuccess = grabEventAndContinueHandler; |
|
82 event = yield undefined; |
|
83 is(event.target.result, undefined, "no such value" + test); |
|
84 |
|
85 // Close version_change transaction |
|
86 openRequest.onsuccess = grabEventAndContinueHandler; |
|
87 event = yield undefined; |
|
88 |
|
89 is(event.target, openRequest, "succeeded to open" + test); |
|
90 is(event.type, "success", "succeeded to open" + test); |
|
91 |
|
92 // Test inserting explicit keys |
|
93 test = " for test explicit keys"; |
|
94 trans = db.transaction("store1", RW); |
|
95 trans.objectStore("store1").add({ explicit: 1 }, 100).onsuccess = |
|
96 genCheck(100, { explicit: 1 }, "first" + test); |
|
97 c1 = 101; |
|
98 trans = db.transaction("store1", RW); |
|
99 trans.objectStore("store1").add({ explicit: 2 }).onsuccess = |
|
100 genCheck(c1++, { explicit: 2 }, "second" + test); |
|
101 yield undefined; yield undefined; |
|
102 |
|
103 trans = db.transaction("store1", RW); |
|
104 trans.objectStore("store1").add({ explicit: 3 }, 200).onsuccess = |
|
105 genCheck(200, { explicit: 3 }, "third" + test); |
|
106 c1 = 201; |
|
107 trans.objectStore("store1").add({ explicit: 4 }).onsuccess = |
|
108 genCheck(c1++, { explicit: 4 }, "fourth" + test); |
|
109 yield undefined; yield undefined; |
|
110 |
|
111 trans = db.transaction("store1", RW); |
|
112 trans.objectStore("store1").add({ explicit: 5 }, 150).onsuccess = |
|
113 genCheck(150, { explicit: 5 }, "fifth" + test); |
|
114 yield undefined; |
|
115 trans.objectStore("store1").add({ explicit: 6 }).onsuccess = |
|
116 genCheck(c1++, { explicit: 6 }, "sixth" + test); |
|
117 yield undefined; |
|
118 |
|
119 trans = db.transaction("store1", RW); |
|
120 trans.objectStore("store1").add({ explicit: 7 }, "key").onsuccess = |
|
121 genCheck("key", { explicit: 7 }, "seventh" + test); |
|
122 yield undefined; |
|
123 trans.objectStore("store1").add({ explicit: 8 }).onsuccess = |
|
124 genCheck(c1++, { explicit: 8 }, "eighth" + test); |
|
125 yield undefined; |
|
126 |
|
127 trans = db.transaction("store1", RW); |
|
128 trans.objectStore("store1").add({ explicit: 7 }, [100000]).onsuccess = |
|
129 genCheck([100000], { explicit: 7 }, "seventh" + test); |
|
130 yield undefined; |
|
131 trans.objectStore("store1").add({ explicit: 8 }).onsuccess = |
|
132 genCheck(c1++, { explicit: 8 }, "eighth" + test); |
|
133 yield undefined; |
|
134 |
|
135 trans = db.transaction("store1", RW); |
|
136 trans.objectStore("store1").add({ explicit: 9 }, -100000).onsuccess = |
|
137 genCheck(-100000, { explicit: 9 }, "ninth" + test); |
|
138 yield undefined; |
|
139 trans.objectStore("store1").add({ explicit: 10 }).onsuccess = |
|
140 genCheck(c1++, { explicit: 10 }, "tenth" + test); |
|
141 yield undefined; |
|
142 |
|
143 |
|
144 trans = db.transaction("store2", RW); |
|
145 trans.objectStore("store2").add({ explicit2: 1, id: 300 }).onsuccess = |
|
146 genCheck(300, { explicit2: 1, id: 300 }, "first store2" + test); |
|
147 c2 = 301; |
|
148 trans = db.transaction("store2", RW); |
|
149 trans.objectStore("store2").add({ explicit2: 2 }).onsuccess = |
|
150 genCheck(c2, { explicit2: 2, id: c2 }, "second store2" + test); |
|
151 c2++; |
|
152 yield undefined; yield undefined; |
|
153 |
|
154 trans = db.transaction("store2", RW); |
|
155 trans.objectStore("store2").add({ explicit2: 3, id: 400 }).onsuccess = |
|
156 genCheck(400, { explicit2: 3, id: 400 }, "third store2" + test); |
|
157 c2 = 401; |
|
158 trans.objectStore("store2").add({ explicit2: 4 }).onsuccess = |
|
159 genCheck(c2, { explicit2: 4, id: c2 }, "fourth store2" + test); |
|
160 c2++; |
|
161 yield undefined; yield undefined; |
|
162 |
|
163 trans = db.transaction("store2", RW); |
|
164 trans.objectStore("store2").add({ explicit: 5, id: 150 }).onsuccess = |
|
165 genCheck(150, { explicit: 5, id: 150 }, "fifth store2" + test); |
|
166 yield undefined; |
|
167 trans.objectStore("store2").add({ explicit: 6 }).onsuccess = |
|
168 genCheck(c2, { explicit: 6, id: c2 }, "sixth store2" + test); |
|
169 c2++; |
|
170 yield undefined; |
|
171 |
|
172 trans = db.transaction("store2", RW); |
|
173 trans.objectStore("store2").add({ explicit: 7, id: "key" }).onsuccess = |
|
174 genCheck("key", { explicit: 7, id: "key" }, "seventh store2" + test); |
|
175 yield undefined; |
|
176 trans.objectStore("store2").add({ explicit: 8 }).onsuccess = |
|
177 genCheck(c2, { explicit: 8, id: c2 }, "eighth store2" + test); |
|
178 c2++; |
|
179 yield undefined; |
|
180 |
|
181 trans = db.transaction("store2", RW); |
|
182 trans.objectStore("store2").add({ explicit: 7, id: [100000] }).onsuccess = |
|
183 genCheck([100000], { explicit: 7, id: [100000] }, "seventh store2" + test); |
|
184 yield undefined; |
|
185 trans.objectStore("store2").add({ explicit: 8 }).onsuccess = |
|
186 genCheck(c2, { explicit: 8, id: c2 }, "eighth store2" + test); |
|
187 c2++; |
|
188 yield undefined; |
|
189 |
|
190 trans = db.transaction("store2", RW); |
|
191 trans.objectStore("store2").add({ explicit: 9, id: -100000 }).onsuccess = |
|
192 genCheck(-100000, { explicit: 9, id: -100000 }, "ninth store2" + test); |
|
193 yield undefined; |
|
194 trans.objectStore("store2").add({ explicit: 10 }).onsuccess = |
|
195 genCheck(c2, { explicit: 10, id: c2 }, "tenth store2" + test); |
|
196 c2++; |
|
197 yield undefined; |
|
198 |
|
199 |
|
200 // Test separate transactions doesn't generate overlapping numbers |
|
201 test = " for test non-overlapping counts"; |
|
202 trans = db.transaction("store1", RW); |
|
203 trans2 = db.transaction("store1", RW); |
|
204 trans2.objectStore("store1").put({ over: 2 }).onsuccess = |
|
205 genCheck(c1 + 1, { over: 2 }, "first" + test, |
|
206 { trans: trans2 }); |
|
207 trans.objectStore("store1").put({ over: 1 }).onsuccess = |
|
208 genCheck(c1, { over: 1 }, "second" + test, |
|
209 { trans: trans }); |
|
210 c1 += 2; |
|
211 yield undefined; yield undefined; |
|
212 |
|
213 trans = db.transaction("store2", RW); |
|
214 trans2 = db.transaction("store2", RW); |
|
215 trans2.objectStore("store2").put({ over: 2 }).onsuccess = |
|
216 genCheck(c2 + 1, { over: 2, id: c2 + 1 }, "third" + test, |
|
217 { trans: trans2 }); |
|
218 trans.objectStore("store2").put({ over: 1 }).onsuccess = |
|
219 genCheck(c2, { over: 1, id: c2 }, "fourth" + test, |
|
220 { trans: trans }); |
|
221 c2 += 2; |
|
222 yield undefined; yield undefined; |
|
223 |
|
224 // Test that error inserts doesn't increase generator |
|
225 test = " for test error inserts"; |
|
226 trans = db.transaction(["store1", "store2"], RW); |
|
227 trans.objectStore("store1").add({ unique: 1 }, -1); |
|
228 trans.objectStore("store2").add({ unique: 1, id: "unique" }); |
|
229 |
|
230 trans.objectStore("store1").add({ error: 1, unique: 1 }). |
|
231 addEventListener("error", new ExpectError("ConstraintError", true)); |
|
232 trans.objectStore("store1").add({ error: 2 }).onsuccess = |
|
233 genCheck(c1++, { error: 2 }, "first" + test); |
|
234 yield undefined; yield undefined; |
|
235 |
|
236 trans.objectStore("store2").add({ error: 3, unique: 1 }). |
|
237 addEventListener("error", new ExpectError("ConstraintError", true)); |
|
238 trans.objectStore("store2").add({ error: 4 }).onsuccess = |
|
239 genCheck(c2, { error: 4, id: c2 }, "second" + test); |
|
240 c2++; |
|
241 yield undefined; yield undefined; |
|
242 |
|
243 trans.objectStore("store1").add({ error: 5, unique: 1 }, 100000). |
|
244 addEventListener("error", new ExpectError("ConstraintError", true)); |
|
245 trans.objectStore("store1").add({ error: 6 }).onsuccess = |
|
246 genCheck(c1++, { error: 6 }, "third" + test); |
|
247 yield undefined; yield undefined; |
|
248 |
|
249 trans.objectStore("store2").add({ error: 7, unique: 1, id: 100000 }). |
|
250 addEventListener("error", new ExpectError("ConstraintError", true)); |
|
251 trans.objectStore("store2").add({ error: 8 }).onsuccess = |
|
252 genCheck(c2, { error: 8, id: c2 }, "fourth" + test); |
|
253 c2++; |
|
254 yield undefined; yield undefined; |
|
255 |
|
256 // Test that aborts doesn't increase generator |
|
257 test = " for test aborted transaction"; |
|
258 trans = db.transaction(["store1", "store2"], RW); |
|
259 trans.objectStore("store1").add({ abort: 1 }).onsuccess = |
|
260 genCheck(c1, { abort: 1 }, "first" + test); |
|
261 trans.objectStore("store2").put({ abort: 2 }).onsuccess = |
|
262 genCheck(c2, { abort: 2, id: c2 }, "second" + test); |
|
263 yield undefined; yield undefined; |
|
264 |
|
265 trans.objectStore("store1").add({ abort: 3 }, 500).onsuccess = |
|
266 genCheck(500, { abort: 3 }, "third" + test); |
|
267 trans.objectStore("store2").put({ abort: 4, id: 600 }).onsuccess = |
|
268 genCheck(600, { abort: 4, id: 600 }, "fourth" + test); |
|
269 yield undefined; yield undefined; |
|
270 |
|
271 trans.objectStore("store1").add({ abort: 5 }).onsuccess = |
|
272 genCheck(501, { abort: 5 }, "fifth" + test); |
|
273 trans.objectStore("store2").put({ abort: 6 }).onsuccess = |
|
274 genCheck(601, { abort: 6, id: 601 }, "sixth" + test); |
|
275 yield undefined; yield undefined; |
|
276 |
|
277 trans.abort(); |
|
278 trans.onabort = grabEventAndContinueHandler; |
|
279 event = yield |
|
280 is(event.type, "abort", "transaction aborted"); |
|
281 is(event.target, trans, "correct transaction aborted"); |
|
282 |
|
283 trans = db.transaction(["store1", "store2"], RW); |
|
284 trans.objectStore("store1").add({ abort: 1 }).onsuccess = |
|
285 genCheck(c1++, { abort: 1 }, "re-first" + test); |
|
286 trans.objectStore("store2").put({ abort: 2 }).onsuccess = |
|
287 genCheck(c2, { abort: 2, id: c2 }, "re-second" + test); |
|
288 c2++; |
|
289 yield undefined; yield undefined; |
|
290 |
|
291 // Test that delete doesn't decrease generator |
|
292 test = " for test delete items" |
|
293 trans = db.transaction(["store1", "store2"], RW); |
|
294 trans.objectStore("store1").add({ delete: 1 }).onsuccess = |
|
295 genCheck(c1++, { delete: 1 }, "first" + test); |
|
296 trans.objectStore("store2").put({ delete: 2 }).onsuccess = |
|
297 genCheck(c2, { delete: 2, id: c2 }, "second" + test); |
|
298 c2++; |
|
299 yield undefined; yield undefined; |
|
300 |
|
301 trans.objectStore("store1").delete(c1 - 1).onsuccess = |
|
302 grabEventAndContinueHandler; |
|
303 trans.objectStore("store2").delete(c2 - 1).onsuccess = |
|
304 grabEventAndContinueHandler; |
|
305 yield undefined; yield undefined; |
|
306 |
|
307 trans.objectStore("store1").add({ delete: 3 }).onsuccess = |
|
308 genCheck(c1++, { delete: 3 }, "first" + test); |
|
309 trans.objectStore("store2").put({ delete: 4 }).onsuccess = |
|
310 genCheck(c2, { delete: 4, id: c2 }, "second" + test); |
|
311 c2++; |
|
312 yield undefined; yield undefined; |
|
313 |
|
314 trans.objectStore("store1").delete(c1 - 1).onsuccess = |
|
315 grabEventAndContinueHandler; |
|
316 trans.objectStore("store2").delete(c2 - 1).onsuccess = |
|
317 grabEventAndContinueHandler; |
|
318 yield undefined; yield undefined; |
|
319 |
|
320 trans = db.transaction(["store1", "store2"], RW); |
|
321 trans.objectStore("store1").add({ delete: 5 }).onsuccess = |
|
322 genCheck(c1++, { delete: 5 }, "first" + test); |
|
323 trans.objectStore("store2").put({ delete: 6 }).onsuccess = |
|
324 genCheck(c2, { delete: 6, id: c2 }, "second" + test); |
|
325 c2++; |
|
326 yield undefined; yield undefined; |
|
327 |
|
328 // Test that clears doesn't decrease generator |
|
329 test = " for test clear stores"; |
|
330 trans = db.transaction(["store1", "store2"], RW); |
|
331 trans.objectStore("store1").add({ clear: 1 }).onsuccess = |
|
332 genCheck(c1++, { clear: 1 }, "first" + test); |
|
333 trans.objectStore("store2").put({ clear: 2 }).onsuccess = |
|
334 genCheck(c2, { clear: 2, id: c2 }, "second" + test); |
|
335 c2++; |
|
336 yield undefined; yield undefined; |
|
337 |
|
338 trans.objectStore("store1").clear().onsuccess = |
|
339 grabEventAndContinueHandler; |
|
340 trans.objectStore("store2").clear().onsuccess = |
|
341 grabEventAndContinueHandler; |
|
342 yield undefined; yield undefined; |
|
343 |
|
344 trans.objectStore("store1").add({ clear: 3 }).onsuccess = |
|
345 genCheck(c1++, { clear: 3 }, "third" + test); |
|
346 trans.objectStore("store2").put({ clear: 4 }).onsuccess = |
|
347 genCheck(c2, { clear: 4, id: c2 }, "forth" + test); |
|
348 c2++; |
|
349 yield undefined; yield undefined; |
|
350 |
|
351 trans.objectStore("store1").clear().onsuccess = |
|
352 grabEventAndContinueHandler; |
|
353 trans.objectStore("store2").clear().onsuccess = |
|
354 grabEventAndContinueHandler; |
|
355 yield undefined; yield undefined; |
|
356 |
|
357 trans = db.transaction(["store1", "store2"], RW); |
|
358 trans.objectStore("store1").add({ clear: 5 }).onsuccess = |
|
359 genCheck(c1++, { clear: 5 }, "fifth" + test); |
|
360 trans.objectStore("store2").put({ clear: 6 }).onsuccess = |
|
361 genCheck(c2, { clear: 6, id: c2 }, "sixth" + test); |
|
362 c2++; |
|
363 yield undefined; yield undefined; |
|
364 |
|
365 |
|
366 // Test that close/reopen doesn't decrease generator |
|
367 test = " for test clear stores"; |
|
368 trans = db.transaction(["store1", "store2"], RW); |
|
369 trans.objectStore("store1").clear().onsuccess = |
|
370 grabEventAndContinueHandler; |
|
371 trans.objectStore("store2").clear().onsuccess = |
|
372 grabEventAndContinueHandler; |
|
373 yield undefined; yield undefined; |
|
374 db.close(); |
|
375 |
|
376 SpecialPowers.gc(); |
|
377 |
|
378 openRequest = indexedDB.open(dbname, 2); |
|
379 openRequest.onerror = errorHandler; |
|
380 openRequest.onupgradeneeded = grabEventAndContinueHandler; |
|
381 openRequest.onsuccess = unexpectedSuccessHandler; |
|
382 event = yield undefined; |
|
383 db = event.target.result; |
|
384 trans = event.target.transaction; |
|
385 |
|
386 trans.objectStore("store1").add({ reopen: 1 }).onsuccess = |
|
387 genCheck(c1++, { reopen: 1 }, "first" + test); |
|
388 trans.objectStore("store2").put({ reopen: 2 }).onsuccess = |
|
389 genCheck(c2, { reopen: 2, id: c2 }, "second" + test); |
|
390 c2++; |
|
391 yield undefined; yield undefined; |
|
392 |
|
393 openRequest.onsuccess = grabEventAndContinueHandler; |
|
394 yield undefined; |
|
395 |
|
396 finishTest(); |
|
397 yield undefined; |
|
398 } |