bug 620974 - Add Breakpad processor code to binary test component to allow testing minidump contents. r=bsmedberg a=testonly

--HG--
extra : rebase_source : ba728fe297e9ce066438719b839e07deb38b1dd5
This commit is contained in:
Ted Mielczarek 2011-01-12 14:14:15 -05:00
Родитель 56ef035383
Коммит e69644724e
15 изменённых файлов: 134 добавлений и 108 удалений

Просмотреть файл

@ -129,8 +129,6 @@ _MOCHICHROME_FILES += \
$(NULL)
endif
# Temporarily disable the tests on Linux, see bug 573290 and bug 583591.
ifneq ($(OS_ARCH),Linux)
ifdef MOZ_CRASHREPORTER
_MOCHICHROME_FILES += \
test_crash_notify.xul \
@ -138,7 +136,6 @@ _MOCHICHROME_FILES += \
test_crash_submit.xul \
$(NULL)
endif
endif
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
_MOCHICHROME_FILES += \

Просмотреть файл

@ -122,10 +122,7 @@ EXTRA_JS_MODULES = \
$(NULL)
ifdef ENABLE_TESTS
# Temporarily disable the tests on Linux, see bug 573290 and bug 583591
ifneq ($(OS_ARCH),Linux)
TOOL_DIRS = test
endif
endif
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,42 @@
var EXPORTED_SYMBOLS = ["CrashTestUtils"];
let CrashTestUtils = {
// These will be defined using ctypes APIs below.
crash: null,
lockDir: null,
dumpHasStream: null,
// Constants for crash()
// Keep these in sync with nsTestCrasher.cpp!
CRASH_INVALID_POINTER_DEREF: 0,
CRASH_PURE_VIRTUAL_CALL: 1,
CRASH_RUNTIMEABORT: 2,
// Constants for dumpHasStream()
// From google_breakpad/common/minidump_format.h
MD_THREAD_LIST_STREAM: 3,
MD_MEMORY_INFO_LIST_STREAM: 16
};
// Grab APIs from the testcrasher shared library
Components.utils.import("resource://gre/modules/ctypes.jsm");
let dir = __LOCATION__.parent;
let file = dir.clone();
file.append(ctypes.libraryName("testcrasher"));
let lib = ctypes.open(file.path);
CrashTestUtils.crash = lib.declare("Crash",
ctypes.default_abi,
ctypes.void_t,
ctypes.int16_t);
CrashTestUtils.lockDir = lib.declare("LockDir",
ctypes.default_abi,
ctypes.voidptr_t, // nsILocalFile*
ctypes.voidptr_t); // nsISupports*
CrashTestUtils.dumpHasStream = lib.declare("DumpHasStream",
ctypes.default_abi,
ctypes.bool,
ctypes.char.ptr,
ctypes.uint32_t);

Просмотреть файл

@ -47,16 +47,26 @@ MODULE = crashreporter_test
XPCSHELL_TESTS = unit
LIBRARY_NAME = testcrasher
IS_COMPONENT = 1
NO_DIST_INSTALL = 1
XPIDLSRCS = nsITestCrasher.idl
VPATH += \
$(srcdir)/../google-breakpad/src/processor/ \
$(srcdir)/../google-breakpad/src/common/ \
$(NULL)
CPPSRCS = \
nsTestCrasher.cpp \
dumputils.cpp \
basic_code_modules.cc \
logging.cc \
minidump.cc \
pathname_stripper.cc \
$(NULL)
LOCAL_INCLUDES += -I$(XPIDL_GEN_DIR)
LOCAL_INCLUDES += \
-I$(XPIDL_GEN_DIR) \
-I$(srcdir)/../google-breakpad/src/ \
$(NULL)
EXTRA_DSO_LIBS += xpcom
EXTRA_DSO_LDOPTS += $(LIBS_DIR) $(MOZ_COMPONENT_LIBS)
@ -76,11 +86,11 @@ EXTRA_DSO_LDOPTS += $(EXTRA_DSO_LIBS) $(XPCOM_LIBS)
endif
EXTRA_PP_COMPONENTS = testcrasher.manifest
EXTRA_JS_MODULES = CrashTestUtils.jsm
include $(topsrcdir)/config/rules.mk
DEFINES += -DSHARED_LIBRARY=$(SHARED_LIBRARY)
DEFINES += -DSHARED_LIBRARY=$(SHARED_LIBRARY) -DNOMINMAX
ifneq (mobile,$(MOZ_BUILD_APP))
_BROWSER_FILES = \
@ -95,7 +105,6 @@ libs:: $(_BROWSER_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)/browser
endif
libs:: $(SHARED_LIBRARY) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt
$(NSINSTALL) -D $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/components
$(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/components
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $(srcdir)/testcrasher.manifest > $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/components/testcrasher.manifest
libs:: $(SHARED_LIBRARY) $(EXTRA_JS_MODULES)
$(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/

Просмотреть файл

@ -0,0 +1,19 @@
#include "google_breakpad/processor/minidump.h"
#include "nscore.h"
using namespace google_breakpad;
extern "C"
NS_EXPORT bool
DumpHasStream(const char* dump_file, u_int32_t stream_type)
{
Minidump dump(dump_file);
if (!dump.Read())
return false;
u_int32_t length;
if (!dump.SeekToStreamType(stream_type, &length) || length == 0)
return false;
return true;
}

Просмотреть файл

@ -1,21 +0,0 @@
#include "nsISupports.idl"
interface nsILocalFile;
[scriptable, uuid(95464a04-6949-46cb-b621-d167790704a0)]
interface nsITestCrasher : nsISupports
{
void crash(in short how);
/**
* Lock a directory using XRE_LockProfileDirectory.
*
* @param directory The directory to lock
* @return An opaque lock object.
*/
nsISupports lockDir(in nsILocalFile directory);
const short CRASH_INVALID_POINTER_DEREF = 0;
const short CRASH_PURE_VIRTUAL_CALL = 1;
const short CRASH_RUNTIMEABORT = 2;
};

Просмотреть файл

@ -1,23 +1,5 @@
#include "nsServiceManagerUtils.h"
#include "nsIComponentManager.h"
#include "nsITestCrasher.h"
#include "nscore.h"
#include "nsXULAppAPI.h"
#include "mozilla/ModuleUtils.h"
class nsTestCrasher : public nsITestCrasher
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSITESTCRASHER
nsTestCrasher() {}
private:
~nsTestCrasher() {};
};
NS_IMPL_ISUPPORTS1(nsTestCrasher, nsITestCrasher)
/*
* This pure virtual call example is from MSDN
@ -49,59 +31,39 @@ void PureVirtualCall()
B b;
}
/* void crash (); */
NS_IMETHODIMP nsTestCrasher::Crash(PRInt16 how)
// Keep these in sync with CrashTestUtils.jsm!
const PRInt16 CRASH_INVALID_POINTER_DEREF = 0;
const PRInt16 CRASH_PURE_VIRTUAL_CALL = 1;
const PRInt16 CRASH_RUNTIMEABORT = 2;
extern "C" NS_EXPORT
void Crash(PRInt16 how)
{
switch (how) {
case nsITestCrasher::CRASH_INVALID_POINTER_DEREF: {
case CRASH_INVALID_POINTER_DEREF: {
volatile int* foo = (int*)0x42;
*foo = 0;
// not reached
break;
}
case nsITestCrasher::CRASH_PURE_VIRTUAL_CALL: {
case CRASH_PURE_VIRTUAL_CALL: {
PureVirtualCall();
// not reached
break;
}
case nsITestCrasher::CRASH_RUNTIMEABORT: {
case CRASH_RUNTIMEABORT: {
NS_RUNTIMEABORT("Intentional crash");
break;
}
default:
return NS_ERROR_INVALID_ARG;
break;
}
return NS_OK;
}
/* nsISupports LockDir (in nsILocalFile directory); */
NS_IMETHODIMP nsTestCrasher::LockDir(nsILocalFile *directory,
nsISupports **_retval NS_OUTPARAM)
extern "C" NS_EXPORT
nsISupports* LockDir(nsILocalFile *directory)
{
return XRE_LockProfileDirectory(directory, _retval);
nsISupports* lockfile = nsnull;
XRE_LockProfileDirectory(directory, &lockfile);
return lockfile;
}
// 54afce51-38d7-4df0-9750-2f90f9ffbca2
#define NS_TESTCRASHER_CID \
{ 0x54afce51, 0x38d7, 0x4df0, {0x97, 0x50, 0x2f, 0x90, 0xf9, 0xff, 0xbc, 0xa2} }
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTestCrasher)
NS_DEFINE_NAMED_CID(NS_TESTCRASHER_CID);
static const mozilla::Module::CIDEntry kTestCrasherCIDs[] = {
{ &kNS_TESTCRASHER_CID, false, NULL, nsTestCrasherConstructor },
{ NULL }
};
static const mozilla::Module::ContractIDEntry kTestCrasherContracts[] = {
{ "@mozilla.org/testcrasher;1", &kNS_TESTCRASHER_CID },
{ NULL }
};
static const mozilla::Module kTestCrasherModule = {
mozilla::Module::kVersion,
kTestCrasherCIDs,
kTestCrasherContracts
};
NSMODULE_DEFN(nsTestCrasherModule) = &kTestCrasherModule;

Просмотреть файл

@ -1,3 +0,0 @@
#filter substitution
binary-component @SHARED_LIBRARY@
interfaces crashreporter_test.xpt

Просмотреть файл

@ -7,9 +7,12 @@ let crashReporter =
.getService(Components.interfaces.nsICrashReporter);
crashReporter.enabled = true;
crashReporter.minidumpPath = cwd;
let cd = cwd.clone();
cd.append("components");
cd.append("testcrasher.manifest");
Components.manager instanceof Components.interfaces.nsIComponentRegistrar;
Components.manager.autoRegister(cd);
let crashType = Components.interfaces.nsITestCrasher.CRASH_INVALID_POINTER_DEREF;
let ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
let protocolHandler = ios.getProtocolHandler("resource")
.QueryInterface(Components.interfaces.nsIResProtocolHandler);
let curDirURI = ios.newFileURI(cwd);
protocolHandler.setSubstitution("test", curDirURI);
Components.utils.import("resource://test/CrashTestUtils.jsm");
let crashType = CrashTestUtils.CRASH_INVALID_POINTER_DEREF;

Просмотреть файл

@ -1,3 +1,2 @@
// now actually crash
let crasher = Components.classes["@mozilla.org/testcrasher;1"].createInstance(Components.interfaces.nsITestCrasher);
crasher.crash(crashType);
CrashTestUtils.crash(crashType);

Просмотреть файл

@ -22,7 +22,7 @@
* @param canReturnZero
* If true, the subprocess may return with a zero exit code.
* Certain types of crashes may not cause the process to
* exit with an error.
* exit with an error.
*/
function do_crash(setup, callback, canReturnZero)
{
@ -81,6 +81,14 @@ function do_crash(setup, callback, canReturnZero)
let extrafile = minidump.clone();
extrafile.leafName = extrafile.leafName.slice(0, -4) + ".extra";
// Just in case, don't let these files linger.
do_register_cleanup(function() {
if (minidump.exists())
minidump.remove(false);
if (extrafile.exists())
extrafile.remove(false);
});
do_check_true(extrafile.exists());
let extra = parseKeyValuePairsFromFile(extrafile);
@ -129,3 +137,6 @@ function parseKeyValuePairsFromFile(file) {
fstream.close();
return parseKeyValuePairs(contents);
}
// Import binary APIs via js-ctypes.
Components.utils.import("resource://test/CrashTestUtils.jsm");

Просмотреть файл

@ -13,7 +13,7 @@ function run_test()
// Try crashing with a pure virtual call
do_crash(function() {
crashType = Components.interfaces.nsITestCrasher.CRASH_PURE_VIRTUAL_CALL;
crashType = CrashTestUtils.CRASH_PURE_VIRTUAL_CALL;
crashReporter.annotateCrashReport("TestKey", "TestValue");
},
function(mdump, extra) {

Просмотреть файл

@ -1,13 +1,13 @@
function run_test()
{
if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) {
dump("INFO | test_crash_purevirtual.js | Can't test crashreporter in a non-libxul build.\n");
dump("INFO | test_crash_runtimeabort.js | Can't test crashreporter in a non-libxul build.\n");
return;
}
// Try crashing with a runtime abort
do_crash(function() {
crashType = Components.interfaces.nsITestCrasher.CRASH_RUNTIMEABORT;
crashType = CrashTestUtils.CRASH_RUNTIMEABORT;
crashReporter.annotateCrashReport("TestKey", "TestValue");
},
function(mdump, extra) {

Просмотреть файл

@ -5,12 +5,24 @@ function run_test()
return;
}
var is_win7_or_newer = false;
var ph = Components.classes["@mozilla.org/network/protocol;1?name=http"]
.getService(Components.interfaces.nsIHttpProtocolHandler);
var match = ph.userAgent.match(/Windows NT (\d+).(\d+)/);
if (match && (parseInt(match[1]) > 6 ||
parseInt(match[1]) == 6 && parseInt(match[2]) >= 1)) {
is_win7_or_newer = true;
}
// try a basic crash
do_crash(null, function(mdump, extra) {
do_check_true(mdump.exists());
do_check_true(mdump.fileSize > 0);
do_check_true('StartupTime' in extra);
do_check_true('CrashTime' in extra);
do_check_true(CrashTestUtils.dumpHasStream(mdump.path, CrashTestUtils.MD_THREAD_LIST_STREAM));
if (is_win7_or_newer)
do_check_true(CrashTestUtils.dumpHasStream(mdump.path, CrashTestUtils.MD_MEMORY_INFO_LIST_STREAM));
});
// check setting some basic data

Просмотреть файл

@ -16,8 +16,7 @@ function run_test()
let dir = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
dir.initWithPath(profd);
let mycrasher = Components.classes["@mozilla.org/testcrasher;1"].createInstance(Components.interfaces.nsITestCrasher);
let lock = mycrasher.lockDir(dir);
let lock = CrashTestUtils.lockDir(dir);
// when we crash, the lock file should be cleaned up
},
function(mdump, extra) {