dom/indexedDB/test/unit/test_transaction_abort.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  */
     6 var testGenerator = testSteps();
     8 var abortFired = false;
    10 function abortListener(evt)
    11 {
    12   abortFired = true;
    13   is(evt.target.error, null, "Expect a null error for an aborted transaction");
    14 }
    16 function testSteps()
    17 {
    18   const Ci = Components.interfaces;
    20   const name = this.window ? window.location.pathname : "Splendid Test";
    22   let request = indexedDB.open(name, 1);
    23   request.onerror = errorHandler;
    24   request.onupgradeneeded = grabEventAndContinueHandler;
    25   request.onsuccess = grabEventAndContinueHandler;
    26   let event = yield undefined;
    28   let db = event.target.result;
    29   db.onabort = abortListener;
    31   let transaction;
    32   let objectStore;
    33   let index;
    35   transaction = event.target.transaction;
    37   try {
    38     let error = transaction.error;
    39     ok(false, "Expect an exception");
    40   } catch(e) {
    41     ok(true, "Got an exception.");
    42     is(e.name, "InvalidStateError", "Got the right exception");
    43   }
    45   objectStore = db.createObjectStore("foo", { autoIncrement: true });
    46   index = objectStore.createIndex("fooindex", "indexKey", { unique: true });
    48   is(transaction.db, db, "Correct database");
    49   is(transaction.mode, "versionchange", "Correct mode");
    50   is(transaction.objectStoreNames.length, 1, "Correct names length");
    51   is(transaction.objectStoreNames.item(0), "foo", "Correct name");
    52   is(transaction.objectStore("foo"), objectStore, "Can get stores");
    53   is(transaction.oncomplete, null, "No complete listener");
    54   is(transaction.onabort, null, "No abort listener");
    56   is(objectStore.name, "foo", "Correct name");
    57   is(objectStore.keyPath, null, "Correct keyPath");
    59   is(objectStore.indexNames.length, 1, "Correct indexNames length");
    60   is(objectStore.indexNames[0], "fooindex", "Correct indexNames name");
    61   is(objectStore.index("fooindex"), index, "Can get index");
    63   // Wait until it's complete!
    64   transaction.oncomplete = grabEventAndContinueHandler;
    65   event = yield undefined;
    67   is(transaction.db, db, "Correct database");
    68   is(transaction.mode, "versionchange", "Correct mode");
    69   is(transaction.objectStoreNames.length, 1, "Correct names length");
    70   is(transaction.objectStoreNames.item(0), "foo", "Correct name");
    71   is(transaction.onabort, null, "No abort listener");
    73   try {
    74     is(transaction.objectStore("foo").name, "foo", "Can't get stores");
    75     ok(false, "Should have thrown");
    76   }
    77   catch (e) {
    78     ok(true, "Out of scope transaction can't make stores");
    79   }
    81   is(objectStore.name, "foo", "Correct name");
    82   is(objectStore.keyPath, null, "Correct keyPath");
    84   is(objectStore.indexNames.length, 1, "Correct indexNames length");
    85   is(objectStore.indexNames[0], "fooindex", "Correct indexNames name");
    87   try {
    88     objectStore.add({});
    89     ok(false, "Should have thrown");
    90   }
    91   catch (e) {
    92     ok(true, "Add threw");
    93   }
    95   try {
    96     objectStore.put({}, 1);
    97     ok(false, "Should have thrown");
    98   }
    99   catch (e) {
   100     ok(true, "Put threw");
   101   }
   103   try {
   104     objectStore.put({}, 1);
   105     ok(false, "Should have thrown");
   106   }
   107   catch (e) {
   108     ok(true, "Put threw");
   109   }
   111   try {
   112     objectStore.delete(1);
   113     ok(false, "Should have thrown");
   114   }
   115   catch (e) {
   116     ok(true, "Remove threw");
   117   }
   119   try {
   120     objectStore.get(1);
   121     ok(false, "Should have thrown");
   122   }
   123   catch (e) {
   124     ok(true, "Get threw");
   125   }
   127   try {
   128     objectStore.getAll(null);
   129     ok(false, "Should have thrown");
   130   }
   131   catch (e) {
   132     ok(true, "GetAll threw");
   133   }
   135   try {
   136     objectStore.openCursor();
   137     ok(false, "Should have thrown");
   138   }
   139   catch (e) {
   140     ok(true, "OpenCursor threw");
   141   }
   143   try {
   144     objectStore.createIndex("bar", "id");
   145     ok(false, "Should have thrown");
   146   }
   147   catch (e) {
   148     ok(true, "CreateIndex threw");
   149   }
   151   try {
   152     objectStore.index("bar");
   153     ok(false, "Should have thrown");
   154   }
   155   catch (e) {
   156     ok(true, "Index threw");
   157   }
   159   try {
   160     objectStore.deleteIndex("bar");
   161     ok(false, "Should have thrown");
   162   }
   163   catch (e) {
   164     ok(true, "RemoveIndex threw");
   165   }
   167   yield undefined;
   169   request = db.transaction("foo", "readwrite").objectStore("foo").add({});
   170   request.onerror = errorHandler;
   171   request.onsuccess = grabEventAndContinueHandler;
   172   event = yield undefined;
   174   event.target.transaction.onabort = function(event) {
   175     ok(false, "Shouldn't see an abort event!");
   176   };
   177   event.target.transaction.oncomplete = grabEventAndContinueHandler;
   178   event = yield undefined;
   180   is(event.type, "complete", "Right kind of event");
   182   let key;
   184   request = db.transaction("foo", "readwrite").objectStore("foo").add({});
   185   request.onerror = errorHandler;
   186   request.onsuccess = grabEventAndContinueHandler;
   187   event = yield undefined;
   189   key = event.target.result;
   191   event.target.transaction.onabort = grabEventAndContinueHandler;
   192   event.target.transaction.oncomplete = function(event) {
   193     ok(false, "Shouldn't see a complete event here!");
   194   };
   196   event.target.transaction.abort();
   198   event = yield undefined;
   200   is(event.type, "abort", "Right kind of event");
   202   request = db.transaction("foo").objectStore("foo").get(key);
   203   request.onerror = errorHandler;
   204   request.onsuccess = grabEventAndContinueHandler;
   205   event = yield undefined;
   207   is(event.target.result, undefined, "Object was removed");
   209   executeSoon(function() { testGenerator.next(); });
   210   yield undefined;
   212   let keys = [];
   213   let abortEventCount = 0;
   214   function abortErrorHandler(event) {
   215       is(event.target.error.name, "AbortError",
   216          "Good error");
   217       abortEventCount++;
   218       event.preventDefault();
   219   };
   220   objectStore = db.transaction("foo", "readwrite").objectStore("foo");
   222   for (let i = 0; i < 10; i++) {
   223     request = objectStore.add({});
   224     request.onerror = abortErrorHandler;
   225     request.onsuccess = function(event) {
   226       keys.push(event.target.result);
   227       if (keys.length == 5) {
   228         event.target.transaction.onabort = grabEventAndContinueHandler;
   229         event.target.transaction.abort();
   230       }
   231     };
   232   }
   233   event = yield undefined;
   235   is(event.type, "abort", "Got abort event");
   236   is(keys.length, 5, "Added 5 items in this transaction");
   237   is(abortEventCount, 5, "Got 5 abort error events");
   239   for (let i in keys) {
   240     request = db.transaction("foo").objectStore("foo").get(keys[i]);
   241     request.onerror = errorHandler;
   242     request.onsuccess = grabEventAndContinueHandler;
   243     event = yield undefined;
   245     is(event.target.result, undefined, "Object was removed by abort");
   246   }
   248   // Set up some predictible data
   249   transaction = db.transaction("foo", "readwrite");
   250   objectStore = transaction.objectStore("foo");
   251   objectStore.clear();
   252   objectStore.add({}, 1);
   253   objectStore.add({}, 2);
   254   request = objectStore.add({}, 1);
   255   request.onsuccess = function() {
   256     ok(false, "inserting duplicate key should fail");
   257   }
   258   request.onerror = function(event) {
   259     ok(true, "inserting duplicate key should fail");
   260     event.preventDefault();
   261   }
   262   transaction.oncomplete = grabEventAndContinueHandler;
   263   yield undefined;
   265   // Check when aborting is allowed
   266   abortEventCount = 0;
   267   let expectedAbortEventCount = 0;
   269   // During INITIAL
   270   transaction = db.transaction("foo");
   271   transaction.abort();
   272   try {
   273     transaction.abort();
   274     ok(false, "second abort should throw an error");
   275   }
   276   catch (ex) {
   277     ok(true, "second abort should throw an error");
   278   }
   280   // During LOADING
   281   transaction = db.transaction("foo");
   282   transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
   283   expectedAbortEventCount++;
   284   transaction.abort();
   285   try {
   286     transaction.abort();
   287     ok(false, "second abort should throw an error");
   288   }
   289   catch (ex) {
   290     ok(true, "second abort should throw an error");
   291   }
   293   // During LOADING from callback
   294   transaction = db.transaction("foo");
   295   transaction.objectStore("foo").get(1).onsuccess = grabEventAndContinueHandler;
   296   event = yield undefined;
   297   transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
   298   expectedAbortEventCount++
   299   transaction.abort();
   300   try {
   301     transaction.abort();
   302     ok(false, "second abort should throw an error");
   303   }
   304   catch (ex) {
   305     ok(true, "second abort should throw an error");
   306   }
   308   // During LOADING from error callback
   309   transaction = db.transaction("foo", "readwrite");
   310   transaction.objectStore("foo").add({}, 1).onerror = function(event) {
   311     event.preventDefault();
   313     transaction.objectStore("foo").get(1).onerror = abortErrorHandler;
   314     expectedAbortEventCount++
   316     transaction.abort();
   317     continueToNextStep();
   318   }
   319   yield undefined;
   321   // In between callbacks
   322   transaction = db.transaction("foo");
   323   function makeNewRequest() {
   324     let r = transaction.objectStore("foo").get(1);
   325     r.onsuccess = makeNewRequest;
   326     r.onerror = abortErrorHandler;
   327   }
   328   makeNewRequest();
   329   transaction.objectStore("foo").get(1).onsuccess = function(event) {
   330     executeSoon(function() {
   331       transaction.abort();
   332       expectedAbortEventCount++;
   333       continueToNextStep();
   334     });
   335   };
   336   yield undefined;
   338   // During COMMITTING
   339   transaction = db.transaction("foo", "readwrite");
   340   transaction.objectStore("foo").put({hello: "world"}, 1).onsuccess = function(event) {
   341     continueToNextStep();
   342   };
   343   yield undefined;
   344   try {
   345     transaction.abort();
   346     ok(false, "second abort should throw an error");
   347   }
   348   catch (ex) {
   349     ok(true, "second abort should throw an error");
   350   }
   351   transaction.oncomplete = grabEventAndContinueHandler;
   352   event = yield undefined;
   354   // Since the previous transaction shouldn't have caused any error events,
   355   // we know that all events should have fired by now.
   356   is(abortEventCount, expectedAbortEventCount,
   357      "All abort errors fired");
   359   // Abort both failing and succeeding requests
   360   transaction = db.transaction("foo", "readwrite");
   361   transaction.onabort = transaction.oncomplete = grabEventAndContinueHandler;
   362   transaction.objectStore("foo").add({indexKey: "key"}).onsuccess = function(event) {
   363     transaction.abort();
   364   };
   365   let request1 = transaction.objectStore("foo").add({indexKey: "key"});
   366   request1.onsuccess = grabEventAndContinueHandler;
   367   request1.onerror = grabEventAndContinueHandler;
   368   let request2 = transaction.objectStore("foo").get(1);
   369   request2.onsuccess = grabEventAndContinueHandler;
   370   request2.onerror = grabEventAndContinueHandler;
   372   event = yield undefined;
   373   is(event.type, "error", "abort() should make all requests fail");
   374   is(event.target, request1, "abort() should make all requests fail");
   375   is(event.target.error.name, "AbortError", "abort() should make all requests fail");
   376   event.preventDefault();
   378   event = yield undefined;
   379   is(event.type, "error", "abort() should make all requests fail");
   380   is(event.target, request2, "abort() should make all requests fail");
   381   is(event.target.error.name, "AbortError", "abort() should make all requests fail");
   382   event.preventDefault();
   384   event = yield undefined;
   385   is(event.type, "abort", "transaction should fail");
   386   is(event.target, transaction, "transaction should fail");
   388   ok(abortFired, "Abort should have fired!");
   390   finishTest();
   391   yield undefined;
   392 }

mercurial