Title: [120222] trunk
Revision
120222
Author
[email protected]
Date
2012-06-13 10:30:52 -0700 (Wed, 13 Jun 2012)

Log Message

IndexedDB: Add tests, an assert, and some comments around open/close/setVersion call sequencing
https://bugs.webkit.org/show_bug.cgi?id=88829

Reviewed by Tony Chang.

Source/WebCore:

Test: storage/indexeddb/three-setversion-calls.html

* Modules/indexeddb/IDBDatabaseBackendImpl.cpp:
(WebCore::IDBDatabaseBackendImpl::processPendingCalls):

LayoutTests:

* storage/indexeddb/factory-deletedatabase-interactions-expected.txt:
* storage/indexeddb/resources/factory-deletedatabase-interactions.js:
(Connection.this.open.req.onsuccess.that.handle.onversionchange):
(Connection.this.open.req.onsuccess):
(Connection.this.open):
(test3):
(test4.runSteps.):
(test4):
(test4.):
* storage/indexeddb/resources/three-setversion-calls.js: Added.
(test):
(openDBConnection):
(successHandler.return.trans.oncomplete):
(openSuccess1.deleteRequest.onsuccess):
(openSuccess1):
* storage/indexeddb/three-setversion-calls-expected.txt: Added.
* storage/indexeddb/three-setversion-calls.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (120221 => 120222)


--- trunk/LayoutTests/ChangeLog	2012-06-13 17:24:59 UTC (rev 120221)
+++ trunk/LayoutTests/ChangeLog	2012-06-13 17:30:52 UTC (rev 120222)
@@ -1,3 +1,28 @@
+2012-06-13  David Grogan  <[email protected]>
+
+        IndexedDB: Add tests, an assert, and some comments around open/close/setVersion call sequencing
+        https://bugs.webkit.org/show_bug.cgi?id=88829
+
+        Reviewed by Tony Chang.
+
+        * storage/indexeddb/factory-deletedatabase-interactions-expected.txt:
+        * storage/indexeddb/resources/factory-deletedatabase-interactions.js:
+        (Connection.this.open.req.onsuccess.that.handle.onversionchange):
+        (Connection.this.open.req.onsuccess):
+        (Connection.this.open):
+        (test3):
+        (test4.runSteps.):
+        (test4):
+        (test4.):
+        * storage/indexeddb/resources/three-setversion-calls.js: Added.
+        (test):
+        (openDBConnection):
+        (successHandler.return.trans.oncomplete):
+        (openSuccess1.deleteRequest.onsuccess):
+        (openSuccess1):
+        * storage/indexeddb/three-setversion-calls-expected.txt: Added.
+        * storage/indexeddb/three-setversion-calls.html: Added.
+
 2012-06-13  Levi Weintraub  <[email protected]>
 
         Unreviewed Chromium test expectation update after r119893.

Modified: trunk/LayoutTests/storage/indexeddb/factory-deletedatabase-interactions-expected.txt (120221 => 120222)


--- trunk/LayoutTests/storage/indexeddb/factory-deletedatabase-interactions-expected.txt	2012-06-13 17:24:59 UTC (rev 120221)
+++ trunk/LayoutTests/storage/indexeddb/factory-deletedatabase-interactions-expected.txt	2012-06-13 17:30:52 UTC (rev 120222)
@@ -12,6 +12,7 @@
 'h.open.onsuccess'
 'deleteDatabase()'
 'h.onversionchange'
+    in versionchange, old = "" new = ""
     h closing, but not immediately
 'deleteDatabase().onblocked'
 'h.close'
@@ -24,6 +25,7 @@
 'h.open.onsuccess'
 'deleteDatabase()'
 'h.onversionchange'
+    in versionchange, old = "" new = ""
     h closing immediately
 'h.close'
 'deleteDatabase().onblocked'
@@ -40,11 +42,36 @@
 'h.setVersion.onsuccess'
 'h.setVersion.transaction-complete'
 'h.onversionchange'
+    in versionchange, old = "1" new = ""
     h closing, but not immediately
 'deleteDatabase().onblocked'
 'h.close'
 'deleteDatabase().onsuccess'
 PASS self.steps.toString() is "h.open,h.open.onsuccess,h.setVersion,deleteDatabase(),h.setVersion.onsuccess,h.setVersion.transaction-complete,h.onversionchange,deleteDatabase().onblocked,h.close,deleteDatabase().onsuccess"
+
+TEST: Correct order when there are pending setVersion, delete and open calls.
+self.dbname = 'test4'; self.ver = 1; self.steps = []
+'h.open'
+'h.open.onsuccess'
+'h2.open'
+'h2.open.onsuccess'
+'h.setVersion'
+'deleteDatabase()'
+'h2.onversionchange'
+    in versionchange, old = "" new = "1"
+'h.setVersion.onblocked'
+'h3.open'
+'h2.close'
+'h.setVersion.onsuccess'
+'h.setVersion.transaction-complete'
+'h.onversionchange'
+    in versionchange, old = "1" new = ""
+    h closing, but not immediately
+'deleteDatabase().onblocked'
+'h.close'
+'deleteDatabase().onsuccess'
+'h3.open.onsuccess'
+PASS self.steps.toString() is "h.open,h.open.onsuccess,h2.open,h2.open.onsuccess,h.setVersion,deleteDatabase(),h2.onversionchange,h.setVersion.onblocked,h3.open,h2.close,h.setVersion.onsuccess,h.setVersion.transaction-complete,h.onversionchange,deleteDatabase().onblocked,h.close,deleteDatabase().onsuccess,h3.open.onsuccess"
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/storage/indexeddb/resources/factory-deletedatabase-interactions.js (120221 => 120222)


--- trunk/LayoutTests/storage/indexeddb/resources/factory-deletedatabase-interactions.js	2012-06-13 17:24:59 UTC (rev 120221)
+++ trunk/LayoutTests/storage/indexeddb/resources/factory-deletedatabase-interactions.js	2012-06-13 17:30:52 UTC (rev 120222)
@@ -17,6 +17,7 @@
             self.steps.push(evalAndLog("'" + id + ".open.onsuccess'"));
             that.handle._onversionchange_ = function(e) {
                 self.steps.push(evalAndLog("'" + id + ".onversionchange'"));
+                debug("    in versionchange, old = " + JSON.stringify(e.target.version) + " new = " + JSON.stringify(e.version));
                 if (opts && opts.onversion) { opts.onversion.call(that); }
             };
             if (opts && opts.onsuccess) { opts.onsuccess.call(that); }
@@ -179,8 +180,55 @@
                                "h.close",
                                "deleteDatabase().onsuccess"
                                ].toString());
+        test4();
+    }
+}
+
+function test4() {
+    debug("");
+    debug("TEST: Correct order when there are pending setVersion, delete and open calls.");
+    evalAndLog("self.dbname = 'test4'; self.ver = 1; self.steps = []");
+    var h = new Connection("h");
+    var h2 = new Connection("h2");
+    var h3 = new Connection("h3");
+    runSteps([function(doNext) { h.open({onsuccess: doNext,
+                                         onversion: function() {
+                                             debug("    h closing, but not immediately");
+                                             setTimeout(function() { h.close(); }, 0);
+                                         }});
+                               },
+              function(doNext) { h2.open({onsuccess: doNext}); },
+              function(doNext) { h.setVersion({onblocked: function() {
+                                               h3.open({onsuccess: finishTest});
+                                               h2.close();
+                                           }});
+                                 doNext();
+                               },
+              function(doNext) { deleteDatabase("", self.dbname); },
+              ]);
+
+    function finishTest() {
+        shouldBeEqualToString("self.steps.toString()",
+                              ["h.open",
+                               "h.open.onsuccess",
+                               "h2.open",
+                               "h2.open.onsuccess",
+                               "h.setVersion",
+                               "deleteDatabase()",
+                               "h2.onversionchange",
+                               "h.setVersion.onblocked",
+                               "h3.open",
+                               "h2.close",
+                               "h.setVersion.onsuccess",
+                               "h.setVersion.transaction-complete",
+                               "h.onversionchange",
+                               "deleteDatabase().onblocked",
+                               "h.close",
+                               "deleteDatabase().onsuccess",
+                               "h3.open.onsuccess"
+                              ].toString());
         finishJSTest();
     }
 }
 
-test();
\ No newline at end of file
+test();

Added: trunk/LayoutTests/storage/indexeddb/resources/three-setversion-calls.js (0 => 120222)


--- trunk/LayoutTests/storage/indexeddb/resources/three-setversion-calls.js	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/resources/three-setversion-calls.js	2012-06-13 17:30:52 UTC (rev 120222)
@@ -0,0 +1,60 @@
+if (this.importScripts) {
+    importScripts('../../../fast/js/resources/js-test-pre.js');
+    importScripts('shared.js');
+}
+
+description("Three setVersion calls are queued correctly - exercises an otherwise-untested code path");
+
+function test()
+{
+    removeVendorPrefixes();
+    openDBConnection();
+}
+
+function openDBConnection()
+{
+    request = evalAndLog("indexedDB.open('three-setversion-calls')");
+    request._onsuccess_ = openSuccess1;
+    request._onerror_ = unexpectedErrorCallback;
+}
+
+function successHandler(id)
+{
+  return function(e) {
+    trans = e.target.result;
+    debug("setVersion " + id);
+    trans._onerror_ = unexpectedErrorCallback;
+    trans._onabort_ = unexpectedAbortCallback;
+    trans._oncomplete_ = function(evt) {
+      debug("setVersion " + id + " complete");
+      if (id == kNumVersionCalls - 1) {
+        evalAndLog("finishedAllSetVersions = true");
+        connection.close();
+      }
+    }
+  }
+}
+
+finishedAllSetVersions = false;
+kNumVersionCalls = 3;
+function openSuccess1(e)
+{
+    connection = e.target.result;
+    for (var i = 0; i < kNumVersionCalls; i++) {
+      vcRequest = evalAndLog('connection.setVersion("version ' + i + '")');
+      vcRequest._onblocked_ = unexpectedBlockedCallback;
+      vcRequest._onerror_ = unexpectedErrorCallback;
+      vcRequest._onsuccess_ = successHandler(i);
+      if (!i) {
+        deleteRequest = evalAndLog('indexedDB.deleteDatabase("three-setversion-calls")');
+        deleteRequest._onerror_ = unexpectedErrorCallback;
+        deleteRequest._onsuccess_ = function() {
+          debug("Successfully deleted database");
+          shouldBeTrue("finishedAllSetVersions");
+          finishJSTest();
+        };
+      }
+    }
+}
+
+test();

Added: trunk/LayoutTests/storage/indexeddb/three-setversion-calls-expected.txt (0 => 120222)


--- trunk/LayoutTests/storage/indexeddb/three-setversion-calls-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/three-setversion-calls-expected.txt	2012-06-13 17:30:52 UTC (rev 120222)
@@ -0,0 +1,25 @@
+Three setVersion calls are queued correctly - exercises an otherwise-untested code path
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.open('three-setversion-calls')
+connection.setVersion("version 0")
+indexedDB.deleteDatabase("three-setversion-calls")
+connection.setVersion("version 1")
+connection.setVersion("version 2")
+setVersion 0
+setVersion 0 complete
+setVersion 1
+setVersion 1 complete
+setVersion 2
+setVersion 2 complete
+finishedAllSetVersions = true
+Successfully deleted database
+PASS finishedAllSetVersions is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/storage/indexeddb/three-setversion-calls.html (0 => 120222)


--- trunk/LayoutTests/storage/indexeddb/three-setversion-calls.html	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/three-setversion-calls.html	2012-06-13 17:30:52 UTC (rev 120222)
@@ -0,0 +1,10 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (120221 => 120222)


--- trunk/Source/WebCore/ChangeLog	2012-06-13 17:24:59 UTC (rev 120221)
+++ trunk/Source/WebCore/ChangeLog	2012-06-13 17:30:52 UTC (rev 120222)
@@ -1,3 +1,15 @@
+2012-06-13  David Grogan  <[email protected]>
+
+        IndexedDB: Add tests, an assert, and some comments around open/close/setVersion call sequencing
+        https://bugs.webkit.org/show_bug.cgi?id=88829
+
+        Reviewed by Tony Chang.
+
+        Test: storage/indexeddb/three-setversion-calls.html
+
+        * Modules/indexeddb/IDBDatabaseBackendImpl.cpp:
+        (WebCore::IDBDatabaseBackendImpl::processPendingCalls):
+
 2012-06-09  Vsevolod Vlasov  <[email protected]>
 
         Web Inspector: Errors when pending console messages are attached to _javascript_SourceFrame.

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp (120221 => 120222)


--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp	2012-06-13 17:24:59 UTC (rev 120221)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp	2012-06-13 17:30:52 UTC (rev 120222)
@@ -280,6 +280,8 @@
 
 void IDBDatabaseBackendImpl::processPendingCalls()
 {
+    ASSERT(m_databaseCallbacksSet.size() <= 1);
+
     // Pending calls may be requeued or aborted
     Deque<RefPtr<PendingSetVersionCall> > pendingSetVersionCalls;
     m_pendingSetVersionCalls.swap(pendingSetVersionCalls);
@@ -290,6 +292,17 @@
         ASSERT(!ec);
     }
 
+    // If there were any pending set version calls, we better have started one.
+    ASSERT(m_pendingSetVersionCalls.isEmpty() || m_runningVersionChangeTransaction);
+
+    // m_pendingSetVersionCalls is non-empty in two cases:
+    // 1) When two versionchange transactions are requested while another
+    //    version change transaction is running.
+    // 2) When three versionchange transactions are requested in a row, before
+    //    any of their event handlers are run.
+    // Note that this check is only an optimization to reduce queue-churn and
+    // not necessary for correctness; deleteDatabase and openConnection will
+    // requeue their calls if this condition is true.
     if (m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty())
         return;
 
@@ -301,13 +314,19 @@
         deleteDatabase(pendingDeleteCall->callbacks());
     }
 
+    // This check is also not really needed, openConnection would just requeue its calls.
     if (m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty() || !m_pendingDeleteCalls.isEmpty())
         return;
 
-    while (!m_pendingOpenCalls.isEmpty()) {
-        RefPtr<PendingOpenCall> pendingOpenCall = m_pendingOpenCalls.takeFirst();
+    // Given the check above, it appears that calls cannot be requeued by
+    // openConnection, but use a different queue for iteration to be safe.
+    Deque<RefPtr<PendingOpenCall> > pendingOpenCalls;
+    m_pendingOpenCalls.swap(pendingOpenCalls);
+    while (!pendingOpenCalls.isEmpty()) {
+        RefPtr<PendingOpenCall> pendingOpenCall = pendingOpenCalls.takeFirst();
         openConnection(pendingOpenCall->callbacks());
     }
+    ASSERT(m_pendingOpenCalls.isEmpty());
 }
 
 PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(DOMStringList* objectStoreNames, unsigned short mode, ExceptionCode& ec)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to