IndexedDB: test conversion batch 3
authordgrogan@chromium.org <dgrogan@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 14 Nov 2012 21:52:49 +0000 (21:52 +0000)
committerdgrogan@chromium.org <dgrogan@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 14 Nov 2012 21:52:49 +0000 (21:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=102168

Reviewed by Tony Chang.

These were all pretty straightforward. metadata.html could include
some additional tests that check the metadata after a versionchange
transaction aborts, but I think that's tested in one of the intversion
tests.

* storage/indexeddb/exceptions-expected.txt:
* storage/indexeddb/factory-deletedatabase-expected.txt:
* storage/indexeddb/index-duplicate-keypaths-expected.txt:
* storage/indexeddb/index-multientry-expected.txt:
* storage/indexeddb/index-population-expected.txt:
* storage/indexeddb/metadata-expected.txt:
* storage/indexeddb/resources/database-basics.js:
  Fix failure when run as a chromium browser test.

* storage/indexeddb/resources/exceptions.js:
  Moved some asserts from running before the database is opened to
  afterward but they appear to be testing the same thing.
(transactionComplete):
  close can't proceed until the transactions are complete, something
  setVersion didn't have to deal with.

* storage/indexeddb/resources/factory-deletedatabase.js:
  The conditions under which deleteDatabase is called in this test is
  _slightly_ different. Previously, deleteDatabase was called from
  inside a versionchange transaction, causing the original connection
  to receive a versionchange event. With upgradeneeded we have to close
  the original connection before entering a versionchange transaction,
  so the second connection is now what closes in response to the
  deleteDatabase's versionchange event.

* storage/indexeddb/resources/index-duplicate-keypaths.js:
(testCollideAutoIncrementSetup):
(testCollideAutoIncrement):
* storage/indexeddb/resources/index-multientry.js:
(prepareDatabase):
(createIndexOnStoreWithData):
* storage/indexeddb/resources/index-population.js:
(prepareDatabase.request.onsuccess):
(prepareDatabase):
(doSetVersion2):
(setVersion2):
(setVersion2Abort):
* storage/indexeddb/resources/metadata.js:
(prepareDatabase):
(snapshotConnection1):
(secondOpen.request.onupgradeneeded):
(secondOpen.request.onsuccess):
(secondOpen):
(thirdOpen.request.onupgradeneeded):
(thirdOpen.request.onerror):
(thirdOpen):
(fourthOpen.request.onupgradeneeded):
(fourthOpen.request.onsuccess):
(fourthOpen):
(checkState):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@134661 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
LayoutTests/ChangeLog
LayoutTests/storage/indexeddb/exceptions-expected.txt
LayoutTests/storage/indexeddb/factory-deletedatabase-expected.txt
LayoutTests/storage/indexeddb/index-duplicate-keypaths-expected.txt
LayoutTests/storage/indexeddb/index-multientry-expected.txt
LayoutTests/storage/indexeddb/index-population-expected.txt
LayoutTests/storage/indexeddb/metadata-expected.txt
LayoutTests/storage/indexeddb/resources/database-basics.js
LayoutTests/storage/indexeddb/resources/exceptions.js
LayoutTests/storage/indexeddb/resources/factory-deletedatabase.js
LayoutTests/storage/indexeddb/resources/index-duplicate-keypaths.js
LayoutTests/storage/indexeddb/resources/index-multientry.js
LayoutTests/storage/indexeddb/resources/index-population.js
LayoutTests/storage/indexeddb/resources/metadata.js

index 15c275d..5d9b5dd 100644 (file)
@@ -1,3 +1,66 @@
+2012-11-14  David Grogan  <dgrogan@chromium.org>
+
+        IndexedDB: test conversion batch 3
+        https://bugs.webkit.org/show_bug.cgi?id=102168
+
+        Reviewed by Tony Chang.
+
+        These were all pretty straightforward. metadata.html could include
+        some additional tests that check the metadata after a versionchange
+        transaction aborts, but I think that's tested in one of the intversion
+        tests.
+
+        * storage/indexeddb/exceptions-expected.txt:
+        * storage/indexeddb/factory-deletedatabase-expected.txt:
+        * storage/indexeddb/index-duplicate-keypaths-expected.txt:
+        * storage/indexeddb/index-multientry-expected.txt:
+        * storage/indexeddb/index-population-expected.txt:
+        * storage/indexeddb/metadata-expected.txt:
+        * storage/indexeddb/resources/database-basics.js:
+          Fix failure when run as a chromium browser test.
+
+        * storage/indexeddb/resources/exceptions.js:
+          Moved some asserts from running before the database is opened to
+          afterward but they appear to be testing the same thing.
+        (transactionComplete):
+          close can't proceed until the transactions are complete, something
+          setVersion didn't have to deal with.
+
+        * storage/indexeddb/resources/factory-deletedatabase.js:
+          The conditions under which deleteDatabase is called in this test is
+          _slightly_ different. Previously, deleteDatabase was called from
+          inside a versionchange transaction, causing the original connection
+          to receive a versionchange event. With upgradeneeded we have to close
+          the original connection before entering a versionchange transaction,
+          so the second connection is now what closes in response to the
+          deleteDatabase's versionchange event.
+
+        * storage/indexeddb/resources/index-duplicate-keypaths.js:
+        (testCollideAutoIncrementSetup):
+        (testCollideAutoIncrement):
+        * storage/indexeddb/resources/index-multientry.js:
+        (prepareDatabase):
+        (createIndexOnStoreWithData):
+        * storage/indexeddb/resources/index-population.js:
+        (prepareDatabase.request.onsuccess):
+        (prepareDatabase):
+        (doSetVersion2):
+        (setVersion2):
+        (setVersion2Abort):
+        * storage/indexeddb/resources/metadata.js:
+        (prepareDatabase):
+        (snapshotConnection1):
+        (secondOpen.request.onupgradeneeded):
+        (secondOpen.request.onsuccess):
+        (secondOpen):
+        (thirdOpen.request.onupgradeneeded):
+        (thirdOpen.request.onerror):
+        (thirdOpen):
+        (fourthOpen.request.onupgradeneeded):
+        (fourthOpen.request.onsuccess):
+        (fourthOpen):
+        (checkState):
+
 2012-11-14  Dimitri Glazkov  <dglazkov@chromium.org>
 
         [Chromium] Updating baselines after r134631.
index f1c3be9..f09a05e 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: The setVersion() method is non-standard and will be removed. Use the "upgradeneeded" event instead.
 Test that expected exceptions are thrown per IndexedDB spec.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
@@ -6,8 +5,24 @@ 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.deleteDatabase('exceptions')
-request = indexedDB.open('exceptions')
+dbname = "exceptions.html"
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+store = db.createObjectStore('store')
+index = store.createIndex('index', 'id')
+store.put({id: 'a'}, 1)
+store.put({id: 'b'}, 2)
+store.put({id: 'c'}, 3)
+store.put({id: 'd'}, 4)
+store.put({id: 'e'}, 5)
+store.put({id: 'f'}, 6)
+store.put({id: 'g'}, 7)
+store.put({id: 'h'}, 8)
+store.put({id: 'i'}, 9)
+store.put({id: 'j'}, 10)
+otherStore = db.createObjectStore('otherStore')
+inlineKeyStore = db.createObjectStore('inlineKeyStore', {keyPath: 'id'})
+request = inlineKeyStore.put({id: 0})
 PASS request.readyState is "pending"
 
 3.2.1 The IDBRequest Interface
@@ -34,27 +49,10 @@ Expecting exception from indexedDB.cmp(null, 0)
 PASS Exception was thrown.
 PASS code is IDBDatabaseException.DATA_ERR
 PASS ename is 'DataError'
-
-db = request.result
-db.setVersion('1')
-store = db.createObjectStore('store')
-index = store.createIndex('index', 'id')
-store.put({id: 'a'}, 1)
-store.put({id: 'b'}, 2)
-store.put({id: 'c'}, 3)
-store.put({id: 'd'}, 4)
-store.put({id: 'e'}, 5)
-store.put({id: 'f'}, 6)
-store.put({id: 'g'}, 7)
-store.put({id: 'h'}, 8)
-store.put({id: 'i'}, 9)
-store.put({id: 'j'}, 10)
-otherStore = db.createObjectStore('otherStore')
-inlineKeyStore = db.createObjectStore('inlineKeyStore', {keyPath: 'id'})
-inlineKeyStore.put({id: 0})
+db.close()
 
 3.2.4 Database
-db.setVersion('2')
+indexedDB.open(dbname, 2)
 
 IDBDatabase.createObjectStore()
 If an objectStore with the same name already exists, the implementation must throw a DOMException of type ConstraintError.
@@ -127,12 +125,12 @@ request = storeFromInactiveTransaction.openCursor()
 cursorFromInactiveTransaction = request.result
 
 3.2.5 Object Store
-storeFromReadOnlyTransaction = db.transaction('store', 'readonly').objectStore('store')
-store = db.transaction('store', 'readwrite').objectStore('store')
+ro_transaction = db.transaction('store', 'readonly')
+storeFromReadOnlyTransaction = ro_transaction.objectStore('store')
+rw_transaction = db.transaction('store', 'readwrite')
+store = rw_transaction.objectStore('store')
 
 IDBObjectStore.add()
-storeFromReadOnlyTransaction = db.transaction('store', 'readonly').objectStore('store')
-store = db.transaction('store', 'readwrite').objectStore('store')
 This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly".
 Expecting exception from storeFromReadOnlyTransaction.add(0, 0)
 PASS Exception was thrown.
@@ -244,7 +242,16 @@ The data being stored could not be cloned by the internal structured cloning alg
 Expecting exception from store.put(self, 0)
 PASS Exception was thrown.
 PASS code is DOMException.DATA_CLONE_ERR
-db.setVersion('3')
+db.close()
+ro_transaction.oncomplete = transactionComplete
+rw_transaction.oncomplete = transactionComplete
+
+transactionComplete():
+First transaction completed
+
+transactionComplete():
+request = indexedDB.open(dbname, 3)
+request.onupgradeneeded = onUpgradeNeeded3
 
 IDBObjectStore.createIndex()
 If an index with the same name already exists, the implementation must throw a DOMException of type ConstraintError. 
index c876685..f32d809 100644 (file)
@@ -1,5 +1,3 @@
-CONSOLE MESSAGE: The setVersion() method is non-standard and will be removed. Use the "upgradeneeded" event instead.
-CONSOLE MESSAGE: The setVersion() method is non-standard and will be removed. Use the "upgradeneeded" event instead.
 Test IndexedDB's webkitIndexedDB.deleteDatabase().
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
@@ -7,11 +5,9 @@ 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('database-to-delete')
-db = event.target.result
-db.setVersion('new version')
-trans = event.target.result
-PASS trans is non-null.
+dbname = "factory-deletedatabase.html"
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
 store = db.createObjectStore('storeName', null)
 store.createIndex('indexName', '')
 PASS store.indexNames.contains('indexName') is true
@@ -20,12 +16,14 @@ db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
 store.get('key')
 PASS event.target.result is "value"
-db.setVersion('new version')
-request = indexedDB.deleteDatabase('database-to-delete')
+db.close()
+indexedDB.open(dbname, 2)
+db = event.target.result
+request = indexedDB.deleteDatabase(dbname)
+db.close()
 PASS request.result is undefined.
-indexedDB.open('database-to-delete')
+indexedDB.open(dbname, 3)
 db = event.target.result
-db.setVersion('new version')
 PASS db.objectStoreNames.length is 0
 PASS successfullyParsed is true
 
index 0244831..ef6b077 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: The setVersion() method is non-standard and will be removed. Use the "upgradeneeded" event instead.
 Test the use of identical keypaths between objectstores and indexes
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
@@ -16,7 +15,8 @@ objectStore.get(10)
 index.get(10)
 PASS JSON.stringify(result) is "{\"foo\":10}"
 PASS JSON.stringify(result) is "{\"foo\":10}"
-db.setVersion('2')
+db.close()
+request = indexedDB.open(dbname, 2)
 Deleted all object stores.
 store = db.createObjectStore('collideWithAutoIncrement', {keyPath: 'foo', autoIncrement: true})
 index = store.createIndex('foo', 'foo')
index 52a9e75..f1d6977 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: The setVersion() method is non-standard and will be removed. Use the "upgradeneeded" event instead.
 Test features of IndexedDB's multiEntry indices.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
@@ -6,14 +5,9 @@ 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('index-multiEntry')
-db = event.target.result
-db.setVersion('1')
-
-Creating empty stores and indexes
-trans = event.target.result
-PASS trans is non-null.
-Deleted all object stores.
+dbname = "index-multientry.html"
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
 store = db.createObjectStore('store')
 store.createIndex('index', 'x', {multiEntry: true})
 store2 = db.createObjectStore('store-unique')
@@ -102,9 +96,10 @@ Request failed, as expected (ConstraintError)
 Transaction aborted as expected
 
 Create an index on a populated store
-db.setVersion('2')
-trans = event.target.result
-PASS trans is non-null.
+db.close()
+indexedDB.open(dbname, 2)
+db = event.target.result
+trans = event.target.transaction
 store = trans.objectStore('store')
 store.createIndex('index-new', 'x', {multiEntry: true})
 
index 6b035b4..5761a27 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: The setVersion() method is non-standard and will be removed. Use the "upgradeneeded" event instead.
 Test IndexedDB index population.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
@@ -6,15 +5,10 @@ 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.deleteDatabase('index-population')
-indexedDB.open('index-population')
-
-doSetVersion1():
-db = event.target.result
-request = db.setVersion('version 1')
-
-setVersion1():
-transaction = request.result
+dbname = "index-population.html"
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+transaction = event.target.transaction
 store = db.createObjectStore('store1')
 store.put({data: 'a', indexKey: 10}, 1)
 store.put({data: 'b', indexKey: 20}, 2)
@@ -27,10 +21,11 @@ request = index.count(IDBKeyRange.bound(-Infinity, Infinity))
 PASS request.result is 4
 
 doSetVersion2():
-request = db.setVersion('version 2')
+db.close()
+request = indexedDB.open(dbname, 2)
 
 setVersion2():
-transaction = request.result
+transaction = request.transaction
 store = db.createObjectStore('store2')
 store.put({data: 'a', indexKey: 10}, 1)
 store.put({data: 'b', indexKey: 20}, 2)
index 554c062..0763fab 100644 (file)
@@ -1,7 +1,3 @@
-CONSOLE MESSAGE: The setVersion() method is non-standard and will be removed. Use the "upgradeneeded" event instead.
-CONSOLE MESSAGE: The setVersion() method is non-standard and will be removed. Use the "upgradeneeded" event instead.
-CONSOLE MESSAGE: The setVersion() method is non-standard and will be removed. Use the "upgradeneeded" event instead.
-CONSOLE MESSAGE: The setVersion() method is non-standard and will be removed. Use the "upgradeneeded" event instead.
 Test IndexedDB database metadata mutation/snapshotting
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
@@ -9,45 +5,38 @@ 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;
 
-dbname = self.location.pathname
-request = indexedDB.deleteDatabase(dbname)
-
-firstOpen():
-request = indexedDB.open(dbname)
-connection1 = request.result
-request = connection1.setVersion('1')
-trans = request.result
+dbname = "metadata.html"
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
 connection1store1 = connection1.createObjectStore('store1')
 connection1store1.createIndex('index1', 'path')
-PASS connection1.version is "1"
+PASS connection1.version is 1
 PASS connection1.objectStoreNames.length is 1
 PASS connection1store1.indexNames.length is 1
 Connection's properties should be snapshotted on close
 connection1.close()
 
 secondOpen():
-request = indexedDB.open(dbname)
+request = indexedDB.open(dbname, 2)
 connection2 = request.result
-request = connection2.setVersion('2')
-trans = request.result
+trans = request.transaction
 connection2.createObjectStore('store2')
 connection2store1 = trans.objectStore('store1')
 connection2store1.createIndex('index2', 'path')
-PASS connection2.version is "2"
+PASS connection2.version is 2
 PASS connection2.objectStoreNames.length is 2
 PASS connection2store1.indexNames.length is 2
 Connection's properties should be snapshotted on close
 connection2.close()
 
 thirdOpen():
-request = indexedDB.open(dbname)
+request = indexedDB.open(dbname, 3)
 connection3 = request.result
-request = connection3.setVersion('3')
-trans = request.result
+trans = request.transaction
 connection3.createObjectStore('store3')
 connection3store1 = trans.objectStore('store1')
 connection3store1.createIndex('index3', 'path')
-PASS connection3.version is "3"
+PASS connection3.version is 3
 PASS connection3.objectStoreNames.length is 3
 PASS connection3store1.indexNames.length is 3
 Connection's properties should be reverted on abort
@@ -56,33 +45,32 @@ Connection's properties should be snapshotted on close
 connection3.close()
 
 fourthOpen():
-request = indexedDB.open(dbname)
+request = indexedDB.open(dbname, 4)
 connection4 = request.result
-request = connection4.setVersion('4')
-trans = request.result
+trans = request.transaction
 connection4.createObjectStore('store4')
 connection4store1 = trans.objectStore('store1')
 connection4store1.createIndex('index4', 'path')
-PASS connection4.version is "4"
+PASS connection4.version is 4
 PASS connection4.objectStoreNames.length is 3
 PASS connection4store1.indexNames.length is 3
 Connection's properties should be snapshotted on close
 connection4.close()
 
 checkState():
-PASS connection1.version is "1"
+PASS connection1.version is 1
 PASS connection1.objectStoreNames.length is 1
 PASS connection1store1.indexNames.length is 1
 
-PASS connection2.version is "2"
+PASS connection2.version is 2
 PASS connection2.objectStoreNames.length is 2
 PASS connection2store1.indexNames.length is 2
 
-PASS connection3.version is "2"
+PASS connection3.version is 2
 PASS connection3.objectStoreNames.length is 2
 PASS connection3store1.indexNames.length is 2
 
-PASS connection4.version is "4"
+PASS connection4.version is 4
 PASS connection4.objectStoreNames.length is 3
 PASS connection4store1.indexNames.length is 3
 
index ccb575a..1721c87 100644 (file)
@@ -41,7 +41,7 @@ function testSetVersionAbort()
     evalAndLog("request = indexedDB.open(dbname, 2)");
     request.onupgradeneeded = createAnotherObjectStore;
     request.onblocked = unexpectedBlockedCallback;
-    request.onerror = unexpectedErrorCallback;
+    request.onsuccess = unexpectedSuccessCallback;
 }
 
 function createAnotherObjectStore()
index e425384..25b5ec9 100644 (file)
@@ -2,83 +2,68 @@ if (this.importScripts) {
     importScripts('../../../fast/js/resources/js-test-pre.js');
     importScripts('shared.js');
 }
+
 description("Test that expected exceptions are thrown per IndexedDB spec.");
 
-function test()
+indexedDBTest(prepareDatabase, testDatabase);
+function prepareDatabase()
 {
-    removeVendorPrefixes();
-    request = evalAndLog("indexedDB.deleteDatabase('exceptions')");
-    request.onerror = unexpectedErrorCallback;
-    request.onblocked = unexpectedBlockedCallback;
-    request.onsuccess = function() {
-        evalAndLog("request = indexedDB.open('exceptions')");
-        shouldBeEqualToString("request.readyState", "pending");
+    db = event.target.result;
+
+    evalAndLog("store = db.createObjectStore('store')");
+    evalAndLog("index = store.createIndex('index', 'id')");
+    evalAndLog("store.put({id: 'a'}, 1)");
+    evalAndLog("store.put({id: 'b'}, 2)");
+    evalAndLog("store.put({id: 'c'}, 3)");
+    evalAndLog("store.put({id: 'd'}, 4)");
+    evalAndLog("store.put({id: 'e'}, 5)");
+    evalAndLog("store.put({id: 'f'}, 6)");
+    evalAndLog("store.put({id: 'g'}, 7)");
+    evalAndLog("store.put({id: 'h'}, 8)");
+    evalAndLog("store.put({id: 'i'}, 9)");
+    evalAndLog("store.put({id: 'j'}, 10)");
+    evalAndLog("otherStore = db.createObjectStore('otherStore')");
+    evalAndLog("inlineKeyStore = db.createObjectStore('inlineKeyStore', {keyPath: 'id'})");
+
+    evalAndLog("request = inlineKeyStore.put({id: 0})");
+    shouldBeEqualToString("request.readyState", "pending");
 
-        debug("");
-        debug("3.2.1 The IDBRequest Interface");
-
-        debug("");
-        debug("IDBRequest.error");
-        debug("When the done flag is false, getting this property must throw a DOMException of type InvalidStateError.");
-        evalAndExpectException("request.error", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
+    debug("");
+    debug("3.2.1 The IDBRequest Interface");
 
-        debug("");
-        debug("IDBRequest.result");
-        debug("When the done flag is false, getting this property must throw a DOMException of type InvalidStateError.");
-        evalAndExpectException("request.result", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
+    debug("");
+    debug("IDBRequest.error");
+    debug("When the done flag is false, getting this property must throw a DOMException of type InvalidStateError.");
+    evalAndExpectException("request.error", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
 
-        debug("");
-        debug("3.2.3 Opening a database");
+    debug("");
+    debug("IDBRequest.result");
+    debug("When the done flag is false, getting this property must throw a DOMException of type InvalidStateError.");
+    evalAndExpectException("request.result", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
 
-        debug("");
-        debug("IDBFactory.cmp()");
-        debug("One of the supplied keys was not a valid key.");
-        evalAndExpectException("indexedDB.cmp(null, 0)", "IDBDatabaseException.DATA_ERR", "'DataError'");
+    debug("");
+    debug("3.2.3 Opening a database");
 
-        request.onerror = unexpectedErrorCallback;
-        request.onsuccess = function() {
-            debug("");
-            evalAndLog("db = request.result");
-
-            request = evalAndLog("db.setVersion('1')");
-            request.onerror = unexpectedErrorCallback;
-            request.onblocked = unexpectedBlockedCallback;
-            request.onsuccess = function() {
-                var trans = request.result;
-                trans.onabort = unexpectedAbortCallback;
-
-                evalAndLog("store = db.createObjectStore('store')");
-                evalAndLog("index = store.createIndex('index', 'id')");
-                evalAndLog("store.put({id: 'a'}, 1)");
-                evalAndLog("store.put({id: 'b'}, 2)");
-                evalAndLog("store.put({id: 'c'}, 3)");
-                evalAndLog("store.put({id: 'd'}, 4)");
-                evalAndLog("store.put({id: 'e'}, 5)");
-                evalAndLog("store.put({id: 'f'}, 6)");
-                evalAndLog("store.put({id: 'g'}, 7)");
-                evalAndLog("store.put({id: 'h'}, 8)");
-                evalAndLog("store.put({id: 'i'}, 9)");
-                evalAndLog("store.put({id: 'j'}, 10)");
-                evalAndLog("otherStore = db.createObjectStore('otherStore')");
-                evalAndLog("inlineKeyStore = db.createObjectStore('inlineKeyStore', {keyPath: 'id'})");
-                evalAndLog("inlineKeyStore.put({id: 0})");
-
-                trans.oncomplete = testDatabase;
-            };
-        };
-    };
+    debug("");
+    debug("IDBFactory.cmp()");
+    debug("One of the supplied keys was not a valid key.");
+    evalAndExpectException("indexedDB.cmp(null, 0)", "IDBDatabaseException.DATA_ERR", "'DataError'");
 }
 
 function testDatabase()
 {
+    evalAndLog("db.close()");
+
     debug("");
     debug("3.2.4 Database");
 
-    request = evalAndLog("db.setVersion('2')");
+    request = evalAndLog("indexedDB.open(dbname, 2)");
     request.onerror = unexpectedErrorCallback;
     request.onblocked = unexpectedBlockedCallback;
-    request.onsuccess = function() {
-        var trans = request.result;
+    request.onsuccess = checkTransactionAndObjectStoreExceptions;
+    request.onupgradeneeded = function() {
+        db = request.result;
+        var trans = request.transaction;
         trans.onabort = unexpectedAbortCallback;
 
         debug("");
@@ -100,30 +85,31 @@ function testDatabase()
         debug("IDBDatabase.transaction()");
         debug('If this method is called on IDBDatabase object for which a "versionchange" transaction is still running, a InvalidStateError exception must be thrown.');
         evalAndExpectException("db.transaction('store')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
-
-        trans.oncomplete = function() {
-            debug("One of the names provided in the storeNames argument doesn't exist in this database.");
-            evalAndExpectException("db.transaction('no-such-store')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");
-            debug("The value for the mode parameter is invalid.");
-            evalAndExpectExceptionClass("db.transaction('store', 'invalid-mode')", "TypeError");
-            debug("The function was called with an empty list of store names");
-            evalAndExpectException("db.transaction([])", "DOMException.INVALID_ACCESS_ERR", "'InvalidAccessError'");
-
-            debug("");
-            debug("One more IDBDatabase.createObjectStore() test:");
-            debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
-            evalAndExpectException("db.createObjectStore('fail')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
-
-            debug("");
-            debug("One more IDBDatabase.deleteObjectStore() test:");
-            debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
-            evalAndExpectException("db.deleteObjectStore('fail')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
-
-            prepareStoreAndIndex();
-        };
     };
 }
 
+function checkTransactionAndObjectStoreExceptions()
+{
+    debug("One of the names provided in the storeNames argument doesn't exist in this database.");
+    evalAndExpectException("db.transaction('no-such-store')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");
+    debug("The value for the mode parameter is invalid.");
+    evalAndExpectExceptionClass("db.transaction('store', 'invalid-mode')", "TypeError");
+    debug("The function was called with an empty list of store names");
+    evalAndExpectException("db.transaction([])", "DOMException.INVALID_ACCESS_ERR", "'InvalidAccessError'");
+
+    debug("");
+    debug("One more IDBDatabase.createObjectStore() test:");
+    debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
+    evalAndExpectException("db.createObjectStore('fail')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
+
+    debug("");
+    debug("One more IDBDatabase.deleteObjectStore() test:");
+    debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
+    evalAndExpectException("db.deleteObjectStore('fail')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
+
+    prepareStoreAndIndex();
+}
+
 function prepareStoreAndIndex()
 {
     debug("");
@@ -144,13 +130,13 @@ function testObjectStore()
 {
     debug("");
     debug("3.2.5 Object Store");
-    evalAndLog("storeFromReadOnlyTransaction = db.transaction('store', 'readonly').objectStore('store')");
-    evalAndLog("store = db.transaction('store', 'readwrite').objectStore('store')");
+    evalAndLog("ro_transaction = db.transaction('store', 'readonly')");
+    evalAndLog("storeFromReadOnlyTransaction = ro_transaction.objectStore('store')");
+    evalAndLog("rw_transaction = db.transaction('store', 'readwrite')");
+    evalAndLog("store = rw_transaction.objectStore('store')");
 
     debug("");
     debug("IDBObjectStore.add()");
-    debug("storeFromReadOnlyTransaction = db.transaction('store', 'readonly').objectStore('store')");
-    debug("store = db.transaction('store', 'readwrite').objectStore('store')");
     debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly".');
     evalAndExpectException("storeFromReadOnlyTransaction.add(0, 0)", "IDBDatabaseException.READ_ONLY_ERR", "'ReadOnlyError'");
     // "If any of the following conditions are true, this method throws a DOMException of type DataError:" - covered in objectstore-basics.html
@@ -223,43 +209,61 @@ function testObjectStore()
     debug("The data being stored could not be cloned by the internal structured cloning algorithm.");
     evalAndExpectException("store.put(self, 0)", "DOMException.DATA_CLONE_ERR"); // FIXME: Test 'DataCloneError' name when DOM4 exceptions are used in binding.
 
-    request = evalAndLog("db.setVersion('3')");
+    evalAndLog("db.close()");
+    evalAndLog("ro_transaction.oncomplete = transactionComplete");
+    evalAndLog("rw_transaction.oncomplete = transactionComplete");
+}
+
+var numCompleted = 0;
+function transactionComplete(evt)
+{
+    preamble(evt);
+    numCompleted++;
+    if (numCompleted == 1) {
+        debug("First transaction completed");
+        return;
+    }
+    evalAndLog("request = indexedDB.open(dbname, 3)");
     request.onerror = unexpectedErrorCallback;
     request.onblocked = unexpectedBlockedCallback;
-    request.onsuccess = function() {
-        var trans = request.result;
-        trans.onabort = unexpectedAbortCallback;
-        store = trans.objectStore('store');
+    evalAndLog("request.onupgradeneeded = onUpgradeNeeded3");
+}
 
-        debug("");
-        debug("IDBObjectStore.createIndex()");
-        debug("If an index with the same name already exists, the implementation must throw a DOMException of type ConstraintError. ");
-        evalAndExpectException("store.createIndex('index', 'keyPath')", "IDBDatabaseException.CONSTRAINT_ERR", "'ConstraintError'");
-        debug("If keyPath is not a valid key path then a DOMException of type SyntaxError must be thrown.");
-        evalAndExpectException("store.createIndex('fail', '-invalid-')", "DOMException.SYNTAX_ERR", "'SyntaxError'");
-        debug("If keyPath is an Array and the multiEntry property in the optionalParameters is true, then a DOMException of type InvalidAccessError must be thrown.");
-        evalAndExpectException("store.createIndex('fail', ['a'], {multiEntry: true})", "DOMException.INVALID_ACCESS_ERR", "'InvalidAccessError'");
-        // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
+function onUpgradeNeeded3()
+{
+    db = request.result;
+    var trans = request.transaction;
+    trans.onabort = unexpectedAbortCallback;
+    trans.oncomplete = testOutsideVersionChangeTransaction;
+    store = trans.objectStore('store');
 
-        debug("");
-        debug("IDBObjectStore.deleteIndex()");
-        debug("There is no index with the given name, compared in a case-sensitive manner, in the connected database.");
-        evalAndExpectException("store.deleteIndex('no-such-index')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");
-        // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
-
-        trans.oncomplete = function() {
-            debug("");
-            debug("One more IDBObjectStore.createIndex() test:");
-            debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
-            evalAndExpectException("db.transaction('store').objectStore('store').createIndex('fail', 'keyPath')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
-
-            debug("");
-            debug("One more IDBObjectStore.deleteIndex() test:");
-            debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
-            evalAndExpectException("db.transaction('store').objectStore('store').deleteIndex('fail', 'keyPath')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
-            testIndex();
-        };
-    };
+    debug("");
+    debug("IDBObjectStore.createIndex()");
+    debug("If an index with the same name already exists, the implementation must throw a DOMException of type ConstraintError. ");
+    evalAndExpectException("store.createIndex('index', 'keyPath')", "IDBDatabaseException.CONSTRAINT_ERR", "'ConstraintError'");
+    debug("If keyPath is not a valid key path then a DOMException of type SyntaxError must be thrown.");
+    evalAndExpectException("store.createIndex('fail', '-invalid-')", "DOMException.SYNTAX_ERR", "'SyntaxError'");
+    debug("If keyPath is an Array and the multiEntry property in the optionalParameters is true, then a DOMException of type InvalidAccessError must be thrown.");
+    evalAndExpectException("store.createIndex('fail', ['a'], {multiEntry: true})", "DOMException.INVALID_ACCESS_ERR", "'InvalidAccessError'");
+    // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
+
+    debug("");
+    debug("IDBObjectStore.deleteIndex()");
+    debug("There is no index with the given name, compared in a case-sensitive manner, in the connected database.");
+    evalAndExpectException("store.deleteIndex('no-such-index')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");
+}
+
+function testOutsideVersionChangeTransaction() {
+    debug("");
+    debug("One more IDBObjectStore.createIndex() test:");
+    debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
+    evalAndExpectException("db.transaction('store').objectStore('store').createIndex('fail', 'keyPath')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
+
+    debug("");
+    debug("One more IDBObjectStore.deleteIndex() test:");
+    debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
+    evalAndExpectException("db.transaction('store').objectStore('store').deleteIndex('fail', 'keyPath')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
+    testIndex();
 }
 
 function testIndex()
@@ -461,5 +465,3 @@ function testTransaction()
 
     finishJSTest();
 }
-
-test();
index a33e070..aec1873 100644 (file)
@@ -5,27 +5,10 @@ if (this.importScripts) {
 
 description("Test IndexedDB's webkitIndexedDB.deleteDatabase().");
 
-function test()
+indexedDBTest(prepareDatabase, getValue);
+function prepareDatabase()
 {
-    removeVendorPrefixes();
-    request = evalAndLog("indexedDB.open('database-to-delete')");
-    request.onsuccess = startSetVersion;
-    request.onerror = unexpectedErrorCallback;
-}
-
-function startSetVersion()
-{
-    db = evalAndLog("db = event.target.result");
-
-    request = evalAndLog("db.setVersion('new version')");
-    request.onsuccess = deleteExisting;
-    request.onerror = unexpectedErrorCallback;
-}
-
-function deleteExisting()
-{
-    self.trans = evalAndLog("trans = event.target.result");
-    shouldBeNonNull("trans");
+    db = event.target.result;
 
     store = evalAndLog("store = db.createObjectStore('storeName', null)");
 
@@ -34,7 +17,6 @@ function deleteExisting()
 
     request = evalAndLog("store.add('value', 'key')");
     request.onerror = unexpectedErrorCallback;
-    trans.oncomplete = getValue;
 }
 
 function getValue()
@@ -51,16 +33,18 @@ function getValue()
 function addIndex()
 {
     shouldBeEqualToString("event.target.result", "value");
+    evalAndLog("db.close()");
 
-    request = evalAndLog("db.setVersion('new version')");
-    request.onsuccess = deleteDatabase;
+    request = evalAndLog("indexedDB.open(dbname, 2)");
+    request.onupgradeneeded = deleteDatabase;
     request.onerror = unexpectedErrorCallback;
 }
 
 function deleteDatabase()
 {
-    db.onversionchange = function() { db.close(); }
-    request = evalAndLog("request = indexedDB.deleteDatabase('database-to-delete')");
+    evalAndLog("db = event.target.result");
+    db.onversionchange = function() { evalAndLog("db.close()"); }
+    request = evalAndLog("request = indexedDB.deleteDatabase(dbname)");
     request.onsuccess = reopenDatabase;
     request.onerror = unexpectedErrorCallback;
 }
@@ -68,25 +52,16 @@ function deleteDatabase()
 function reopenDatabase()
 {
     shouldBeUndefined("request.result");
-    request = evalAndLog("indexedDB.open('database-to-delete')");
-    request.onsuccess = startSetVersionAgain;
-    request.onerror = unexpectedErrorCallback;
-}
-
-function startSetVersionAgain()
-{
-    rdb = evalAndLog("db = event.target.result");
-
-    request = evalAndLog("db.setVersion('new version')");
-    request.onsuccess = verifyNotFound;
+    request = evalAndLog("indexedDB.open(dbname, 3)");
+    request.onupgradeneeded = verifyNotFound;
     request.onerror = unexpectedErrorCallback;
+    request.onblocked = unexpectedBlockedCallback;
 }
 
 function verifyNotFound()
 {
+    db = evalAndLog("db = event.target.result");
     shouldBe("db.objectStoreNames.length", "0");
 
     finishJSTest();
 }
-
-test();
\ No newline at end of file
index 5167b28..904473d 100644 (file)
@@ -37,16 +37,18 @@ function storeCollidedStoreIndexData() {
 
 function testCollideAutoIncrementSetup()
 {
-    request = evalAndLog("db.setVersion('2')");
-    request.onsuccess = testCollideAutoIncrement;
+    evalAndLog("db.close()");
+    evalAndLog("request = indexedDB.open(dbname, 2)");
+    request.onupgradeneeded = testCollideAutoIncrement;
     request.onerror = unexpectedErrorCallback;
     request.onblocked = unexpectedBlockedCallback;
 }
 
 function testCollideAutoIncrement()
 {
+    db = event.target.result;
+    var trans = request.transaction;
     deleteAllObjectStores(db);
-    var trans = request.result;
     evalAndLog("store = db.createObjectStore('collideWithAutoIncrement', {keyPath: 'foo', autoIncrement: true})");
     evalAndLog("index = store.createIndex('foo', 'foo')");
 
index 58fb92d..7df5f59 100644 (file)
@@ -5,31 +5,10 @@ if (this.importScripts) {
 
 description("Test features of IndexedDB's multiEntry indices.");
 
-function test()
-{
-    removeVendorPrefixes();
-
-    request = evalAndLog("indexedDB.open('index-multiEntry')");
-    request.onerror = unexpectedErrorCallback;
-    request.onsuccess = function() {
-        db = evalAndLog("db = event.target.result");
-
-        request = evalAndLog("db.setVersion('1')");
-        request.onerror = unexpectedErrorCallback;
-        request.onsuccess = prepareDatabase;
-    };
-}
-
+indexedDBTest(prepareDatabase, addData);
 function prepareDatabase()
 {
-    debug("");
-    debug("Creating empty stores and indexes");
-    var trans = evalAndLog("trans = event.target.result");
-    shouldBeNonNull("trans");
-    trans.onabort = unexpectedAbortCallback;
-    trans.oncomplete = addData;
-
-    deleteAllObjectStores(db);
+    db = event.target.result;
 
     store = evalAndLog("store = db.createObjectStore('store')");
     evalAndLog("store.createIndex('index', 'x', {multiEntry: true})");
@@ -129,13 +108,13 @@ function createIndexOnStoreWithData()
 {
     debug("");
     debug("Create an index on a populated store");
+    evalAndLog("db.close()");
 
-    request = evalAndLog("db.setVersion('2')");
+    request = evalAndLog("indexedDB.open(dbname, 2)");
     request.onerror = unexpectedErrorCallback;
-    request.onsuccess = function() {
-
-        var trans = evalAndLog("trans = event.target.result");
-        shouldBeNonNull("trans");
+    request.onupgradeneeded = function() {
+        evalAndLog("db = event.target.result");
+        evalAndLog("trans = event.target.transaction");
         trans.onabort = unexpectedAbortCallback;
         trans.oncomplete = function() { verifyIndexes('index-new', finishJSTest); };
 
@@ -143,5 +122,3 @@ function createIndexOnStoreWithData()
         evalAndLog("store.createIndex('index-new', 'x', {multiEntry: true})");
     };
 }
-
-test();
\ No newline at end of file
index 9c6ac28..30247c9 100644 (file)
@@ -5,39 +5,11 @@ if (this.importScripts) {
 
 description("Test IndexedDB index population.");
 
-function test()
+indexedDBTest(prepareDatabase, doSetVersion2);
+function prepareDatabase()
 {
-    removeVendorPrefixes();
-
-    request = evalAndLog("indexedDB.deleteDatabase('index-population')");
-    request.onsuccess = deleteSuccess;
-    request.onerror = unexpectedErrorCallback;
-}
-
-function deleteSuccess()
-{
-    request = evalAndLog("indexedDB.open('index-population')");
-    request.onsuccess = doSetVersion1;
-    request.onblocked = unexpectedBlockedCallback;
-    request.onerror = unexpectedErrorCallback;
-}
-
-function doSetVersion1()
-{
-    debug("");
-    debug("doSetVersion1():");
-    self.db = evalAndLog("db = event.target.result");
-    request = evalAndLog("request = db.setVersion('version 1')");
-    request.onsuccess = setVersion1;
-    request.onblocked = unexpectedBlockedCallback;
-    request.onerror = unexpectedErrorCallback;
-}
-
-function setVersion1()
-{
-    debug("");
-    debug("setVersion1():");
-    transaction = evalAndLog("transaction = request.result");
+    db = event.target.result;
+    evalAndLog("transaction = event.target.transaction");
     transaction.onerror = unexpectedErrorCallback;
     transaction.onabort = unexpectedAbortCallback;
     store = evalAndLog("store = db.createObjectStore('store1')");
@@ -53,22 +25,23 @@ function setVersion1()
     request.onsuccess = function () {
         shouldBe("request.result", "4");
     };
-    transaction.oncomplete = doSetVersion2;
 }
 
 function doSetVersion2() {
     debug("");
     debug("doSetVersion2():");
-    request = evalAndLog("request = db.setVersion('version 2')");
-    request.onsuccess = setVersion2;
-    request.onerror = unexpectedErrorCallback;
+    evalAndLog("db.close()");
+    evalAndLog("request = indexedDB.open(dbname, 2)");
+    request.onupgradeneeded = setVersion2;
+    request.onblocked = unexpectedBlockedCallback;
 }
 
 function setVersion2()
 {
     debug("");
     debug("setVersion2():");
-    transaction2 = evalAndLog("transaction = request.result");
+    db = event.target.result;
+    transaction2 = evalAndLog("transaction = request.transaction");
     transaction2.onabort = setVersion2Abort;
     transaction2.oncomplete = unexpectedCompleteCallback;
 
@@ -96,5 +69,3 @@ function setVersion2Abort()
     shouldBeEqualToString("db.objectStoreNames[0]", "store1");
     finishJSTest();
 }
-
-test();
\ No newline at end of file
index 14c47c7..85d0db0 100644 (file)
@@ -5,71 +5,47 @@ if (this.importScripts) {
 
 description("Test IndexedDB database metadata mutation/snapshotting");
 
-function test()
+indexedDBTest(prepareDatabase, snapshotConnection1);
+function prepareDatabase()
 {
-    removeVendorPrefixes();
-    evalAndLog("dbname = self.location.pathname");
-    evalAndLog("request = indexedDB.deleteDatabase(dbname)");
-    request.onerror = unexpectedErrorCallback;
-    request.onsuccess = firstOpen;
+    connection1 = event.target.result;
+    evalAndLog("connection1store1 = connection1.createObjectStore('store1')");
+    evalAndLog("connection1store1.createIndex('index1', 'path')");
+
+    shouldBe("connection1.version", "1");
+    shouldBe("connection1.objectStoreNames.length", "1");
+    shouldBe("connection1store1.indexNames.length", "1");
 }
 
-function firstOpen()
+function snapshotConnection1()
 {
-    debug("");
-    debug("firstOpen():");
-    evalAndLog("request = indexedDB.open(dbname)");
-    request.onerror = unexpectedErrorCallback;
-    request.onsuccess = function() {
-        evalAndLog("connection1 = request.result");
-        evalAndLog("request = connection1.setVersion('1')");
-        request.onerror = unexpectedErrorCallback;
-        request.onsuccess = function() {
-            evalAndLog("trans = request.result");
-            evalAndLog("connection1store1 = connection1.createObjectStore('store1')");
-            evalAndLog("connection1store1.createIndex('index1', 'path')");
-
-            shouldBeEqualToString("connection1.version", "1");
-            shouldBe("connection1.objectStoreNames.length", "1");
-            shouldBe("connection1store1.indexNames.length", "1");
-
-            trans.onabort = unexpectedAbortCallback;
-            trans.oncomplete = function() {
-                debug("Connection's properties should be snapshotted on close");
-                evalAndLog("connection1.close()");
-                secondOpen();
-            };
-        };
-    };
+    debug("Connection's properties should be snapshotted on close");
+    evalAndLog("connection1.close()");
+    secondOpen();
 }
 
 function secondOpen()
 {
     debug("");
     debug("secondOpen():");
-    evalAndLog("request = indexedDB.open(dbname)");
+    evalAndLog("request = indexedDB.open(dbname, 2)");
     request.onerror = unexpectedErrorCallback;
-    request.onsuccess = function() {
+    request.onblocked = unexpectedBlockedCallback;
+    request.onupgradeneeded = function() {
         evalAndLog("connection2 = request.result");
-        evalAndLog("request = connection2.setVersion('2')");
-        request.onerror = unexpectedErrorCallback;
-        request.onsuccess = function() {
-            evalAndLog("trans = request.result");
-            evalAndLog("connection2.createObjectStore('store2')");
-            evalAndLog("connection2store1 = trans.objectStore('store1')");
-            evalAndLog("connection2store1.createIndex('index2', 'path')");
-
-            shouldBeEqualToString("connection2.version", "2");
-            shouldBe("connection2.objectStoreNames.length", "2");
-            shouldBe("connection2store1.indexNames.length", "2");
-
-            trans.onabort = unexpectedAbortCallback;
-            trans.oncomplete = function() {
-                debug("Connection's properties should be snapshotted on close");
-                evalAndLog("connection2.close()");
-                thirdOpen();
-            };
-        };
+        evalAndLog("trans = request.transaction");
+        evalAndLog("connection2.createObjectStore('store2')");
+        evalAndLog("connection2store1 = trans.objectStore('store1')");
+        evalAndLog("connection2store1.createIndex('index2', 'path')");
+
+        shouldBe("connection2.version", "2");
+        shouldBe("connection2.objectStoreNames.length", "2");
+        shouldBe("connection2store1.indexNames.length", "2");
+    };
+    request.onsuccess = function() {
+        debug("Connection's properties should be snapshotted on close");
+        evalAndLog("connection2.close()");
+        thirdOpen();
     };
 }
 
@@ -77,61 +53,51 @@ function thirdOpen()
 {
     debug("");
     debug("thirdOpen():");
-    evalAndLog("request = indexedDB.open(dbname)");
-    request.onerror = unexpectedErrorCallback;
-    request.onsuccess = function() {
+    evalAndLog("request = indexedDB.open(dbname, 3)");
+    request.onsuccess = unexpectedSuccessCallback;
+    request.onupgradeneeded = function() {
         evalAndLog("connection3 = request.result");
-        evalAndLog("request = connection3.setVersion('3')");
-        request.onerror = unexpectedErrorCallback;
-        request.onsuccess = function() {
-            evalAndLog("trans = request.result");
-            evalAndLog("connection3.createObjectStore('store3')");
-            evalAndLog("connection3store1 = trans.objectStore('store1')");
-            evalAndLog("connection3store1.createIndex('index3', 'path')");
-
-            shouldBeEqualToString("connection3.version", "3");
-            shouldBe("connection3.objectStoreNames.length", "3");
-            shouldBe("connection3store1.indexNames.length", "3");
-
-            trans.oncomplete = unexpectedCompleteCallback;
-            trans.onabort = function() {
-                debug("Connection's properties should be snapshotted on close");
-                evalAndLog("connection3.close()");
-                fourthOpen();
-            };
-            debug("Connection's properties should be reverted on abort");
-            evalAndLog("trans.abort()");
-        };
+        evalAndLog("trans = request.transaction");
+        evalAndLog("connection3.createObjectStore('store3')");
+        evalAndLog("connection3store1 = trans.objectStore('store1')");
+        evalAndLog("connection3store1.createIndex('index3', 'path')");
+
+        shouldBe("connection3.version", "3");
+        shouldBe("connection3.objectStoreNames.length", "3");
+        shouldBe("connection3store1.indexNames.length", "3");
+
+        trans.oncomplete = unexpectedCompleteCallback;
+        debug("Connection's properties should be reverted on abort");
+        evalAndLog("trans.abort()");
     };
+    request.onerror = function() {
+        debug("Connection's properties should be snapshotted on close");
+        evalAndLog("connection3.close()");
+        fourthOpen();
+    }
 }
 
 function fourthOpen()
 {
     debug("");
     debug("fourthOpen():");
-    evalAndLog("request = indexedDB.open(dbname)");
+    evalAndLog("request = indexedDB.open(dbname, 4)");
     request.onerror = unexpectedErrorCallback;
-    request.onsuccess = function() {
+    request.onupgradeneeded = function() {
         evalAndLog("connection4 = request.result");
-        evalAndLog("request = connection4.setVersion('4')");
-        request.onerror = unexpectedErrorCallback;
-        request.onsuccess = function() {
-            evalAndLog("trans = request.result");
-            evalAndLog("connection4.createObjectStore('store4')");
-            evalAndLog("connection4store1 = trans.objectStore('store1')");
-            evalAndLog("connection4store1.createIndex('index4', 'path')");
-
-            shouldBeEqualToString("connection4.version", "4");
-            shouldBe("connection4.objectStoreNames.length", "3");
-            shouldBe("connection4store1.indexNames.length", "3");
-
-            trans.onabort = unexpectedAbortCallback;
-            trans.oncomplete = function() {
-                debug("Connection's properties should be snapshotted on close");
-                evalAndLog("connection4.close()");
-                checkState();
-            };
-        };
+        evalAndLog("trans = request.transaction");
+        evalAndLog("connection4.createObjectStore('store4')");
+        evalAndLog("connection4store1 = trans.objectStore('store1')");
+        evalAndLog("connection4store1.createIndex('index4', 'path')");
+
+        shouldBe("connection4.version", "4");
+        shouldBe("connection4.objectStoreNames.length", "3");
+        shouldBe("connection4store1.indexNames.length", "3");
+    };
+    request.onsuccess = function() {
+        debug("Connection's properties should be snapshotted on close");
+        evalAndLog("connection4.close()");
+        checkState();
     };
 }
 
@@ -140,27 +106,25 @@ function checkState()
     debug("");
     debug("checkState():");
 
-    shouldBeEqualToString("connection1.version", "1");
+    shouldBe("connection1.version", "1");
     shouldBe("connection1.objectStoreNames.length", "1");
     shouldBe("connection1store1.indexNames.length", "1");
     debug("");
 
-    shouldBeEqualToString("connection2.version", "2");
+    shouldBe("connection2.version", "2");
     shouldBe("connection2.objectStoreNames.length", "2");
     shouldBe("connection2store1.indexNames.length", "2");
     debug("");
 
-    shouldBeEqualToString("connection3.version", "2");
+    shouldBe("connection3.version", "2");
     shouldBe("connection3.objectStoreNames.length", "2");
     shouldBe("connection3store1.indexNames.length", "2");
     debug("");
 
-    shouldBeEqualToString("connection4.version", "4");
+    shouldBe("connection4.version", "4");
     shouldBe("connection4.objectStoreNames.length", "3");
     shouldBe("connection4store1.indexNames.length", "3");
     debug("");
 
     finishJSTest();
 }
-
-test();