Diff
Modified: trunk/LayoutTests/ChangeLog (131465 => 131466)
--- trunk/LayoutTests/ChangeLog 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/ChangeLog 2012-10-16 16:52:26 UTC (rev 131466)
@@ -1,3 +1,50 @@
+2012-10-16 Joshua Bell <[email protected]>
+
+ IndexedDB: setTimeout in layout tests causes flakiness in multiprocess ports
+ https://bugs.webkit.org/show_bug.cgi?id=98949
+
+ Reviewed by Tony Chang.
+
+ In multiprocess ports with asynchronous IPC, events and timers may race causing script
+ callbacks to execute in different orders.
+
+ Eliminate the uses of setTimeout() where the intent is to have code delayed but may
+ race with a pending event.
+
+ * fast/js/resources/js-test-pre.js:
+ (evalAndLog) Added quiet flag.
+ * storage/indexeddb/deletedatabase-blocked-expected.txt:
+ * storage/indexeddb/deletedatabase-delayed-by-open-and-versionchange-expected.txt:
+ * storage/indexeddb/deletedatabase-delayed-by-versionchange-expected.txt:
+ * storage/indexeddb/intversion-close-between-events-expected.txt:
+ * storage/indexeddb/resources/deletedatabase-blocked.js: Remove setTimeout.
+ (test.request.onsuccess.openOnSuccess.h.onversionchange):
+ (test.request.onsuccess.openOnSuccess.request.onblocked):
+ * storage/indexeddb/resources/deletedatabase-delayed-by-open-and-versionchange.js: Remove setTimeout.
+ (test.request.onsuccess.openOnSuccess.h.onversionchange):
+ (test.request.onsuccess.openOnSuccess.request.onblocked):
+ * storage/indexeddb/resources/deletedatabase-delayed-by-versionchange.js: Remove setTimeout.
+ (test.request.onsuccess.openOnSuccess.h.onversionchange):
+ (test.request.onsuccess.openOnSuccess.request.onsuccess.h2OpenOnSuccess.request.onblocked):
+ * storage/indexeddb/resources/intversion-close-between-events.js: Test was intended to call db.close()
+ between "complete" and "success" but in single process ports this is not possible, and in multi-process
+ ports is not reliable. To make the test not flaky and watch out for regressions in this edge case, it
+ is changed to have minimal logging.
+ (deleteSuccess):
+ (upgradeNeeded.transaction.oncomplete):
+ (upgradeNeeded):
+ (closeDB):
+ (openSuccess):
+ (checkFinished):
+ * storage/indexeddb/resources/intversion-close-in-oncomplete.js: Log on error rather than timing out.
+ (deleteSuccess):
+ * storage/indexeddb/resources/setversion-blocked.js: Removed setTimeout.
+ (test.request.onsuccess.h1OpenOnSuccess.request.onsuccess.h2OpenOnSuccess.h2.onversionchange):
+ (test.request.onsuccess.h1OpenOnSuccess.request.onsuccess.h2OpenOnSuccess.request.onblocked):
+ * storage/indexeddb/resources/shared.js:
+ (evalAndExpectException) Added quiet flag.
+ * storage/indexeddb/setversion-blocked-expected.txt:
+
2012-10-16 Takashi Sakamoto <[email protected]>
[Meta] [Shadow] contenteditable attribute for distributed nodes.
Modified: trunk/LayoutTests/fast/js/resources/js-test-pre.js (131465 => 131466)
--- trunk/LayoutTests/fast/js/resources/js-test-pre.js 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/fast/js/resources/js-test-pre.js 2012-10-16 16:52:26 UTC (rev 131466)
@@ -145,13 +145,14 @@
else return "" + v;
}
-function evalAndLog(_a)
+function evalAndLog(_a, _quiet)
{
if (typeof _a != "string")
debug("WARN: tryAndLog() expects a string argument");
// Log first in case things go horribly wrong or this causes a sync event.
- debug(_a);
+ if (!_quiet)
+ debug(_a);
var _av;
try {
@@ -527,7 +528,6 @@
workerPort = e.ports[0];
workerPort._onmessage_ = function(event)
{
-
var colon = event.data.indexOf(":");
if (colon == -1) {
testFailed("Unrecognized message to shared worker: " + event.data);
Modified: trunk/LayoutTests/storage/indexeddb/deletedatabase-blocked-expected.txt (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/deletedatabase-blocked-expected.txt 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/deletedatabase-blocked-expected.txt 2012-10-16 16:52:26 UTC (rev 131466)
@@ -16,12 +16,9 @@
onVersionChange():
old = 1
new = ""
-scheduling timeout to close
deleteDatabaseOnBlocked():
blockedEventFired = true
-
-timeoutCallback():
h.close()
deleteDatabaseOnSuccess():
Modified: trunk/LayoutTests/storage/indexeddb/deletedatabase-delayed-by-open-and-versionchange-expected.txt (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/deletedatabase-delayed-by-open-and-versionchange-expected.txt 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/deletedatabase-delayed-by-open-and-versionchange-expected.txt 2012-10-16 16:52:26 UTC (rev 131466)
@@ -24,11 +24,8 @@
onVersionChange():
old = "1"
new = ""
-scheduling timeout to close
deleteDatabaseOnBlocked():
-
-timeoutCallback():
h.close()
deleteDatabaseOnSuccess():
Modified: trunk/LayoutTests/storage/indexeddb/deletedatabase-delayed-by-versionchange-expected.txt (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/deletedatabase-delayed-by-versionchange-expected.txt 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/deletedatabase-delayed-by-versionchange-expected.txt 2012-10-16 16:52:26 UTC (rev 131466)
@@ -39,12 +39,9 @@
onVersionChange():
old = "1"
new = ""
-scheduling timeout to close
deleteDatabaseOnBlocked():
deleteDatabaseBlockedEventFired = true
-
-timeoutCallback():
h.close()
deleteDatabaseOnSuccess():
Modified: trunk/LayoutTests/storage/indexeddb/intversion-close-between-events-expected.txt (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/intversion-close-between-events-expected.txt 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/intversion-close-between-events-expected.txt 2012-10-16 16:52:26 UTC (rev 131466)
@@ -7,30 +7,33 @@
dbname = "intversion-close-between-events.html"
indexedDB.deleteDatabase(dbname)
+
+deleteSuccess():
request = indexedDB.open(dbname, 7)
-
upgradeNeeded():
db = event.target.result
PASS event.newVersion is 7
db.createObjectStore('objectstore')
transaction = event.target.transaction
-transaction.oncomplete:
+transactionComplete():
sawTransactionComplete = true
+
+Now try and close the database after oncomplete but before onsuccess.
+This will not happen in single process ports. In multi-process ports
+it may and is fine; but flaky crashes would indicate a regression.
+
setTimeout(closeDB, 0)
-openSuccess():
-PASS didCallCloseDB is false
+checkFinished():
+Not done yet...
+
+checkFinished():
+PASS didCallCloseDB is true
PASS sawTransactionComplete is true
-db = event.target.result
PASS db.version is 7
PASS db.objectStoreNames.length is 1
-db.transaction(db.objectStoreNames)
-
-closeDB():
-didCallCloseDB = true
-db.close()
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/storage/indexeddb/mozilla/resources/create-index-unique.js (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/mozilla/resources/create-index-unique.js 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/mozilla/resources/create-index-unique.js 2012-10-16 16:52:26 UTC (rev 131466)
@@ -38,7 +38,7 @@
indexName = "1";
indexKeyPath = "unique_value";
- index = evalAndLog("index = objectStore.createIndex(indexName, indexKeyPath, { unique: true });", "IDBDatabaseException.CONSTRAINT_ERR");
+ index = evalAndLog("index = objectStore.createIndex(indexName, indexKeyPath, { unique: true });");
shouldBe("index.name", "indexName");
shouldBe("index.keyPath", "indexKeyPath");
shouldBe("index.unique", "true");
Modified: trunk/LayoutTests/storage/indexeddb/resources/deletedatabase-blocked.js (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/resources/deletedatabase-blocked.js 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/resources/deletedatabase-blocked.js 2012-10-16 16:52:26 UTC (rev 131466)
@@ -22,25 +22,14 @@
preamble(evt);
debug("old = " + JSON.stringify(event.target.version));
debug("new = " + JSON.stringify(event.version));
+ };
- debug("scheduling timeout to close");
- // This setTimeout() is used to move the close call outside of the event dispatch
- // callback. Per spec, a blocked event should only fire if connections are still
- // open after the versionchange event dispatch is complete.
- // FIXME: There is potential for test flakiness in the timing between when the
- // timeout runs and when the blocked event is dispatched. Move the close call
- // into or after the blocked event handler.
- setTimeout(function timeoutCallback() {
- preamble();
- evalAndLog("h.close()");
- }, 0);
- };
-
request = evalAndLog("indexedDB.deleteDatabase(dbname)");
request._onerror_ = unexpectedErrorCallback;
request._onblocked_ = function deleteDatabaseOnBlocked(evt) {
preamble(evt);
evalAndLog("blockedEventFired = true");
+ evalAndLog("h.close()");
};
request._onsuccess_ = function deleteDatabaseOnSuccess(evt) {
preamble(evt);
Modified: trunk/LayoutTests/storage/indexeddb/resources/deletedatabase-delayed-by-open-and-versionchange.js (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/resources/deletedatabase-delayed-by-open-and-versionchange.js 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/resources/deletedatabase-delayed-by-open-and-versionchange.js 2012-10-16 16:52:26 UTC (rev 131466)
@@ -23,18 +23,6 @@
preamble(evt);
debug("old = " + JSON.stringify(event.target.version));
debug("new = " + JSON.stringify(event.version));
-
- debug("scheduling timeout to close");
- // This setTimeout() is used to move the close call outside of the event dispatch
- // callback. Per spec, a blocked event should only fire if connections are still
- // open after the versionchange event dispatch is complete.
- // FIXME: There is potential for test flakiness in the timing between when the
- // timeout runs and when the blocked event is dispatched. Move the close call
- // into or after the blocked event handler.
- setTimeout(function timeoutCallback() {
- preamble();
- evalAndLog("h.close()");
- }, 0);
};
request = evalAndLog("h.setVersion(String(ver++))");
@@ -55,6 +43,8 @@
request._onerror_ = unexpectedErrorCallback;
request._onblocked_ = function deleteDatabaseOnBlocked(evt) {
preamble(evt);
+
+ evalAndLog("h.close()");
};
request._onsuccess_ = function deleteDatabaseOnSuccess(evt) {
preamble(evt);
Modified: trunk/LayoutTests/storage/indexeddb/resources/deletedatabase-delayed-by-versionchange.js (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/resources/deletedatabase-delayed-by-versionchange.js 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/resources/deletedatabase-delayed-by-versionchange.js 2012-10-16 16:52:26 UTC (rev 131466)
@@ -26,18 +26,6 @@
preamble(evt);
debug("old = " + JSON.stringify(event.target.version));
debug("new = " + JSON.stringify(event.version));
-
- debug("scheduling timeout to close");
- // This setTimeout() is used to move the close call outside of the event dispatch
- // callback. Per spec, a blocked event should only fire if connections are still
- // open after the versionchange event dispatch is complete.
- // FIXME: There is potential for test flakiness in the timing between when the
- // timeout runs and when the blocked event is dispatched. Move the close call
- // into or after the blocked event handler.
- setTimeout(function timeoutCallback() {
- preamble();
- evalAndLog("h.close()");
- }, 0);
};
request = evalAndLog("indexedDB.open(dbname)");
@@ -93,6 +81,8 @@
request._onblocked_ = function deleteDatabaseOnBlocked(evt) {
preamble(evt);
evalAndLog("deleteDatabaseBlockedEventFired = true");
+
+ evalAndLog("h.close()");
};
request._onsuccess_ = function deleteDatabaseOnSuccess(evt) {
preamble(evt);
Modified: trunk/LayoutTests/storage/indexeddb/resources/intversion-close-between-events.js (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/resources/intversion-close-between-events.js 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/resources/intversion-close-between-events.js 2012-10-16 16:52:26 UTC (rev 131466)
@@ -16,58 +16,78 @@
}
function deleteSuccess(evt) {
+ preamble(evt);
+
evalAndLog("request = indexedDB.open(dbname, 7)");
request._onsuccess_ = openSuccess;
request._onupgradeneeded_ = upgradeNeeded;
request._onblocked_ = unexpectedBlockedCallback;
- debug("");
+ request._onerror_ = unexpectedErrorCallback;
}
var sawTransactionComplete = false;
function upgradeNeeded(evt)
{
- event = evt;
- debug("");
- debug("upgradeNeeded():");
+ preamble(evt);
evalAndLog("db = event.target.result");
shouldBe("event.newVersion", "7");
evalAndLog("db.createObjectStore('objectstore')");
evalAndLog("transaction = event.target.transaction");
transaction._onabort_ = unexpectedAbortCallback;
- transaction._oncomplete_ = function() {
+ transaction._oncomplete_ = function transactionComplete(evt) {
+ preamble(evt);
+ evalAndLog("sawTransactionComplete = true");
+
debug("");
- debug("transaction.oncomplete:");
- evalAndLog("sawTransactionComplete = true");
+ debug("Now try and close the database after oncomplete but before onsuccess.");
+ debug("This will not happen in single process ports. In multi-process ports");
+ debug("it may and is fine; but flaky crashes would indicate a regression.");
+ debug("");
+
evalAndLog("setTimeout(closeDB, 0)");
- }
+ };
}
var didCallCloseDB = false;
+var didGetOpenSuccess = false;
+
function closeDB()
{
- debug("");
- debug("closeDB():");
- evalAndLog("didCallCloseDB = true");
- evalAndLog("db.close()");
- finishJSTest();
+ db.close();
+ didCallCloseDB = true;
+ checkFinished();
}
function openSuccess(evt)
{
- event = evt;
- debug("");
- debug("openSuccess():");
- shouldBeFalse("didCallCloseDB");
+ didGetOpenSuccess = true;
+
+ var quiet = true;
+ if (didCallCloseDB) {
+ evalAndExpectException("db.transaction(db.objectStoreNames)", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'", quiet);
+ } else {
+ evalAndLog("db.transaction(db.objectStoreNames)", quiet);
+ }
+
+ checkFinished();
+}
+
+function checkFinished()
+{
+ preamble();
+
+ if (!didCallCloseDB || !didGetOpenSuccess) {
+ debug("Not done yet...");
+ return;
+ }
+
+ shouldBeTrue("didCallCloseDB");
shouldBeTrue("sawTransactionComplete");
- db = evalAndLog("db = event.target.result");
shouldBe('db.version', "7");
- if (db.version !== 7) {
- finishJSTest();
- return;
- }
shouldBe("db.objectStoreNames.length", "1");
- evalAndLog("db.transaction(db.objectStoreNames)");
+
+ finishJSTest();
}
test();
Modified: trunk/LayoutTests/storage/indexeddb/resources/intversion-close-in-oncomplete.js (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/resources/intversion-close-in-oncomplete.js 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/resources/intversion-close-in-oncomplete.js 2012-10-16 16:52:26 UTC (rev 131466)
@@ -20,6 +20,7 @@
request._onsuccess_ = openSuccess;
request._onupgradeneeded_ = upgradeNeeded;
request._onblocked_ = unexpectedBlockedCallback;
+ request._onerror_ = unexpectedErrorCallback;
}
var sawTransactionComplete = false;
Modified: trunk/LayoutTests/storage/indexeddb/resources/setversion-blocked.js (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/resources/setversion-blocked.js 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/resources/setversion-blocked.js 2012-10-16 16:52:26 UTC (rev 131466)
@@ -32,18 +32,6 @@
preamble(evt);
debug("old = " + JSON.stringify(event.target.version));
debug("new = " + JSON.stringify(event.version));
-
- debug("scheduling timeout to close h2");
- // This setTimeout() is used to move the close call outside of the event dispatch
- // callback. Per spec, a blocked event should only fire if connections are still
- // open after the versionchange event dispatch is complete.
- // FIXME: There is potential for test flakiness in the timing between when the
- // timeout runs and when the blocked event is dispatched. Move the close call
- // into or after the blocked event handler.
- setTimeout(function timeoutCallback() {
- preamble();
- evalAndLog("h2.close()");
- }, 0);
};
request = evalAndLog("h1.setVersion(String(ver++))");
@@ -51,6 +39,7 @@
request._onblocked_ = function h1SetVersionOnBlocked(evt) {
preamble(evt);
evalAndLog("blockedEventFired = true");
+ evalAndLog("h2.close()");
};
request._onsuccess_ = function h1SetVersionOnSuccess(evt) {
preamble(evt);
Modified: trunk/LayoutTests/storage/indexeddb/resources/shared.js (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/resources/shared.js 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/resources/shared.js 2012-10-16 16:52:26 UTC (rev 131466)
@@ -82,19 +82,21 @@
finishJSTest();
}
-function evalAndExpectException(cmd, exceptionCode, exceptionName)
+function evalAndExpectException(cmd, exceptionCode, exceptionName, _quiet)
{
- debug("Expecting exception from " + cmd);
+ if (!_quiet)
+ debug("Expecting exception from " + cmd);
try {
eval(cmd);
testFailed("No exception thrown! Should have been " + exceptionCode);
} catch (e) {
code = e.code;
- testPassed("Exception was thrown.");
- shouldBe("code", exceptionCode);
+ if (!_quiet)
+ testPassed("Exception was thrown.");
+ shouldBe("code", exceptionCode, _quiet);
if (exceptionName) {
ename = e.name;
- shouldBe("ename", exceptionName);
+ shouldBe("ename", exceptionName, _quiet);
}
}
}
Modified: trunk/LayoutTests/storage/indexeddb/setversion-blocked-expected.txt (131465 => 131466)
--- trunk/LayoutTests/storage/indexeddb/setversion-blocked-expected.txt 2012-10-16 16:42:02 UTC (rev 131465)
+++ trunk/LayoutTests/storage/indexeddb/setversion-blocked-expected.txt 2012-10-16 16:52:26 UTC (rev 131466)
@@ -22,12 +22,9 @@
h2OnVersionChange():
old = 1
new = "1"
-scheduling timeout to close h2
h1SetVersionOnBlocked():
blockedEventFired = true
-
-timeoutCallback():
h2.close()
h1SetVersionOnSuccess():