dom/indexedDB/test/unit/test_lowDiskSpace.js

changeset 2
7e26c7da4463
equal deleted inserted replaced
-1:000000000000 0:1ebd15371572
1 /**
2 * Any copyright is dedicated to the Public Domain.
3 * http://creativecommons.org/publicdomain/zero/1.0/
4 */
5 "use strict";
6
7 var self = this;
8
9 var testGenerator = testSteps();
10
11 function testSteps()
12 {
13 const dbName = self.window ? window.location.pathname : "test_lowDiskSpace";
14 const dbVersion = 1;
15
16 const objectStoreName = "foo";
17 const objectStoreOptions = { keyPath: "foo" };
18
19 const indexName = "bar";
20 const indexOptions = { unique: true };
21
22 const dbData = [
23 { foo: 0, bar: 0 },
24 { foo: 1, bar: 10 },
25 { foo: 2, bar: 20 },
26 { foo: 3, bar: 30 },
27 { foo: 4, bar: 40 },
28 { foo: 5, bar: 50 },
29 { foo: 6, bar: 60 },
30 { foo: 7, bar: 70 },
31 { foo: 8, bar: 80 },
32 { foo: 9, bar: 90 }
33 ];
34
35 let lowDiskMode = false;
36 function setLowDiskMode(val) {
37 let data = val ? "full" : "free";
38
39 if (val == lowDiskMode) {
40 info("Low disk mode is: " + data);
41 }
42 else {
43 info("Changing low disk mode to: " + data);
44 SpecialPowers.notifyObserversInParentProcess(null, "disk-space-watcher",
45 data);
46 lowDiskMode = val;
47 }
48 }
49
50 { // Make sure opening works from the beginning.
51 info("Test 1");
52
53 setLowDiskMode(false);
54
55 let request = indexedDB.open(dbName, dbVersion);
56 request.onerror = errorHandler;
57 request.onsuccess = grabEventAndContinueHandler;
58 let event = yield undefined;
59
60 is(event.type, "success", "Opened database without setting low disk mode");
61
62 let db = event.target.result;
63 db.close();
64 }
65
66 { // Make sure delete works in low disk mode.
67 info("Test 2");
68
69 setLowDiskMode(true);
70
71 let request = indexedDB.deleteDatabase(dbName);
72 request.onerror = errorHandler;
73 request.onsuccess = grabEventAndContinueHandler;
74 let event = yield undefined;
75
76 is(event.type, "success", "Deleted database after setting low disk mode");
77 }
78
79 { // Make sure creating a db in low disk mode fails.
80 info("Test 3");
81
82 setLowDiskMode(true);
83
84 let request = indexedDB.open(dbName, dbVersion);
85 request.onerror = expectedErrorHandler("QuotaExceededError");
86 request.onupgradeneeded = unexpectedSuccessHandler;
87 request.onsuccess = unexpectedSuccessHandler;
88 let event = yield undefined;
89
90 is(event.type, "error", "Didn't create new database in low disk mode");
91 }
92
93 { // Make sure opening an already-existing db in low disk mode succeeds.
94 info("Test 4");
95
96 setLowDiskMode(false);
97
98 let request = indexedDB.open(dbName, dbVersion);
99 request.onerror = errorHandler;
100 request.onupgradeneeded = grabEventAndContinueHandler;
101 request.onsuccess = unexpectedSuccessHandler;
102 let event = yield undefined;
103
104 is(event.type, "upgradeneeded", "Upgrading database");
105
106 let db = event.target.result;
107 db.onerror = errorHandler;
108
109 request.onupgradeneeded = unexpectedSuccessHandler;
110 request.onsuccess = grabEventAndContinueHandler;
111 event = yield undefined;
112
113 is(event.type, "success", "Created database");
114 ok(event.target.result === db, "Got the same database");
115
116 db.close();
117
118 setLowDiskMode(true);
119
120 request = indexedDB.open(dbName);
121 request.onerror = errorHandler;
122 request.onupgradeneeded = unexpectedSuccessHandler;
123 request.onsuccess = grabEventAndContinueHandler;
124 event = yield undefined;
125
126 is(event.type, "success", "Opened existing database in low disk mode");
127
128 db = event.target.result;
129 db.close();
130 }
131
132 { // Make sure upgrading an already-existing db in low disk mode succeeds.
133 info("Test 5");
134
135 setLowDiskMode(true);
136
137 let request = indexedDB.open(dbName, dbVersion + 1);
138 request.onerror = errorHandler;
139 request.onupgradeneeded = grabEventAndContinueHandler;
140 request.onsuccess = unexpectedSuccessHandler;
141
142 let event = yield undefined;
143
144 is(event.type, "upgradeneeded", "Upgrading database");
145
146 let db = event.target.result;
147 db.onerror = errorHandler;
148
149 request.onupgradeneeded = unexpectedSuccessHandler;
150 request.onsuccess = grabEventAndContinueHandler;
151 event = yield undefined;
152
153 is(event.type, "success", "Created database");
154 ok(event.target.result === db, "Got the same database");
155
156 db.close();
157 }
158
159 { // Make sure creating objectStores in low disk mode fails.
160 info("Test 6");
161
162 setLowDiskMode(true);
163
164 let request = indexedDB.open(dbName, dbVersion + 2);
165 request.onerror = expectedErrorHandler("QuotaExceededError");
166 request.onupgradeneeded = grabEventAndContinueHandler;
167 request.onsuccess = unexpectedSuccessHandler;
168
169 let event = yield undefined;
170
171 is(event.type, "upgradeneeded", "Upgrading database");
172
173 let db = event.target.result;
174 db.onerror = errorHandler;
175
176 let objectStore = db.createObjectStore(objectStoreName, objectStoreOptions);
177
178 request.onupgradeneeded = unexpectedSuccessHandler;
179 event = yield undefined;
180
181 is(event.type, "error", "Failed database upgrade");
182 }
183
184 { // Make sure creating indexes in low disk mode fails.
185 info("Test 7");
186
187 setLowDiskMode(false);
188
189 let request = indexedDB.open(dbName, dbVersion + 2);
190 request.onerror = errorHandler;
191 request.onupgradeneeded = grabEventAndContinueHandler;
192 request.onsuccess = unexpectedSuccessHandler;
193
194 let event = yield undefined;
195
196 is(event.type, "upgradeneeded", "Upgrading database");
197
198 let db = event.target.result;
199 db.onerror = errorHandler;
200
201 let objectStore = db.createObjectStore(objectStoreName, objectStoreOptions);
202
203 request.onupgradeneeded = unexpectedSuccessHandler;
204 request.onsuccess = grabEventAndContinueHandler;
205 event = yield undefined;
206
207 is(event.type, "success", "Upgraded database");
208 ok(event.target.result === db, "Got the same database");
209
210 db.close();
211
212 setLowDiskMode(true);
213
214 request = indexedDB.open(dbName, dbVersion + 3);
215 request.onerror = expectedErrorHandler("QuotaExceededError");
216 request.onupgradeneeded = grabEventAndContinueHandler;
217 request.onsuccess = unexpectedSuccessHandler;
218 event = yield undefined;
219
220 is(event.type, "upgradeneeded", "Upgrading database");
221
222 db = event.target.result;
223 db.onerror = errorHandler;
224
225 objectStore = event.target.transaction.objectStore(objectStoreName);
226 let index = objectStore.createIndex(indexName, indexName, indexOptions);
227
228 request.onupgradeneeded = unexpectedSuccessHandler;
229 event = yield undefined;
230
231 is(event.type, "error", "Failed database upgrade");
232 }
233
234 { // Make sure deleting indexes in low disk mode succeeds.
235 info("Test 8");
236
237 setLowDiskMode(false);
238
239 let request = indexedDB.open(dbName, dbVersion + 3);
240 request.onerror = errorHandler;
241 request.onupgradeneeded = grabEventAndContinueHandler;
242 request.onsuccess = unexpectedSuccessHandler;
243
244 let event = yield undefined;
245
246 is(event.type, "upgradeneeded", "Upgrading database");
247
248 let db = event.target.result;
249 db.onerror = errorHandler;
250
251 let objectStore = event.target.transaction.objectStore(objectStoreName);
252 let index = objectStore.createIndex(indexName, indexName, indexOptions);
253
254 request.onupgradeneeded = unexpectedSuccessHandler;
255 request.onsuccess = grabEventAndContinueHandler;
256 event = yield undefined;
257
258 is(event.type, "success", "Upgraded database");
259 ok(event.target.result === db, "Got the same database");
260
261 db.close();
262
263 setLowDiskMode(true);
264
265 request = indexedDB.open(dbName, dbVersion + 4);
266 request.onerror = errorHandler;
267 request.onupgradeneeded = grabEventAndContinueHandler;
268 request.onsuccess = unexpectedSuccessHandler;
269 event = yield undefined;
270
271 is(event.type, "upgradeneeded", "Upgrading database");
272
273 db = event.target.result;
274 db.onerror = errorHandler;
275
276 objectStore = event.target.transaction.objectStore(objectStoreName);
277 objectStore.deleteIndex(indexName);
278
279 request.onupgradeneeded = unexpectedSuccessHandler;
280 request.onsuccess = grabEventAndContinueHandler;
281 event = yield undefined;
282
283 is(event.type, "success", "Upgraded database");
284 ok(event.target.result === db, "Got the same database");
285
286 db.close();
287 }
288
289 { // Make sure deleting objectStores in low disk mode succeeds.
290 info("Test 9");
291
292 setLowDiskMode(true);
293
294 let request = indexedDB.open(dbName, dbVersion + 5);
295 request.onerror = errorHandler;
296 request.onupgradeneeded = grabEventAndContinueHandler;
297 request.onsuccess = unexpectedSuccessHandler;
298
299 let event = yield undefined;
300
301 is(event.type, "upgradeneeded", "Upgrading database");
302
303 let db = event.target.result;
304 db.onerror = errorHandler;
305
306 db.deleteObjectStore(objectStoreName);
307
308 request.onupgradeneeded = unexpectedSuccessHandler;
309 request.onsuccess = grabEventAndContinueHandler;
310 event = yield undefined;
311
312 is(event.type, "success", "Upgraded database");
313 ok(event.target.result === db, "Got the same database");
314
315 db.close();
316
317 // Reset everything.
318 indexedDB.deleteDatabase(dbName);
319 }
320
321
322 { // Add data that the rest of the tests will use.
323 info("Adding test data");
324
325 setLowDiskMode(false);
326
327 let request = indexedDB.open(dbName, dbVersion);
328 request.onerror = errorHandler;
329 request.onupgradeneeded = grabEventAndContinueHandler;
330 request.onsuccess = unexpectedSuccessHandler;
331 let event = yield undefined;
332
333 is(event.type, "upgradeneeded", "Upgrading database");
334
335 let db = event.target.result;
336 db.onerror = errorHandler;
337
338 let objectStore = db.createObjectStore(objectStoreName, objectStoreOptions);
339 let index = objectStore.createIndex(indexName, indexName, indexOptions);
340
341 for each (let data in dbData) {
342 objectStore.add(data);
343 }
344
345 request.onupgradeneeded = unexpectedSuccessHandler;
346 request.onsuccess = grabEventAndContinueHandler;
347 event = yield undefined;
348
349 is(event.type, "success", "Upgraded database");
350 ok(event.target.result === db, "Got the same database");
351
352 db.close();
353 }
354
355 { // Make sure read operations in readonly transactions succeed in low disk
356 // mode.
357 info("Test 10");
358
359 setLowDiskMode(true);
360
361 let request = indexedDB.open(dbName, dbVersion);
362 request.onerror = errorHandler;
363 request.onupgradeneeded = unexpectedSuccessHandler;
364 request.onsuccess = grabEventAndContinueHandler;
365 let event = yield undefined;
366
367 let db = event.target.result;
368 db.onerror = errorHandler;
369
370 let transaction = db.transaction(objectStoreName);
371 let objectStore = transaction.objectStore(objectStoreName);
372 let index = objectStore.index(indexName);
373
374 let data = dbData[0];
375
376 let requestCounter = new RequestCounter();
377
378 objectStore.get(data.foo).onsuccess = requestCounter.handler();
379 objectStore.mozGetAll().onsuccess = requestCounter.handler();
380 objectStore.count().onsuccess = requestCounter.handler();
381 index.get(data.bar).onsuccess = requestCounter.handler();
382 index.mozGetAll().onsuccess = requestCounter.handler();
383 index.getKey(data.bar).onsuccess = requestCounter.handler();
384 index.mozGetAllKeys().onsuccess = requestCounter.handler();
385 index.count().onsuccess = requestCounter.handler();
386
387 let objectStoreDataCount = 0;
388
389 request = objectStore.openCursor();
390 request.onsuccess = function(event) {
391 let cursor = event.target.result;
392 if (cursor) {
393 objectStoreDataCount++;
394 objectStoreDataCount % 2 ? cursor.continue() : cursor.advance(1);
395 }
396 else {
397 is(objectStoreDataCount, dbData.length, "Saw all data");
398 requestCounter.decr();
399 }
400 };
401 requestCounter.incr();
402
403 let indexDataCount = 0;
404
405 request = index.openCursor();
406 request.onsuccess = function(event) {
407 let cursor = event.target.result;
408 if (cursor) {
409 indexDataCount++;
410 indexDataCount % 2 ? cursor.continue() : cursor.advance(1);
411 }
412 else {
413 is(indexDataCount, dbData.length, "Saw all data");
414 requestCounter.decr();
415 }
416 };
417 requestCounter.incr();
418
419 let indexKeyDataCount = 0;
420
421 request = index.openCursor();
422 request.onsuccess = function(event) {
423 let cursor = event.target.result;
424 if (cursor) {
425 indexKeyDataCount++;
426 indexKeyDataCount % 2 ? cursor.continue() : cursor.advance(1);
427 }
428 else {
429 is(indexKeyDataCount, dbData.length, "Saw all data");
430 requestCounter.decr();
431 }
432 };
433 requestCounter.incr();
434
435 // Wait for all requests.
436 yield undefined;
437
438 transaction.oncomplete = grabEventAndContinueHandler;
439 event = yield undefined;
440
441 is(event.type, "complete", "Transaction succeeded");
442
443 db.close();
444 }
445
446 { // Make sure read operations in readwrite transactions succeed in low disk
447 // mode.
448 info("Test 11");
449
450 setLowDiskMode(true);
451
452 let request = indexedDB.open(dbName, dbVersion);
453 request.onerror = errorHandler;
454 request.onupgradeneeded = unexpectedSuccessHandler;
455 request.onsuccess = grabEventAndContinueHandler;
456 let event = yield undefined;
457
458 let db = event.target.result;
459 db.onerror = errorHandler;
460
461 let transaction = db.transaction(objectStoreName, "readwrite");
462 let objectStore = transaction.objectStore(objectStoreName);
463 let index = objectStore.index(indexName);
464
465 let data = dbData[0];
466
467 let requestCounter = new RequestCounter();
468
469 objectStore.get(data.foo).onsuccess = requestCounter.handler();
470 objectStore.mozGetAll().onsuccess = requestCounter.handler();
471 objectStore.count().onsuccess = requestCounter.handler();
472 index.get(data.bar).onsuccess = requestCounter.handler();
473 index.mozGetAll().onsuccess = requestCounter.handler();
474 index.getKey(data.bar).onsuccess = requestCounter.handler();
475 index.mozGetAllKeys().onsuccess = requestCounter.handler();
476 index.count().onsuccess = requestCounter.handler();
477
478 let objectStoreDataCount = 0;
479
480 request = objectStore.openCursor();
481 request.onsuccess = function(event) {
482 let cursor = event.target.result;
483 if (cursor) {
484 objectStoreDataCount++;
485 objectStoreDataCount % 2 ? cursor.continue() : cursor.advance(1);
486 }
487 else {
488 is(objectStoreDataCount, dbData.length, "Saw all data");
489 requestCounter.decr();
490 }
491 };
492 requestCounter.incr();
493
494 let indexDataCount = 0;
495
496 request = index.openCursor();
497 request.onsuccess = function(event) {
498 let cursor = event.target.result;
499 if (cursor) {
500 indexDataCount++;
501 indexDataCount % 2 ? cursor.continue() : cursor.advance(1);
502 }
503 else {
504 is(indexDataCount, dbData.length, "Saw all data");
505 requestCounter.decr();
506 }
507 };
508 requestCounter.incr();
509
510 let indexKeyDataCount = 0;
511
512 request = index.openCursor();
513 request.onsuccess = function(event) {
514 let cursor = event.target.result;
515 if (cursor) {
516 indexKeyDataCount++;
517 indexKeyDataCount % 2 ? cursor.continue() : cursor.advance(1);
518 }
519 else {
520 is(indexKeyDataCount, dbData.length, "Saw all data");
521 requestCounter.decr();
522 }
523 };
524 requestCounter.incr();
525
526 // Wait for all requests.
527 yield undefined;
528
529 transaction.oncomplete = grabEventAndContinueHandler;
530 event = yield undefined;
531
532 is(event.type, "complete", "Transaction succeeded");
533
534 db.close();
535 }
536
537 { // Make sure write operations in readwrite transactions fail in low disk
538 // mode.
539 info("Test 12");
540
541 setLowDiskMode(true);
542
543 let request = indexedDB.open(dbName, dbVersion);
544 request.onerror = errorHandler;
545 request.onupgradeneeded = unexpectedSuccessHandler;
546 request.onsuccess = grabEventAndContinueHandler;
547 let event = yield undefined;
548
549 let db = event.target.result;
550 db.onerror = errorHandler;
551
552 let transaction = db.transaction(objectStoreName, "readwrite");
553 let objectStore = transaction.objectStore(objectStoreName);
554 let index = objectStore.index(indexName);
555
556 let data = dbData[0];
557 let newData = { foo: 999, bar: 999 };
558
559 let requestCounter = new RequestCounter();
560
561 objectStore.add(newData).onerror = requestCounter.errorHandler();
562 objectStore.put(newData).onerror = requestCounter.errorHandler();
563
564 objectStore.get(data.foo).onsuccess = requestCounter.handler();
565 objectStore.mozGetAll().onsuccess = requestCounter.handler();
566 objectStore.count().onsuccess = requestCounter.handler();
567 index.get(data.bar).onsuccess = requestCounter.handler();
568 index.mozGetAll().onsuccess = requestCounter.handler();
569 index.getKey(data.bar).onsuccess = requestCounter.handler();
570 index.mozGetAllKeys().onsuccess = requestCounter.handler();
571 index.count().onsuccess = requestCounter.handler();
572
573 let objectStoreDataCount = 0;
574
575 request = objectStore.openCursor();
576 request.onsuccess = function(event) {
577 let cursor = event.target.result;
578 if (cursor) {
579 objectStoreDataCount++;
580 cursor.update(cursor.value).onerror = requestCounter.errorHandler();
581 objectStoreDataCount % 2 ? cursor.continue() : cursor.advance(1);
582 }
583 else {
584 is(objectStoreDataCount, dbData.length, "Saw all data");
585 requestCounter.decr();
586 }
587 };
588 requestCounter.incr();
589
590 let indexDataCount = 0;
591
592 request = index.openCursor();
593 request.onsuccess = function(event) {
594 let cursor = event.target.result;
595 if (cursor) {
596 indexDataCount++;
597 cursor.update(cursor.value).onerror = requestCounter.errorHandler();
598 indexDataCount % 2 ? cursor.continue() : cursor.advance(1);
599 }
600 else {
601 is(indexDataCount, dbData.length, "Saw all data");
602 requestCounter.decr();
603 }
604 };
605 requestCounter.incr();
606
607 let indexKeyDataCount = 0;
608
609 request = index.openCursor();
610 request.onsuccess = function(event) {
611 let cursor = event.target.result;
612 if (cursor) {
613 indexKeyDataCount++;
614 cursor.update(cursor.value).onerror = requestCounter.errorHandler();
615 indexKeyDataCount % 2 ? cursor.continue() : cursor.advance(1);
616 }
617 else {
618 is(indexKeyDataCount, dbData.length, "Saw all data");
619 requestCounter.decr();
620 }
621 };
622 requestCounter.incr();
623
624 // Wait for all requests.
625 yield undefined;
626
627 transaction.oncomplete = grabEventAndContinueHandler;
628 event = yield undefined;
629
630 is(event.type, "complete", "Transaction succeeded");
631
632 db.close();
633 }
634
635 { // Make sure deleting operations in readwrite transactions succeed in low
636 // disk mode.
637 info("Test 13");
638
639 setLowDiskMode(true);
640
641 let request = indexedDB.open(dbName, dbVersion);
642 request.onerror = errorHandler;
643 request.onupgradeneeded = unexpectedSuccessHandler;
644 request.onsuccess = grabEventAndContinueHandler;
645 let event = yield undefined;
646
647 let db = event.target.result;
648 db.onerror = errorHandler;
649
650 let transaction = db.transaction(objectStoreName, "readwrite");
651 let objectStore = transaction.objectStore(objectStoreName);
652 let index = objectStore.index(indexName);
653
654 let dataIndex = 0;
655 let data = dbData[dataIndex++];
656
657 let requestCounter = new RequestCounter();
658
659 objectStore.delete(data.foo).onsuccess = requestCounter.handler();
660
661 objectStore.openCursor().onsuccess = function(event) {
662 let cursor = event.target.result;
663 if (cursor) {
664 cursor.delete().onsuccess = requestCounter.handler();
665 }
666 requestCounter.decr();
667 };
668 requestCounter.incr();
669
670 index.openCursor(null, "prev").onsuccess = function(event) {
671 let cursor = event.target.result;
672 if (cursor) {
673 cursor.delete().onsuccess = requestCounter.handler();
674 }
675 requestCounter.decr();
676 };
677 requestCounter.incr();
678
679 yield undefined;
680
681 objectStore.count().onsuccess = grabEventAndContinueHandler;
682 event = yield undefined;
683
684 is(event.target.result, dbData.length - 3, "Actually deleted something");
685
686 objectStore.clear();
687 objectStore.count().onsuccess = grabEventAndContinueHandler;
688 event = yield undefined;
689
690 is(event.target.result, 0, "Actually cleared");
691
692 transaction.oncomplete = grabEventAndContinueHandler;
693 event = yield undefined;
694
695 is(event.type, "complete", "Transaction succeeded");
696
697 db.close();
698 }
699
700 finishTest();
701 yield undefined;
702 }
703
704 function RequestCounter(expectedType) {
705 this._counter = 0;
706 }
707 RequestCounter.prototype = {
708 incr: function() {
709 this._counter++;
710 },
711
712 decr: function() {
713 if (!--this._counter) {
714 continueToNextStepSync();
715 }
716 },
717
718 handler: function(type, preventDefault) {
719 this.incr();
720 return function(event) {
721 is(event.type, type || "success", "Correct type");
722 this.decr();
723 }.bind(this);
724 },
725
726 errorHandler: function(eventType, errorName) {
727 this.incr();
728 return function(event) {
729 is(event.type, eventType || "error", "Correct type");
730 is(event.target.error.name, errorName || "QuotaExceededError",
731 "Correct error name");
732 event.preventDefault();
733 event.stopPropagation();
734 this.decr();
735 }.bind(this);
736 }
737 };

mercurial