Bug 652494 - Report uncaught JS exceptions in chrome mochitests as test failures. r=jmaher
--- a/browser/base/content/test/browser_bug422590.js
+++ b/browser/base/content/test/browser_bug422590.js
@@ -1,10 +1,11 @@
function test() {
waitForExplicitFinish();
+ ignoreAllUncaughtExceptions();
// test the main (normal) browser window
testCustomize(window, testChromeless);
}
function testChromeless() {
// test a chromeless window
var newWin = openDialog("chrome://browser/content/", "_blank",
--- a/browser/base/content/test/browser_bug599325.js
+++ b/browser/base/content/test/browser_bug599325.js
@@ -1,10 +1,11 @@
function test() {
waitForExplicitFinish();
+ ignoreAllUncaughtExceptions();
testCustomize(window, finish);
}
function testCustomize(aWindow, aCallback) {
var addonBar = aWindow.document.getElementById("addon-bar");
ok(addonBar, "got addon bar");
ok(!isElementVisible(addonBar), "addon bar initially hidden");
--- a/browser/components/places/tests/browser/browser_sidebarpanels_click.js
+++ b/browser/components/places/tests/browser/browser_sidebarpanels_click.js
@@ -35,16 +35,17 @@
*
* ***** END LICENSE BLOCK ***** */
// This test makes sure that the items in the bookmarks and history sidebar
// panels are clickable in both LTR and RTL modes.
function test() {
waitForExplicitFinish();
+ ignoreAllUncaughtExceptions();
const BOOKMARKS_SIDEBAR_ID = "viewBookmarksSidebar";
const BOOKMARKS_SIDEBAR_TREE_ID = "bookmarks-view";
const HISTORY_SIDEBAR_ID = "viewHistorySidebar";
const HISTORY_SIDEBAR_TREE_ID = "historyTree";
const TEST_URL = "http://mochi.test:8888/browser/browser/components/places/tests/browser/sidebarpanels_click_test_page.html";
// If a sidebar is already open, close it.
--- a/browser/devtools/highlighter/test/browser_inspector_breadcrumbs.js
+++ b/browser/devtools/highlighter/test/browser_inspector_breadcrumbs.js
@@ -1,14 +1,15 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
+ ignoreAllUncaughtExceptions();
let nodes = [
{nodeId: "i1111", result: "i1 i11 i111 i1111"},
{nodeId: "i22", result: "i2 i22 i221"},
{nodeId: "i2111", result: "i2 i21 i211 i2111"},
{nodeId: "i21", result: "i2 i21 i211 i2111"},
{nodeId: "i22211", result: "i2 i22 i222 i2221 i22211"},
{nodeId: "i22", result: "i2 i22 i222 i2221 i22211"},
--- a/dom/plugins/test/mochitest/test_crash_submit.xul
+++ b/dom/plugins/test/mochitest/test_crash_submit.xul
@@ -11,16 +11,17 @@
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js" />
<body xmlns="http://www.w3.org/1999/xhtml" onload="runTests()">
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
SimpleTest.waitForExplicitFinish();
+SimpleTest.ignoreAllUncaughtExceptions();
Components.utils.import("resource://gre/modules/NetUtil.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
var crashReporter =
Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
.getService(Components.interfaces.nsICrashReporter);
var oldServerURL = crashReporter.serverURL;
--- a/extensions/spellcheck/tests/chrome/test_add_remove_dictionaries.xul
+++ b/extensions/spellcheck/tests/chrome/test_add_remove_dictionaries.xul
@@ -7,16 +7,17 @@
<title>Add and remove dictionaries test</title>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript">
<![CDATA[
SimpleTest.waitForExplicitFinish();
+SimpleTest.ignoreAllUncaughtExceptions();
function getMisspelledWords(editor) {
return editor.selectionController.getSelection(Components.interfaces.nsISelectionController.SELECTION_SPELLCHECK).toString();
}
function getDictionaryList(editor) {
var spellchecker = editor.getInlineSpellChecker(true).spellChecker;
var o1 = {};
--- a/layout/xul/base/test/test_resizer.xul
+++ b/layout/xul/base/test/test_resizer.xul
@@ -11,16 +11,17 @@ XUL <resizer> tests
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
SimpleTest.waitForExplicitFinish();
+ SimpleTest.ignoreAllUncaughtExceptions();
function openPopup()
{
document.getElementById("panel").
openPopupAtScreen(Math.round(window.mozInnerScreenX) + window.innerWidth - 130,
Math.round(window.mozInnerScreenY) + window.innerHeight - 130);
}
--- a/testing/mochitest/browser-test.js
+++ b/testing/mochitest/browser-test.js
@@ -466,16 +466,20 @@ function testScope(aTester, aTest) {
this.copyToProfile = function test_copyToProfile(filename) {
self.SimpleTest.copyToProfile(filename);
};
this.expectUncaughtException = function test_expectUncaughtException() {
self.SimpleTest.expectUncaughtException();
};
+ this.ignoreAllUncaughtExceptions = function test_ignoreAllUncaughtExceptions() {
+ self.SimpleTest.ignoreAllUncaughtExceptions();
+ };
+
this.finish = function test_finish() {
self.__done = true;
if (self.SimpleTest._expectingUncaughtException) {
self.ok(false, "expectUncaughtException was called but no uncaught exception was detected!");
}
if (self.__waitTimer) {
self.executeSoon(function() {
if (self.__done && self.__waitTimer) {
--- a/testing/mochitest/tests/SimpleTest/SimpleTest.js
+++ b/testing/mochitest/tests/SimpleTest/SimpleTest.js
@@ -10,34 +10,45 @@
*
* NOTE: Pay attention to cross-browser compatibility in this file. For
* instance, do not use const or JS > 1.5 features which are not yet
* implemented everywhere.
*
**/
var SimpleTest = { };
+var parentRunner = null;
+var isPrimaryTestWindow = !!parent.TestRunner;
-var parentRunner = null;
-if (parent) {
- parentRunner = parent.TestRunner;
- if (!parentRunner && parent.wrappedJSObject) {
- parentRunner = parent.wrappedJSObject.TestRunner;
+// Finds the TestRunner for this test run and the SpecialPowers object (in
+// case it is not defined) from a parent/opener window.
+//
+// Finding the SpecialPowers object is needed when we have ChromePowers in
+// harness.xul and we need SpecialPowers in the iframe, and also for tests
+// like test_focus.xul where we open a window which opens another window which
+// includes SimpleTest.js.
+(function() {
+ function ancestor(w) {
+ return w.parent != w ? w.parent : w.opener;
}
- // This is the case where we have ChromePowers in harness.xul and we need it in the iframe
- if (window.SpecialPowers == undefined && parent.SpecialPowers !== undefined) {
- window.SpecialPowers = parent.SpecialPowers;
+ var w = ancestor(window);
+ while (w && (!parentRunner || !window.SpecialPowers)) {
+ if (!parentRunner) {
+ parentRunner = w.TestRunner;
+ if (!parentRunner && w.wrappedJSObject) {
+ parentRunner = w.wrappedJSObject.TestRunner;
+ }
+ }
+ if (!window.SpecialPowers) {
+ window.SpecialPowers = w.SpecialPowers;
+ }
+ w = ancestor(w);
}
-}
-
-// Workaround test_focus.xul where we open a window which opens another window which includes SimpleTest.js
-if (window.SpecialPowers == undefined && window.opener && window.opener.SpecialPowers !== undefined) {
- window.SpecialPowers = window.opener.SpecialPowers;
-}
+})();
/* Helper functions pulled out of various MochiKit modules */
if (typeof(repr) == 'undefined') {
function repr(o) {
if (typeof(o) == "undefined") {
return "undefined";
} else if (o === null) {
return "null";
@@ -698,22 +709,32 @@ SimpleTest.expectChildProcessCrash = fun
/**
* Indicates to the test framework that the next uncaught exception during
* the test is expected, and should not cause a test failure.
*/
SimpleTest.expectUncaughtException = function () {
SimpleTest._expectingUncaughtException = true;
};
+/**
+ * Indicates to the test framework that all of the uncaught exceptions
+ * during the test are known problems that should be fixed in the future,
+ * but which should not cause the test to fail currently.
+ */
+SimpleTest.ignoreAllUncaughtExceptions = function () {
+ SimpleTest._ignoringAllUncaughtExceptions = true;
+};
-addLoadEvent(function() {
- if (SimpleTest._stopOnLoad) {
- SimpleTest.finish();
- }
-});
+if (isPrimaryTestWindow) {
+ addLoadEvent(function() {
+ if (SimpleTest._stopOnLoad) {
+ SimpleTest.finish();
+ }
+ });
+}
// --------------- Test.Builder/Test.More isDeeply() -----------------
SimpleTest.DNE = {dne: 'Does not exist'};
SimpleTest.LF = "\r\n";
SimpleTest._isRef = function (object) {
var type = typeof(object);
@@ -919,29 +940,28 @@ var isDeeply = SimpleTest.isDeeply;
var info = SimpleTest.info;
var gOldOnError = window.onerror;
window.onerror = function simpletestOnerror(errorMsg, url, lineNumber) {
var funcIdentifier = "[SimpleTest/SimpleTest.js, window.onerror]";
// Log the message.
// XXX Chrome mochitests sometimes trigger this window.onerror handler,
- // but there are a number of uncaught JS exceptions from those tests
- // currently, so we can't log them as errors just yet. For now, when
- // not in a plain mochitest, just dump it so that the error is visible but
- // doesn't cause a test failure. See bug 652494.
+ // but there are a number of uncaught JS exceptions from those tests.
+ // For now, for tests that self identify as having unintentional uncaught
+ // exceptions, just dump it so that the error is visible but doesn't cause
+ // a test failure. See bug 652494.
var message = "An error occurred: " + errorMsg + " at " + url + ":" + lineNumber;
var href = SpecialPowers.getPrivilegedProps(window, 'location.href');
- var isPlainMochitest = href.substring(0,7) != "chrome:";
var isExpected = !!SimpleTest._expectingUncaughtException;
- if (isPlainMochitest) {
+ if (!SimpleTest._ignoringAllUncaughtExceptions) {
SimpleTest.ok(isExpected, funcIdentifier, message);
SimpleTest._expectingUncaughtException = false;
} else {
- SimpleTest.info(funcIdentifier + " " + message);
+ SimpleTest.todo(false, funcIdentifier, message);
}
// There is no Components.stack.caller to log. (See bug 511888.)
// Call previous handler.
if (gOldOnError) {
try {
// Ignore return value: always run default handler.
gOldOnError(errorMsg, url, lineNumber);