Bug 1756407 - Make about:restartrequired tests more robust r=gsvelto

Differential Revision: https://phabricator.services.mozilla.com/D144953
This commit is contained in:
Alexandre Lissy 2022-04-29 13:44:12 +00:00
parent fb36ca3259
commit 68da11d927
10 changed files with 210 additions and 219 deletions

View File

@ -5,12 +5,6 @@ support-files =
file_contains_emptyiframe.html
file_iframe.html
[browser_aboutRestartRequired_basic.js]
skip-if =
!debug
[browser_aboutRestartRequired_buildid.js]
skip-if =
!debug
[browser_autoSubmitRequest.js]
[browser_launchFail.js]
[browser_multipleCrashedTabs.js]

View File

@ -0,0 +1,13 @@
[DEFAULT]
skip-if =
!debug || !e10s || !crashreporter
support-files =
head.js
prefs =
dom.ipc.processCount=1
dom.ipc.processPrelaunch.fission.number=0
[browser_aboutRestartRequired_basic.js]
[browser_aboutRestartRequired_buildid_false-positive.js]
[browser_aboutRestartRequired_buildid_mismatch.js]
[browser_aboutRestartRequired_buildid_no-platform-ini.js]

View File

@ -1,6 +1,11 @@
"use strict";
const kTimeout = 5 * 1000;
// On debug builds, crashing tabs results in much thinking, which
// slows down the test and results in intermittent test timeouts,
// so we'll pump up the expected timeout for this test.
requestLongerTimeout(5);
SimpleTest.expectChildProcessCrash();
add_task(async function test_browser_crashed_basic_event() {
info("Waiting for oop-browser-crashed event.");
@ -12,8 +17,9 @@ add_task(async function test_browser_crashed_basic_event() {
"Build ID mismatch false positive count should be undefined"
);
let eventPromise = getEventPromise("oop-browser-crashed", "basic", kTimeout);
await openNewTab(true);
await forceCleanProcesses();
let eventPromise = getEventPromise("oop-browser-crashed", "basic");
let tab = await openNewTab(true);
await eventPromise;
is(
@ -21,4 +27,5 @@ add_task(async function test_browser_crashed_basic_event() {
undefined,
"Build ID mismatch false positive count should be undefined"
);
await closeTab(tab);
});

View File

@ -1,184 +0,0 @@
"use strict";
const kTimeout = 60 * 1000;
// On debug builds, crashing tabs results in much thinking, which
// slows down the test and results in intermittent test timeouts,
// so we'll pump up the expected timeout for this test.
requestLongerTimeout(5);
async function waitForObserver(topic) {
return new Promise(function(resolve, reject) {
info("Setting up observer for '" + topic + "'");
let interval = undefined;
let obs = {
observe() {
info("Observed '" + topic + "'");
clearInterval(interval);
Services.obs.removeObserver(obs, topic);
resolve();
},
};
Services.obs.addObserver(obs, topic);
let times = 0;
let intervalMs = 1000;
interval = setInterval(async () => {
info("Opening and closing tab '" + topic + "'");
await openNewTab(false);
times += intervalMs;
if (times > kTimeout) {
clearInterval(interval);
reject();
}
}, intervalMs);
});
}
async function forceCleanProcesses() {
const origPrefValue = SpecialPowers.getBoolPref(
"dom.ipc.processPrelaunch.enabled"
);
info(
"forceCleanProcesses: get dom.ipc.processPrelaunch.enabled=" + origPrefValue
);
await SpecialPowers.setBoolPref("dom.ipc.processPrelaunch.enabled", false);
info("forceCleanProcesses: set dom.ipc.processPrelaunch.enabled=false");
await SpecialPowers.setBoolPref(
"dom.ipc.processPrelaunch.enabled",
origPrefValue
);
info(
"forceCleanProcesses: set dom.ipc.processPrelaunch.enabled=" + origPrefValue
);
const currPrefValue = SpecialPowers.getBoolPref(
"dom.ipc.processPrelaunch.enabled"
);
ok(currPrefValue === origPrefValue, "processPrelaunch properly re-enabled");
}
add_task(async function test_browser_crashed_false_positive_event() {
info("Waiting for oop-browser-crashed event.");
Services.telemetry.clearScalars();
is(
getFalsePositiveTelemetry(),
undefined,
"Build ID mismatch false positive count should be undefined"
);
try {
setBuildidMatchDontSendEnv();
await forceCleanProcesses();
let eventPromise = getEventPromise(
"oop-browser-crashed",
"false-positive",
kTimeout
);
await openNewTab(false);
await eventPromise;
} finally {
unsetBuildidMatchDontSendEnv();
}
is(
getFalsePositiveTelemetry(),
1,
"Build ID mismatch false positive count should be 1"
);
});
add_task(async function test_browser_restartrequired_event() {
info("Waiting for oop-browser-buildid-mismatch event.");
Services.telemetry.clearScalars();
is(
getFalsePositiveTelemetry(),
undefined,
"Build ID mismatch false positive count should be undefined"
);
let profD = Services.dirsvc.get("GreD", Ci.nsIFile);
let platformIniOrig = await IOUtils.readUTF8(
PathUtils.join(profD.path, "platform.ini")
);
let buildID = Services.appinfo.platformBuildID;
let platformIniNew = platformIniOrig.replace(buildID, "1234");
await IOUtils.writeUTF8(
PathUtils.join(profD.path, "platform.ini"),
platformIniNew
);
try {
setBuildidMatchDontSendEnv();
await forceCleanProcesses();
let eventPromise = getEventPromise(
"oop-browser-buildid-mismatch",
"buildid-mismatch",
kTimeout
);
await openNewTab(false);
await eventPromise;
} finally {
await IOUtils.writeUTF8(
PathUtils.join(profD.path, "platform.ini"),
platformIniOrig
);
unsetBuildidMatchDontSendEnv();
}
is(
getFalsePositiveTelemetry(),
undefined,
"Build ID mismatch false positive count should be undefined"
);
});
add_task(async function test_browser_crashed_no_platform_ini_event() {
info("Waiting for oop-browser-buildid-mismatch event.");
Services.telemetry.clearScalars();
is(
getFalsePositiveTelemetry(),
undefined,
"Build ID mismatch false positive count should be undefined"
);
let profD = Services.dirsvc.get("GreD", Ci.nsIFile);
let platformIniOrig = await IOUtils.readUTF8(
PathUtils.join(profD.path, "platform.ini")
);
await IOUtils.remove(PathUtils.join(profD.path, "platform.ini"));
try {
setBuildidMatchDontSendEnv();
await forceCleanProcesses();
let eventPromise = getEventPromise(
"oop-browser-buildid-mismatch",
"no-platform-ini",
kTimeout
);
await openNewTab(false);
await eventPromise;
} finally {
await IOUtils.writeUTF8(
PathUtils.join(profD.path, "platform.ini"),
platformIniOrig
);
unsetBuildidMatchDontSendEnv();
}
is(
getFalsePositiveTelemetry(),
undefined,
"Build ID mismatch false positive count should be undefined"
);
});

View File

@ -0,0 +1,35 @@
"use strict";
// On debug builds, crashing tabs results in much thinking, which
// slows down the test and results in intermittent test timeouts,
// so we'll pump up the expected timeout for this test.
requestLongerTimeout(2);
SimpleTest.expectChildProcessCrash();
add_task(async function test_browser_crashed_false_positive_event() {
info("Waiting for oop-browser-crashed event.");
Services.telemetry.clearScalars();
is(
getFalsePositiveTelemetry(),
undefined,
"Build ID mismatch false positive count should be undefined"
);
ok(await ensureBuildID(), "System has correct platform.ini");
setBuildidMatchDontSendEnv();
await forceCleanProcesses();
let eventPromise = getEventPromise("oop-browser-crashed", "false-positive");
let tab = await openNewTab(false);
await eventPromise;
unsetBuildidMatchDontSendEnv();
is(
getFalsePositiveTelemetry(),
1,
"Build ID mismatch false positive count should be 1"
);
await closeTab(tab);
});

View File

@ -0,0 +1,56 @@
"use strict";
// On debug builds, crashing tabs results in much thinking, which
// slows down the test and results in intermittent test timeouts,
// so we'll pump up the expected timeout for this test.
requestLongerTimeout(2);
SimpleTest.expectChildProcessCrash();
add_task(async function test_browser_restartrequired_event() {
info("Waiting for oop-browser-buildid-mismatch event.");
Services.telemetry.clearScalars();
is(
getFalsePositiveTelemetry(),
undefined,
"Build ID mismatch false positive count should be undefined"
);
ok(await ensureBuildID(), "System has correct platform.ini");
let profD = Services.dirsvc.get("GreD", Ci.nsIFile);
let platformIniOrig = await IOUtils.readUTF8(
PathUtils.join(profD.path, "platform.ini")
);
let buildID = Services.appinfo.platformBuildID;
let platformIniNew = platformIniOrig.replace(buildID, "1234");
await IOUtils.writeUTF8(
PathUtils.join(profD.path, "platform.ini"),
platformIniNew,
{ flush: true }
);
setBuildidMatchDontSendEnv();
await forceCleanProcesses();
let eventPromise = getEventPromise(
"oop-browser-buildid-mismatch",
"buildid-mismatch"
);
let tab = await openNewTab(false);
await eventPromise;
await IOUtils.writeUTF8(
PathUtils.join(profD.path, "platform.ini"),
platformIniOrig,
{ flush: true }
);
unsetBuildidMatchDontSendEnv();
is(
getFalsePositiveTelemetry(),
undefined,
"Build ID mismatch false positive count should be undefined"
);
await closeTab(tab);
});

View File

@ -0,0 +1,50 @@
"use strict";
// On debug builds, crashing tabs results in much thinking, which
// slows down the test and results in intermittent test timeouts,
// so we'll pump up the expected timeout for this test.
requestLongerTimeout(2);
SimpleTest.expectChildProcessCrash();
add_task(async function test_browser_crashed_no_platform_ini_event() {
info("Waiting for oop-browser-buildid-mismatch event.");
Services.telemetry.clearScalars();
is(
getFalsePositiveTelemetry(),
undefined,
"Build ID mismatch false positive count should be undefined"
);
ok(await ensureBuildID(), "System has correct platform.ini");
let profD = Services.dirsvc.get("GreD", Ci.nsIFile);
let platformIniOrig = await IOUtils.readUTF8(
PathUtils.join(profD.path, "platform.ini")
);
await IOUtils.remove(PathUtils.join(profD.path, "platform.ini"));
setBuildidMatchDontSendEnv();
await forceCleanProcesses();
let eventPromise = getEventPromise(
"oop-browser-buildid-mismatch",
"no-platform-ini"
);
let tab = await openNewTab(false);
await eventPromise;
await IOUtils.writeUTF8(
PathUtils.join(profD.path, "platform.ini"),
platformIniOrig,
{ flush: true }
);
unsetBuildidMatchDontSendEnv();
is(
getFalsePositiveTelemetry(),
undefined,
"Build ID mismatch false positive count should be undefined"
);
await closeTab(tab);
});

View File

@ -146,42 +146,26 @@ function prepareNoDump() {
}
const kBuildidMatchEnv = "MOZ_BUILDID_MATCH_DONTSEND";
const envService = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
function setBuildidMatchDontSendEnv() {
const envService = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
info("Setting " + kBuildidMatchEnv + "=1");
envService.set(kBuildidMatchEnv, "1");
info("Set " + kBuildidMatchEnv + "=1");
}
function unsetBuildidMatchDontSendEnv() {
const envService = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
info("Setting " + kBuildidMatchEnv + "=0");
envService.set(kBuildidMatchEnv, "0");
info("Set " + kBuildidMatchEnv + "=0");
}
function getEventPromise(eventName, eventKind, kTimeout) {
function getEventPromise(eventName, eventKind) {
return new Promise(function(resolve, reject) {
/* eslint-disable mozilla/no-arbitrary-setTimeout */
let maybeTimeout = setTimeout(() => {
ok(
false,
"Timed out waiting " + eventName + " (" + eventKind + ") event"
);
reject();
}, kTimeout);
info("Installing event listener (" + eventKind + ")");
window.addEventListener(
eventName,
event => {
info("Clear timeout for " + eventKind + " event");
clearTimeout(maybeTimeout);
ok(true, "Received " + eventName + " (" + eventKind + ") event");
info("Call resolve() for " + eventKind + " event");
resolve();
@ -192,6 +176,15 @@ function getEventPromise(eventName, eventKind, kTimeout) {
});
}
async function ensureBuildID() {
let profD = Services.dirsvc.get("GreD", Ci.nsIFile);
let platformIniOrig = await IOUtils.readUTF8(
PathUtils.join(profD.path, "platform.ini")
);
let buildID = Services.appinfo.platformBuildID;
return platformIniOrig.indexOf(buildID) > 0;
}
async function openNewTab(forceCrash) {
const PAGE =
"data:text/html,<html><body>A%20regular,%20everyday,%20normal%20page.";
@ -205,14 +198,21 @@ async function openNewTab(forceCrash) {
};
let tab = await BrowserTestUtils.openNewForegroundTab(options);
if (forceCrash === true) {
let browser = tab.linkedBrowser;
await BrowserTestUtils.crashFrame(browser, true, true, null);
await BrowserTestUtils.crashFrame(
browser,
/* shouldShowTabCrashPage */ false,
/* shouldClearMinidumps */ true,
/* BrowsingContext */ null
);
}
// Since we crashed early, we expect to have some about:blank
// Remove it to clean up
return tab;
}
async function closeTab(tab) {
await TestUtils.waitForTick();
BrowserTestUtils.removeTab(tab);
}
@ -220,3 +220,24 @@ function getFalsePositiveTelemetry() {
const scalars = TelemetryTestUtils.getProcessScalars("parent");
return scalars["dom.contentprocess.buildID_mismatch_false_positive"];
}
// The logic bound to dom.ipc.processPrelaunch.enabled will react to value
// changes: https://searchfox.org/mozilla-central/rev/ecd91b104714a8b2584a4c03175be50ccb3a7c67/dom/ipc/PreallocatedProcessManager.cpp#171-195
// So we force flip to ensure we have no dangling process.
async function forceCleanProcesses() {
const origPrefValue = SpecialPowers.getBoolPref(
"dom.ipc.processPrelaunch.enabled"
);
await SpecialPowers.setBoolPref(
"dom.ipc.processPrelaunch.enabled",
!origPrefValue
);
await SpecialPowers.setBoolPref(
"dom.ipc.processPrelaunch.enabled",
origPrefValue
);
const currPrefValue = SpecialPowers.getBoolPref(
"dom.ipc.processPrelaunch.enabled"
);
ok(currPrefValue === origPrefValue, "processPrelaunch properly re-enabled");
}

View File

@ -56,6 +56,7 @@ BROWSER_CHROME_MANIFESTS += [
"content/test/statuspanel/browser.ini",
"content/test/sync/browser.ini",
"content/test/tabcrashed/browser.ini",
"content/test/tabcrashed/browser_aboutRestartRequired.ini",
"content/test/tabdialogs/browser.ini",
"content/test/tabMediaIndicator/browser.ini",
"content/test/tabPrompts/browser.ini",

View File

@ -873,8 +873,6 @@ bool MessageChannel::SendBuildIDsMatchMessage(const char* aParentBuildID) {
// tooling to avoid intermittent missing leakcheck
NoteIntentionalCrash(XRE_GetProcessTypeString());
if (XRE_IsContentProcess()) {
// Make sure we do not die too early, as this causes weird behavior
PR_Sleep(PR_MillisecondsToInterval(1000));
return false;
}
}