dom/indexedDB/test/unit/test_lowDiskSpace.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /**
     2  * Any copyright is dedicated to the Public Domain.
     3  * http://creativecommons.org/publicdomain/zero/1.0/
     4  */
     5 "use strict";
     7 var self = this;
     9 var testGenerator = testSteps();
    11 function testSteps()
    12 {
    13   const dbName = self.window ? window.location.pathname : "test_lowDiskSpace";
    14   const dbVersion = 1;
    16   const objectStoreName = "foo";
    17   const objectStoreOptions = { keyPath: "foo" };
    19   const indexName = "bar";
    20   const indexOptions = { unique: true };
    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   ];
    35   let lowDiskMode = false;
    36   function setLowDiskMode(val) {
    37     let data = val ? "full" : "free";
    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   }
    50   { // Make sure opening works from the beginning.
    51     info("Test 1");
    53     setLowDiskMode(false);
    55     let request = indexedDB.open(dbName, dbVersion);
    56     request.onerror = errorHandler;
    57     request.onsuccess = grabEventAndContinueHandler;
    58     let event = yield undefined;
    60     is(event.type, "success", "Opened database without setting low disk mode");
    62     let db = event.target.result;
    63     db.close();
    64   }
    66   { // Make sure delete works in low disk mode.
    67     info("Test 2");
    69     setLowDiskMode(true);
    71     let request = indexedDB.deleteDatabase(dbName);
    72     request.onerror = errorHandler;
    73     request.onsuccess = grabEventAndContinueHandler;
    74     let event = yield undefined;
    76     is(event.type, "success", "Deleted database after setting low disk mode");
    77   }
    79   { // Make sure creating a db in low disk mode fails.
    80     info("Test 3");
    82     setLowDiskMode(true);
    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;
    90     is(event.type, "error", "Didn't create new database in low disk mode");
    91   }
    93   { // Make sure opening an already-existing db in low disk mode succeeds.
    94     info("Test 4");
    96     setLowDiskMode(false);
    98     let request = indexedDB.open(dbName, dbVersion);
    99     request.onerror = errorHandler;
   100     request.onupgradeneeded = grabEventAndContinueHandler;
   101     request.onsuccess = unexpectedSuccessHandler;
   102     let event = yield undefined;
   104     is(event.type, "upgradeneeded", "Upgrading database");
   106     let db = event.target.result;
   107     db.onerror = errorHandler;
   109     request.onupgradeneeded = unexpectedSuccessHandler;
   110     request.onsuccess = grabEventAndContinueHandler;
   111     event = yield undefined;
   113     is(event.type, "success", "Created database");
   114     ok(event.target.result === db, "Got the same database");
   116     db.close();
   118     setLowDiskMode(true);
   120     request = indexedDB.open(dbName);
   121     request.onerror = errorHandler;
   122     request.onupgradeneeded = unexpectedSuccessHandler;
   123     request.onsuccess = grabEventAndContinueHandler;
   124     event = yield undefined;
   126     is(event.type, "success", "Opened existing database in low disk mode");
   128     db = event.target.result;
   129     db.close();
   130   }
   132   { // Make sure upgrading an already-existing db in low disk mode succeeds.
   133     info("Test 5");
   135     setLowDiskMode(true);
   137     let request = indexedDB.open(dbName, dbVersion + 1);
   138     request.onerror = errorHandler;
   139     request.onupgradeneeded = grabEventAndContinueHandler;
   140     request.onsuccess = unexpectedSuccessHandler;
   142     let event = yield undefined;
   144     is(event.type, "upgradeneeded", "Upgrading database");
   146     let db = event.target.result;
   147     db.onerror = errorHandler;
   149     request.onupgradeneeded = unexpectedSuccessHandler;
   150     request.onsuccess = grabEventAndContinueHandler;
   151     event = yield undefined;
   153     is(event.type, "success", "Created database");
   154     ok(event.target.result === db, "Got the same database");
   156     db.close();
   157   }
   159   { // Make sure creating objectStores in low disk mode fails.
   160     info("Test 6");
   162     setLowDiskMode(true);
   164     let request = indexedDB.open(dbName, dbVersion + 2);
   165     request.onerror = expectedErrorHandler("QuotaExceededError");
   166     request.onupgradeneeded = grabEventAndContinueHandler;
   167     request.onsuccess = unexpectedSuccessHandler;
   169     let event = yield undefined;
   171     is(event.type, "upgradeneeded", "Upgrading database");
   173     let db = event.target.result;
   174     db.onerror = errorHandler;
   176     let objectStore = db.createObjectStore(objectStoreName, objectStoreOptions);
   178     request.onupgradeneeded = unexpectedSuccessHandler;
   179     event = yield undefined;
   181     is(event.type, "error", "Failed database upgrade");
   182   }
   184   { // Make sure creating indexes in low disk mode fails.
   185     info("Test 7");
   187     setLowDiskMode(false);
   189     let request = indexedDB.open(dbName, dbVersion + 2);
   190     request.onerror = errorHandler;
   191     request.onupgradeneeded = grabEventAndContinueHandler;
   192     request.onsuccess = unexpectedSuccessHandler;
   194     let event = yield undefined;
   196     is(event.type, "upgradeneeded", "Upgrading database");
   198     let db = event.target.result;
   199     db.onerror = errorHandler;
   201     let objectStore = db.createObjectStore(objectStoreName, objectStoreOptions);
   203     request.onupgradeneeded = unexpectedSuccessHandler;
   204     request.onsuccess = grabEventAndContinueHandler;
   205     event = yield undefined;
   207     is(event.type, "success", "Upgraded database");
   208     ok(event.target.result === db, "Got the same database");
   210     db.close();
   212     setLowDiskMode(true);
   214     request = indexedDB.open(dbName, dbVersion + 3);
   215     request.onerror = expectedErrorHandler("QuotaExceededError");
   216     request.onupgradeneeded = grabEventAndContinueHandler;
   217     request.onsuccess = unexpectedSuccessHandler;
   218     event = yield undefined;
   220     is(event.type, "upgradeneeded", "Upgrading database");
   222     db = event.target.result;
   223     db.onerror = errorHandler;
   225     objectStore = event.target.transaction.objectStore(objectStoreName);
   226     let index = objectStore.createIndex(indexName, indexName, indexOptions);
   228     request.onupgradeneeded = unexpectedSuccessHandler;
   229     event = yield undefined;
   231     is(event.type, "error", "Failed database upgrade");
   232   }
   234   { // Make sure deleting indexes in low disk mode succeeds.
   235     info("Test 8");
   237     setLowDiskMode(false);
   239     let request = indexedDB.open(dbName, dbVersion + 3);
   240     request.onerror = errorHandler;
   241     request.onupgradeneeded = grabEventAndContinueHandler;
   242     request.onsuccess = unexpectedSuccessHandler;
   244     let event = yield undefined;
   246     is(event.type, "upgradeneeded", "Upgrading database");
   248     let db = event.target.result;
   249     db.onerror = errorHandler;
   251     let objectStore = event.target.transaction.objectStore(objectStoreName);
   252     let index = objectStore.createIndex(indexName, indexName, indexOptions);
   254     request.onupgradeneeded = unexpectedSuccessHandler;
   255     request.onsuccess = grabEventAndContinueHandler;
   256     event = yield undefined;
   258     is(event.type, "success", "Upgraded database");
   259     ok(event.target.result === db, "Got the same database");
   261     db.close();
   263     setLowDiskMode(true);
   265     request = indexedDB.open(dbName, dbVersion + 4);
   266     request.onerror = errorHandler;
   267     request.onupgradeneeded = grabEventAndContinueHandler;
   268     request.onsuccess = unexpectedSuccessHandler;
   269     event = yield undefined;
   271     is(event.type, "upgradeneeded", "Upgrading database");
   273     db = event.target.result;
   274     db.onerror = errorHandler;
   276     objectStore = event.target.transaction.objectStore(objectStoreName);
   277     objectStore.deleteIndex(indexName);
   279     request.onupgradeneeded = unexpectedSuccessHandler;
   280     request.onsuccess = grabEventAndContinueHandler;
   281     event = yield undefined;
   283     is(event.type, "success", "Upgraded database");
   284     ok(event.target.result === db, "Got the same database");
   286     db.close();
   287   }
   289   { // Make sure deleting objectStores in low disk mode succeeds.
   290     info("Test 9");
   292     setLowDiskMode(true);
   294     let request = indexedDB.open(dbName, dbVersion + 5);
   295     request.onerror = errorHandler;
   296     request.onupgradeneeded = grabEventAndContinueHandler;
   297     request.onsuccess = unexpectedSuccessHandler;
   299     let event = yield undefined;
   301     is(event.type, "upgradeneeded", "Upgrading database");
   303     let db = event.target.result;
   304     db.onerror = errorHandler;
   306     db.deleteObjectStore(objectStoreName);
   308     request.onupgradeneeded = unexpectedSuccessHandler;
   309     request.onsuccess = grabEventAndContinueHandler;
   310     event = yield undefined;
   312     is(event.type, "success", "Upgraded database");
   313     ok(event.target.result === db, "Got the same database");
   315     db.close();
   317     // Reset everything.
   318     indexedDB.deleteDatabase(dbName);
   319   }
   322   { // Add data that the rest of the tests will use.
   323     info("Adding test data");
   325     setLowDiskMode(false);
   327     let request = indexedDB.open(dbName, dbVersion);
   328     request.onerror = errorHandler;
   329     request.onupgradeneeded = grabEventAndContinueHandler;
   330     request.onsuccess = unexpectedSuccessHandler;
   331     let event = yield undefined;
   333     is(event.type, "upgradeneeded", "Upgrading database");
   335     let db = event.target.result;
   336     db.onerror = errorHandler;
   338     let objectStore = db.createObjectStore(objectStoreName, objectStoreOptions);
   339     let index = objectStore.createIndex(indexName, indexName, indexOptions);
   341     for each (let data in dbData) {
   342       objectStore.add(data);
   343     }
   345     request.onupgradeneeded = unexpectedSuccessHandler;
   346     request.onsuccess = grabEventAndContinueHandler;
   347     event = yield undefined;
   349     is(event.type, "success", "Upgraded database");
   350     ok(event.target.result === db, "Got the same database");
   352     db.close();
   353   }
   355   { // Make sure read operations in readonly transactions succeed in low disk
   356     // mode.
   357     info("Test 10");
   359     setLowDiskMode(true);
   361     let request = indexedDB.open(dbName, dbVersion);
   362     request.onerror = errorHandler;
   363     request.onupgradeneeded = unexpectedSuccessHandler;
   364     request.onsuccess = grabEventAndContinueHandler;
   365     let event = yield undefined;
   367     let db = event.target.result;
   368     db.onerror = errorHandler;
   370     let transaction = db.transaction(objectStoreName);
   371     let objectStore = transaction.objectStore(objectStoreName);
   372     let index = objectStore.index(indexName);
   374     let data = dbData[0];
   376     let requestCounter = new RequestCounter();
   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();
   387     let objectStoreDataCount = 0;
   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();
   403     let indexDataCount = 0;
   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();
   419     let indexKeyDataCount = 0;
   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();
   435     // Wait for all requests.
   436     yield undefined;
   438     transaction.oncomplete = grabEventAndContinueHandler;
   439     event = yield undefined;
   441     is(event.type, "complete", "Transaction succeeded");
   443     db.close();
   444   }
   446   { // Make sure read operations in readwrite transactions succeed in low disk
   447     // mode.
   448     info("Test 11");
   450     setLowDiskMode(true);
   452     let request = indexedDB.open(dbName, dbVersion);
   453     request.onerror = errorHandler;
   454     request.onupgradeneeded = unexpectedSuccessHandler;
   455     request.onsuccess = grabEventAndContinueHandler;
   456     let event = yield undefined;
   458     let db = event.target.result;
   459     db.onerror = errorHandler;
   461     let transaction = db.transaction(objectStoreName, "readwrite");
   462     let objectStore = transaction.objectStore(objectStoreName);
   463     let index = objectStore.index(indexName);
   465     let data = dbData[0];
   467     let requestCounter = new RequestCounter();
   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();
   478     let objectStoreDataCount = 0;
   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();
   494     let indexDataCount = 0;
   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();
   510     let indexKeyDataCount = 0;
   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();
   526     // Wait for all requests.
   527     yield undefined;
   529     transaction.oncomplete = grabEventAndContinueHandler;
   530     event = yield undefined;
   532     is(event.type, "complete", "Transaction succeeded");
   534     db.close();
   535   }
   537   { // Make sure write operations in readwrite transactions fail in low disk
   538     // mode.
   539     info("Test 12");
   541     setLowDiskMode(true);
   543     let request = indexedDB.open(dbName, dbVersion);
   544     request.onerror = errorHandler;
   545     request.onupgradeneeded = unexpectedSuccessHandler;
   546     request.onsuccess = grabEventAndContinueHandler;
   547     let event = yield undefined;
   549     let db = event.target.result;
   550     db.onerror = errorHandler;
   552     let transaction = db.transaction(objectStoreName, "readwrite");
   553     let objectStore = transaction.objectStore(objectStoreName);
   554     let index = objectStore.index(indexName);
   556     let data = dbData[0];
   557     let newData = { foo: 999, bar: 999 };
   559     let requestCounter = new RequestCounter();
   561     objectStore.add(newData).onerror = requestCounter.errorHandler();
   562     objectStore.put(newData).onerror = requestCounter.errorHandler();
   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();
   573     let objectStoreDataCount = 0;
   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();
   590     let indexDataCount = 0;
   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();
   607     let indexKeyDataCount = 0;
   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();
   624     // Wait for all requests.
   625     yield undefined;
   627     transaction.oncomplete = grabEventAndContinueHandler;
   628     event = yield undefined;
   630     is(event.type, "complete", "Transaction succeeded");
   632     db.close();
   633   }
   635   { // Make sure deleting operations in readwrite transactions succeed in low
   636     // disk mode.
   637     info("Test 13");
   639     setLowDiskMode(true);
   641     let request = indexedDB.open(dbName, dbVersion);
   642     request.onerror = errorHandler;
   643     request.onupgradeneeded = unexpectedSuccessHandler;
   644     request.onsuccess = grabEventAndContinueHandler;
   645     let event = yield undefined;
   647     let db = event.target.result;
   648     db.onerror = errorHandler;
   650     let transaction = db.transaction(objectStoreName, "readwrite");
   651     let objectStore = transaction.objectStore(objectStoreName);
   652     let index = objectStore.index(indexName);
   654     let dataIndex = 0;
   655     let data = dbData[dataIndex++];
   657     let requestCounter = new RequestCounter();
   659     objectStore.delete(data.foo).onsuccess = requestCounter.handler();
   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();
   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();
   679     yield undefined;
   681     objectStore.count().onsuccess = grabEventAndContinueHandler;
   682     event = yield undefined;
   684     is(event.target.result, dbData.length - 3, "Actually deleted something");
   686     objectStore.clear();
   687     objectStore.count().onsuccess = grabEventAndContinueHandler;
   688     event = yield undefined;
   690     is(event.target.result, 0, "Actually cleared");
   692     transaction.oncomplete = grabEventAndContinueHandler;
   693     event = yield undefined;
   695     is(event.type, "complete", "Transaction succeeded");
   697     db.close();
   698   }
   700   finishTest();
   701   yield undefined;
   702 }
   704 function RequestCounter(expectedType) {
   705   this._counter = 0;
   706 }
   707 RequestCounter.prototype = {
   708   incr: function() {
   709     this._counter++;
   710   },
   712   decr: function() {
   713     if (!--this._counter) {
   714       continueToNextStepSync();
   715     }
   716   },
   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   },
   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