forked from mirrors/gecko-dev
CLOSED TREE Backed out changeset bf7f73fd1921 (bug 1726804) Backed out changeset c9936f7534cb (bug 1726804)
220 lines
6.8 KiB
JavaScript
220 lines
6.8 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
ChromeUtils.import("resource://gre/modules/osfile.jsm", this);
|
|
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
|
ChromeUtils.import("resource://testing-common/AppData.jsm", this);
|
|
ChromeUtils.import("resource://testing-common/CrashManagerTest.jsm", this);
|
|
var bsp = ChromeUtils.import("resource://gre/modules/CrashManager.jsm", null);
|
|
|
|
add_task(async function test_instantiation() {
|
|
Assert.ok(
|
|
!bsp.gCrashManager,
|
|
"CrashManager global instance not initially defined."
|
|
);
|
|
|
|
do_get_profile();
|
|
await makeFakeAppDir();
|
|
|
|
// Fake profile creation.
|
|
Cc["@mozilla.org/crashservice;1"]
|
|
.getService(Ci.nsIObserver)
|
|
.observe(null, "profile-after-change", null);
|
|
|
|
Assert.ok(bsp.gCrashManager, "Profile creation makes it available.");
|
|
Assert.ok(Services.crashmanager, "CrashManager available via Services.");
|
|
Assert.strictEqual(
|
|
bsp.gCrashManager,
|
|
Services.crashmanager,
|
|
"The objects are the same."
|
|
);
|
|
});
|
|
|
|
var gMinidumpDir = do_get_tempdir();
|
|
var gCrashReporter = Cc["@mozilla.org/toolkit/crash-reporter;1"].getService(
|
|
Ci.nsICrashReporter
|
|
);
|
|
|
|
// Ensure that the nsICrashReporter methods can find the dump
|
|
gCrashReporter.minidumpPath = gMinidumpDir;
|
|
|
|
var gDumpFile;
|
|
var gExtraFile;
|
|
|
|
// Sets up a fake crash dump and sets up the crashreporter so that it will be
|
|
// able to find it.
|
|
async function setup(crashId) {
|
|
let cwd = await OS.File.getCurrentDirectory();
|
|
let minidump = OS.Path.join(cwd, "crash.dmp");
|
|
let extra = OS.Path.join(cwd, "crash.extra");
|
|
|
|
// Make a copy of the files because the .extra file will be modified
|
|
gDumpFile = OS.Path.join(gMinidumpDir.path, crashId + ".dmp");
|
|
await OS.File.copy(minidump, gDumpFile);
|
|
gExtraFile = OS.Path.join(gMinidumpDir.path, crashId + ".extra");
|
|
await OS.File.copy(extra, gExtraFile);
|
|
}
|
|
|
|
// Cleans up the fake crash dump and resets the minidump path
|
|
async function teardown() {
|
|
await OS.File.remove(gDumpFile);
|
|
await OS.File.remove(gExtraFile);
|
|
}
|
|
|
|
async function addCrash(id, type = Ci.nsICrashService.CRASH_TYPE_CRASH) {
|
|
let cs = Cc["@mozilla.org/crashservice;1"].getService(Ci.nsICrashService);
|
|
return cs.addCrash(Ci.nsICrashService.PROCESS_TYPE_CONTENT, type, id);
|
|
}
|
|
|
|
async function getCrash(crashId) {
|
|
let crashes = await Services.crashmanager.getCrashes();
|
|
return crashes.find(c => {
|
|
return c.id === crashId;
|
|
});
|
|
}
|
|
|
|
async function test_addCrashBase(crashId, allThreads) {
|
|
await setup(crashId);
|
|
|
|
let crashType = Ci.nsICrashService.CRASH_TYPE_CRASH;
|
|
if (allThreads) {
|
|
crashType = Ci.nsICrashService.CRASH_TYPE_HANG;
|
|
}
|
|
await addCrash(crashId, crashType);
|
|
let crash = await getCrash(crashId);
|
|
Assert.ok(crash, "Crash " + crashId + " has been stored successfully.");
|
|
Assert.equal(crash.metadata.ProcessType, "content");
|
|
Assert.equal(
|
|
crash.metadata.MinidumpSha256Hash,
|
|
"c8ad56a2096310f40c8a4b46c890625a740fdd72e409f412933011ff947c5a40"
|
|
);
|
|
Assert.ok(crash.metadata.StackTraces, "The StackTraces field is present.\n");
|
|
|
|
try {
|
|
let stackTraces = crash.metadata.StackTraces;
|
|
Assert.equal(stackTraces.status, "OK");
|
|
Assert.ok(stackTraces.crash_info, "The crash_info field is populated.");
|
|
Assert.ok(
|
|
stackTraces.modules && !!stackTraces.modules.length,
|
|
"The module list is populated."
|
|
);
|
|
Assert.ok(
|
|
stackTraces.threads && !!stackTraces.threads.length,
|
|
"The thread list is populated."
|
|
);
|
|
|
|
if (allThreads) {
|
|
Assert.ok(
|
|
stackTraces.threads.length > 1,
|
|
"The stack trace contains more than one thread."
|
|
);
|
|
} else {
|
|
Assert.ok(
|
|
stackTraces.threads.length == 1,
|
|
"The stack trace contains exactly one thread."
|
|
);
|
|
}
|
|
|
|
let frames = stackTraces.threads[0].frames;
|
|
Assert.ok(frames && !!frames.length, "The stack trace is present.\n");
|
|
} catch (e) {
|
|
Assert.ok(false, "StackTraces does not contain valid JSON.");
|
|
}
|
|
|
|
try {
|
|
let telemetryEnvironment = JSON.parse(crash.metadata.TelemetryEnvironment);
|
|
Assert.equal(telemetryEnvironment.EscapedField, "EscapedData\n\nfoo");
|
|
} catch (e) {
|
|
Assert.ok(
|
|
false,
|
|
"TelemetryEnvironment contents were not properly escaped\n"
|
|
);
|
|
}
|
|
|
|
await teardown();
|
|
}
|
|
|
|
add_task(async function test_addCrash() {
|
|
await test_addCrashBase("56cd87bc-bb26-339b-3a8e-f00c0f11380e", false);
|
|
});
|
|
|
|
add_task(async function test_addCrashAllThreads() {
|
|
await test_addCrashBase("071843c4-da89-4447-af9f-965163e0b253", true);
|
|
});
|
|
|
|
add_task(async function test_addCrash_shutdownOnCrash() {
|
|
const crashId = "de7f63dd-7516-4525-a44b-6d2f2bd3934a";
|
|
await setup(crashId);
|
|
|
|
// Set the MOZ_CRASHREPORTER_SHUTDOWN environment variable
|
|
let env = Cc["@mozilla.org/process/environment;1"].getService(
|
|
Ci.nsIEnvironment
|
|
);
|
|
env.set("MOZ_CRASHREPORTER_SHUTDOWN", "1");
|
|
|
|
await addCrash(crashId);
|
|
|
|
let crash = await getCrash(crashId);
|
|
Assert.ok(crash, "Crash " + crashId + " has been stored successfully.");
|
|
Assert.ok(
|
|
crash.metadata.StackTraces === undefined,
|
|
"The StackTraces field is not present because the minidump " +
|
|
"analyzer did not start.\n"
|
|
);
|
|
|
|
env.set("MOZ_CRASHREPORTER_SHUTDOWN", ""); // Unset the environment variable
|
|
await teardown();
|
|
});
|
|
|
|
add_task(async function test_addCrash_quitting() {
|
|
const firstCrashId = "0e578a74-a887-48cb-b270-d4775d01e715";
|
|
const secondCrashId = "208379e5-1979-430d-a066-f6e57a8130ce";
|
|
|
|
await setup(firstCrashId);
|
|
|
|
let minidumpAnalyzerKilledPromise = new Promise((resolve, reject) => {
|
|
Services.obs.addObserver((subject, topic, data) => {
|
|
if (topic === "test-minidump-analyzer-killed") {
|
|
resolve();
|
|
}
|
|
|
|
reject();
|
|
}, "test-minidump-analyzer-killed");
|
|
});
|
|
|
|
let addCrashPromise = addCrash(firstCrashId);
|
|
|
|
// Spin the event loop so that the minidump analyzer is launched
|
|
await new Promise(resolve => {
|
|
executeSoon(resolve);
|
|
});
|
|
|
|
// Pretend we're quitting
|
|
let cs = Cc["@mozilla.org/crashservice;1"].getService(Ci.nsICrashService);
|
|
let obs = cs.QueryInterface(Ci.nsIObserver);
|
|
obs.observe(null, "quit-application", null);
|
|
|
|
// Wait for the minidump analyzer to be killed
|
|
await minidumpAnalyzerKilledPromise;
|
|
|
|
// Now wait for the crash to be recorded
|
|
await addCrashPromise;
|
|
let crash = await getCrash(firstCrashId);
|
|
Assert.ok(crash, "Crash " + firstCrashId + " has been stored successfully.");
|
|
|
|
// Cleanup the fake crash and generate a new one
|
|
await teardown();
|
|
await setup(secondCrashId);
|
|
|
|
await addCrash(secondCrashId);
|
|
crash = await getCrash(secondCrashId);
|
|
Assert.ok(crash, "Crash " + secondCrashId + " has been stored successfully.");
|
|
Assert.ok(
|
|
crash.metadata.StackTraces === undefined,
|
|
"The StackTraces field is not present because the minidump " +
|
|
"analyzer did not start.\n"
|
|
);
|
|
await teardown();
|
|
});
|