mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-08-04 04:21:14 +00:00
Support custom URL parameters. Added unit tests for Breakpad. Added
a way to specify server parameters in app plist file, as well. R=stuartmorgan, jeremy A=nealsid git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@346 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
1a997295b6
commit
2eb356a68d
|
@ -30,6 +30,8 @@
|
|||
33880C800F9E097100817F82 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 33880C7E0F9E097100817F82 /* InfoPlist.strings */; };
|
||||
4084699D0F5D9CF900FDCA37 /* crash_report_sender.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4084699C0F5D9CF900FDCA37 /* crash_report_sender.icns */; };
|
||||
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
|
||||
F91AF5D00FD60393009D8BE2 /* BreakpadFramework_Test.mm in Sources */ = {isa = PBXBuildFile; fileRef = F91AF5CF0FD60393009D8BE2 /* BreakpadFramework_Test.mm */; };
|
||||
F91AF6210FD60784009D8BE2 /* Breakpad.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Breakpad.framework */; };
|
||||
F9286B3A0F7EB25800A4DCC8 /* InspectorMain.mm in Sources */ = {isa = PBXBuildFile; fileRef = F9286B390F7EB25800A4DCC8 /* InspectorMain.mm */; };
|
||||
F92C53B80ECCE7B3009BE4BA /* Inspector.mm in Sources */ = {isa = PBXBuildFile; fileRef = F92C53B70ECCE7B3009BE4BA /* Inspector.mm */; };
|
||||
F92C554C0ECCF534009BE4BA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; };
|
||||
|
@ -105,6 +107,13 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
F91AF6370FD60A74009D8BE2 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
|
||||
remoteInfo = Breakpad;
|
||||
};
|
||||
F92C564D0ECD10E5009BE4BA /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
|
||||
|
@ -133,13 +142,6 @@
|
|||
remoteGlobalIDString = F93803BD0F80820F004D428B;
|
||||
remoteInfo = generator_test;
|
||||
};
|
||||
F93DE2FD0F82C3C900608B94 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F93DE2D00F82A67300608B94;
|
||||
remoteInfo = minidump_file_writer_unittest;
|
||||
};
|
||||
F93DE36F0F82CC1300608B94 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
|
||||
|
@ -228,6 +230,7 @@
|
|||
33880C7F0F9E097100817F82 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = sender/English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
4084699C0F5D9CF900FDCA37 /* crash_report_sender.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = crash_report_sender.icns; path = sender/crash_report_sender.icns; sourceTree = "<group>"; };
|
||||
8DC2EF5B0486A6940098B216 /* Breakpad.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Breakpad.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F91AF5CF0FD60393009D8BE2 /* BreakpadFramework_Test.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = BreakpadFramework_Test.mm; path = tests/BreakpadFramework_Test.mm; sourceTree = "<group>"; };
|
||||
F9286B380F7EB25800A4DCC8 /* Inspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Inspector.h; path = crash_generation/Inspector.h; sourceTree = "<group>"; };
|
||||
F9286B390F7EB25800A4DCC8 /* InspectorMain.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = InspectorMain.mm; path = crash_generation/InspectorMain.mm; sourceTree = "<group>"; };
|
||||
F92C53540ECCE349009BE4BA /* Inspector */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Inspector; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -375,6 +378,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F91AF6210FD60784009D8BE2 /* Breakpad.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -564,6 +568,7 @@
|
|||
children = (
|
||||
F9C77DE00F7DD7E30045F7DB /* SimpleStringDictionaryTest.h */,
|
||||
F9C77DE10F7DD7E30045F7DB /* SimpleStringDictionaryTest.mm */,
|
||||
F91AF5CF0FD60393009D8BE2 /* BreakpadFramework_Test.mm */,
|
||||
);
|
||||
name = tests;
|
||||
sourceTree = "<group>";
|
||||
|
@ -754,8 +759,8 @@
|
|||
);
|
||||
dependencies = (
|
||||
F93DE2FC0F82C3C600608B94 /* PBXTargetDependency */,
|
||||
F93DE2FE0F82C3C900608B94 /* PBXTargetDependency */,
|
||||
F93DE3700F82CC1300608B94 /* PBXTargetDependency */,
|
||||
F91AF6380FD60A74009D8BE2 /* PBXTargetDependency */,
|
||||
);
|
||||
name = UnitTests;
|
||||
productName = UnitTests;
|
||||
|
@ -871,7 +876,7 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n\necho running minidump generator tests...\n\"${BUILT_PRODUCTS_DIR}/generator_test\"\necho Running minidump file writer tests...\n\"${BUILT_PRODUCTS_DIR}/minidump_file_writer_unittest\"\necho Running exception handler tests...\n\"${BUILT_PRODUCTS_DIR}/handler_test\"\n";
|
||||
shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n\necho running minidump generator tests...\n\"${BUILT_PRODUCTS_DIR}/generator_test\"\necho Running exception handler tests...\n\"${BUILT_PRODUCTS_DIR}/handler_test\"\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
|
@ -991,12 +996,18 @@
|
|||
F9C77DE40F7DD82F0045F7DB /* SimpleStringDictionary.mm in Sources */,
|
||||
F9C77DE20F7DD7E30045F7DB /* SimpleStringDictionaryTest.mm in Sources */,
|
||||
F9C77E130F7DDF810045F7DB /* GTMSenTestCase.m in Sources */,
|
||||
F91AF5D00FD60393009D8BE2 /* BreakpadFramework_Test.mm in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
F91AF6380FD60A74009D8BE2 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 8DC2EF4F0486A6940098B216 /* Breakpad */;
|
||||
targetProxy = F91AF6370FD60A74009D8BE2 /* PBXContainerItemProxy */;
|
||||
};
|
||||
F92C564E0ECD10E5009BE4BA /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = F92C563B0ECD10B3009BE4BA /* breakpadUtilities */;
|
||||
|
@ -1017,11 +1028,6 @@
|
|||
target = F93803BD0F80820F004D428B /* generator_test */;
|
||||
targetProxy = F93DE2FB0F82C3C600608B94 /* PBXContainerItemProxy */;
|
||||
};
|
||||
F93DE2FE0F82C3C900608B94 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = F93DE2D00F82A67300608B94 /* minidump_file_writer_unittest */;
|
||||
targetProxy = F93DE2FD0F82C3C900608B94 /* PBXContainerItemProxy */;
|
||||
};
|
||||
F93DE3700F82CC1300608B94 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = F93DE32B0F82C55600608B94 /* handler_test */;
|
||||
|
|
|
@ -81,15 +81,15 @@ extern "C" {
|
|||
#define BREAKPAD_REQUEST_EMAIL "BreakpadRequestEmail"
|
||||
#define BREAKPAD_EMAIL "BreakpadEmail"
|
||||
#define BREAKPAD_SERVER_TYPE "BreakpadServerType"
|
||||
// TODO(nealsid) find a better way to support server-specific
|
||||
// parameters without having to rebuild Breakpad
|
||||
#define BREAKPAD_BUILD_ID "BreakpadBuildID"
|
||||
#define BREAKPAD_SERVER_PARAMETER_DICT "BreakpadServerParameters"
|
||||
|
||||
// The keys below are NOT user supplied, and are used internally.
|
||||
#define BREAKPAD_PROCESS_START_TIME "BreakpadProcStartTime"
|
||||
#define BREAKPAD_PROCESS_UP_TIME "BreakpadProcessUpTime"
|
||||
#define BREAKPAD_PROCESS_CRASH_TIME "BreakpadProcessCrashTime"
|
||||
#define BREAKPAD_LOGFILE_KEY_PREFIX "BreakpadAppLogFile"
|
||||
#define BREAKPAD_SERVER_PARAMETER_PREFIX "BreakpadServerParameterPrefix_"
|
||||
|
||||
// Optional user-defined function to dec to decide if we should handle
|
||||
// this crash or forward it along.
|
||||
// Return true if you want Breakpad to handle it.
|
||||
|
@ -98,7 +98,8 @@ extern "C" {
|
|||
// (which means the next exception handler will take the exception)
|
||||
typedef bool (*BreakpadFilterCallback)(int exception_type,
|
||||
int exception_code,
|
||||
mach_port_t crashing_thread);
|
||||
mach_port_t crashing_thread,
|
||||
void *context);
|
||||
|
||||
// Create a new BreakpadRef object and install it as an exception
|
||||
// handler. The |parameters| will typically be the contents of your
|
||||
|
@ -179,8 +180,15 @@ typedef bool (*BreakpadFilterCallback)(int exception_type,
|
|||
// other types, see the function in
|
||||
// crash_report_sender.m that maps parameters to
|
||||
// URL parameters. Defaults to 'google'.
|
||||
// BREAKPAD_BUILD_ID A string parameter indicating build id.
|
||||
// Optional.
|
||||
//
|
||||
// BREAKPAD_SERVER_PARAMETER_DICT A plist dictionary of static
|
||||
// parameters that are uploaded to the
|
||||
// server. The parameters are sent as
|
||||
// is to the crash server. Their
|
||||
// content isn't added to the minidump
|
||||
// but pass as URL parameters when
|
||||
// uploading theminidump to the crash
|
||||
// server.
|
||||
//=============================================================================
|
||||
// The BREAKPAD_PRODUCT, BREAKPAD_VERSION and BREAKPAD_URL are
|
||||
// required to have non-NULL values. By default, the BREAKPAD_PRODUCT
|
||||
|
@ -213,13 +221,27 @@ typedef bool (*BreakpadFilterCallback)(int exception_type,
|
|||
//
|
||||
// BREAKPAD_PROCESS_CRASH_TIME The time the process crashed.
|
||||
//
|
||||
// BREAKPAD_PROCESS_UP_TIME The total time the process has been running.
|
||||
// This parameter is not set until the
|
||||
// crash-dump-generation phase.
|
||||
// BREAKPAD_PROCESS_UP_TIME The total time the process has been
|
||||
// running. This parameter is not set
|
||||
// until the crash-dump-generation phase.
|
||||
//
|
||||
// BREAKPAD_LOGFILE_KEY_PREFIX Used to find out which parameters in the
|
||||
// parameter dictionary correspond to log file
|
||||
// paths.
|
||||
// parameter dictionary correspond to log
|
||||
// file paths.
|
||||
//
|
||||
// BREAKPAD_SERVER_PARAMETER_PREFIX This prefix is used by Breakpad
|
||||
// internally, because Breakpad uses
|
||||
// the same dictionary internally to
|
||||
// track both its internal
|
||||
// configuration parameters and
|
||||
// parameters meant to be uploaded
|
||||
// to the server. This string is
|
||||
// used internally by Breakpad to
|
||||
// prefix user-supplied parameter
|
||||
// names so those can be sent to the
|
||||
// server without leaking Breakpad's
|
||||
// internal values.
|
||||
//
|
||||
|
||||
// Returns a new BreakpadRef object on success, NULL otherwise.
|
||||
BreakpadRef BreakpadCreate(NSDictionary *parameters);
|
||||
|
@ -227,27 +249,49 @@ BreakpadRef BreakpadCreate(NSDictionary *parameters);
|
|||
// Uninstall and release the data associated with |ref|.
|
||||
void BreakpadRelease(BreakpadRef ref);
|
||||
|
||||
// Clients may set an optional callback which gets called when a crash occurs.
|
||||
// The callback function should return |true| if we should handle the crash,
|
||||
// generate a crash report, etc. or |false| if we should ignore it and forward
|
||||
// the crash (normally to CrashReporter)
|
||||
// Clients may set an optional callback which gets called when a crash
|
||||
// occurs. The callback function should return |true| if we should
|
||||
// handle the crash, generate a crash report, etc. or |false| if we
|
||||
// should ignore it and forward the crash (normally to CrashReporter).
|
||||
// Context is a pointer to arbitrary data to make the callback with.
|
||||
void BreakpadSetFilterCallback(BreakpadRef ref,
|
||||
BreakpadFilterCallback callback);
|
||||
BreakpadFilterCallback callback,
|
||||
void *context);
|
||||
|
||||
// User defined key and value string storage
|
||||
// All set keys will be uploaded with the minidump if a crash occurs
|
||||
// Keys and Values are limited to 255 bytes (256 - 1 for terminator).
|
||||
// NB this is BYTES not GLYPHS.
|
||||
// Anything longer than 255 bytes will be truncated. Note that the string is
|
||||
// converted to UTF8 before truncation, so any multibyte character that
|
||||
// straddles the 255 byte limit will be mangled.
|
||||
// User defined key and value string storage. Generally this is used
|
||||
// to configure Breakpad's internal operation, such as whether the
|
||||
// crash_sender should prompt the user, or the filesystem location for
|
||||
// the minidump file. See Breakpad.h for some parameters that can be
|
||||
// set. Anything longer than 255 bytes will be truncated. Note that
|
||||
// the string is converted to UTF8 before truncation, so any multibyte
|
||||
// character that straddles the 255(256 - 1 for terminator) byte limit
|
||||
// will be mangled.
|
||||
//
|
||||
// A maximum number of 64 key/value pairs are supported. An assert() will fire
|
||||
// if more than this number are set.
|
||||
// A maximum number of 64 key/value pairs are supported. An assert()
|
||||
// will fire if more than this number are set. Unfortunately, right
|
||||
// now, the same dictionary is used for both Breakpad's parameters AND
|
||||
// the Upload parameters.
|
||||
//
|
||||
// TODO (nealsid): Investigate how necessary this is if we don't
|
||||
// automatically upload parameters to the server anymore.
|
||||
// TODO (nealsid): separate server parameter dictionary from the
|
||||
// dictionary used to configure Breakpad, and document limits for each
|
||||
// independently.
|
||||
void BreakpadSetKeyValue(BreakpadRef ref, NSString *key, NSString *value);
|
||||
NSString *BreakpadKeyValue(BreakpadRef ref, NSString *key);
|
||||
void BreakpadRemoveKeyValue(BreakpadRef ref, NSString *key);
|
||||
|
||||
// You can use this method to specify parameters that will be uploaded
|
||||
// to the crash server. They will be automatically encoded as
|
||||
// necessary. Note that as mentioned above there are limits on both
|
||||
// the number of keys and their length.
|
||||
void BreakpadAddUploadParameter(BreakpadRef ref, NSString *key,
|
||||
NSString *value);
|
||||
|
||||
// This method will remove a previously-added parameter from the
|
||||
// upload parameter set.
|
||||
void BreakpadRemoveUploadParameter(BreakpadRef ref, NSString *key);
|
||||
|
||||
// Add a log file for Breakpad to read and send upon crash dump
|
||||
void BreakpadAddLogFile(BreakpadRef ref, NSString *logPathname);
|
||||
|
||||
|
|
|
@ -154,8 +154,9 @@ class Breakpad {
|
|||
|
||||
void GenerateAndSendReport();
|
||||
|
||||
void SetFilterCallback(BreakpadFilterCallback callback) {
|
||||
void SetFilterCallback(BreakpadFilterCallback callback, void *context) {
|
||||
filter_callback_ = callback;
|
||||
filter_callback_context_ = context;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -163,7 +164,8 @@ class Breakpad {
|
|||
: handler_(NULL),
|
||||
config_params_(NULL),
|
||||
send_and_exit_(true),
|
||||
filter_callback_(NULL) {
|
||||
filter_callback_(NULL),
|
||||
filter_callback_context_(NULL) {
|
||||
inspector_path_[0] = 0;
|
||||
}
|
||||
|
||||
|
@ -194,8 +196,7 @@ class Breakpad {
|
|||
bool send_and_exit_; // Exit after sending, if true
|
||||
|
||||
BreakpadFilterCallback filter_callback_;
|
||||
|
||||
unsigned int logFileCounter;
|
||||
void *filter_callback_context_;
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
|
@ -412,8 +413,10 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) {
|
|||
[parameters objectForKey:@BREAKPAD_VENDOR];
|
||||
NSString *dumpSubdirectory =
|
||||
[parameters objectForKey:@BREAKPAD_DUMP_DIRECTORY];
|
||||
NSString *buildId =
|
||||
[parameters objectForKey:@BREAKPAD_BUILD_ID];
|
||||
|
||||
NSDictionary *serverParameters =
|
||||
[parameters objectForKey:@BREAKPAD_SERVER_PARAMETER_DICT];
|
||||
|
||||
// These may have been set above as user prefs, which take priority.
|
||||
if (!skipConfirm) {
|
||||
skipConfirm = [parameters objectForKey:@BREAKPAD_SKIP_CONFIRM];
|
||||
|
@ -521,10 +524,19 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) {
|
|||
dumpSubdirectory = @"";
|
||||
}
|
||||
|
||||
// The product and version are required values.
|
||||
if (![product length] || ![version length]) {
|
||||
DEBUGLOG(stderr,
|
||||
"Missing required product or version subdirectory keys\n");
|
||||
// The product, version, and URL are required values.
|
||||
if (![product length]) {
|
||||
DEBUGLOG(stderr, "Missing required product key.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (![version length]) {
|
||||
DEBUGLOG(stderr, "Missing required version key.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (![urlStr length]) {
|
||||
DEBUGLOG(stderr, "Missing required URL key.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -555,8 +567,6 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) {
|
|||
dictionary.SetKeyValue(BREAKPAD_DUMP_DIRECTORY,
|
||||
[dumpSubdirectory UTF8String]);
|
||||
|
||||
dictionary.SetKeyValue(BREAKPAD_BUILD_ID,
|
||||
[buildId UTF8String]);
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
char timeStartedString[32];
|
||||
|
@ -579,6 +589,15 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) {
|
|||
[reportEmail UTF8String]);
|
||||
}
|
||||
|
||||
if (serverParameters) {
|
||||
// For each key-value pair, call BreakpadAddUploadParameter()
|
||||
NSEnumerator *keyEnumerator = [serverParameters keyEnumerator];
|
||||
NSString *aParameter;
|
||||
while (aParameter = [keyEnumerator nextObject]) {
|
||||
BreakpadAddUploadParameter(this, aParameter,
|
||||
[serverParameters objectForKey:aParameter]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -622,7 +641,8 @@ bool Breakpad::HandleException(int exception_type,
|
|||
if (filter_callback_) {
|
||||
bool should_handle = filter_callback_(exception_type,
|
||||
exception_code,
|
||||
crashing_thread);
|
||||
crashing_thread,
|
||||
filter_callback_context_);
|
||||
if (!should_handle) return false;
|
||||
}
|
||||
|
||||
|
@ -769,7 +789,7 @@ BreakpadRef BreakpadCreate(NSDictionary *parameters) {
|
|||
|
||||
[pool release];
|
||||
return (BreakpadRef)breakpad;
|
||||
} catch(...) { // don't let exception leave this C API
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
if (gKeyValueAllocator) {
|
||||
gKeyValueAllocator->~ProtectedMemoryAllocator();
|
||||
gKeyValueAllocator = NULL;
|
||||
|
@ -817,7 +837,7 @@ void BreakpadRelease(BreakpadRef ref) {
|
|||
|
||||
pthread_mutex_destroy(&gDictionaryMutex);
|
||||
}
|
||||
} catch(...) { // don't let exception leave this C API
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadRelease() : error\n");
|
||||
}
|
||||
}
|
||||
|
@ -833,11 +853,51 @@ void BreakpadSetKeyValue(BreakpadRef ref, NSString *key, NSString *value) {
|
|||
|
||||
breakpad->SetKeyValue(key, value);
|
||||
}
|
||||
} catch(...) { // don't let exception leave this C API
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadSetKeyValue() : error\n");
|
||||
}
|
||||
}
|
||||
|
||||
void BreakpadAddUploadParameter(BreakpadRef ref,
|
||||
NSString *key,
|
||||
NSString *value) {
|
||||
// The only difference, internally, between an upload parameter and
|
||||
// a key value one that is set with BreakpadSetKeyValue is that we
|
||||
// prepend the keyname with a special prefix. This informs the
|
||||
// crash sender that the parameter should be sent along with the
|
||||
// POST of the crash dump upload.
|
||||
try {
|
||||
Breakpad *breakpad = (Breakpad *)ref;
|
||||
|
||||
if (breakpad && key && gKeyValueAllocator) {
|
||||
ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator);
|
||||
|
||||
NSString *prefixedKey = [@BREAKPAD_SERVER_PARAMETER_PREFIX
|
||||
stringByAppendingString:key];
|
||||
breakpad->SetKeyValue(prefixedKey, value);
|
||||
}
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadSetKeyValue() : error\n");
|
||||
}
|
||||
}
|
||||
|
||||
void BreakpadRemoveUploadParameter(BreakpadRef ref,
|
||||
NSString *key) {
|
||||
try {
|
||||
// Not called at exception time
|
||||
Breakpad *breakpad = (Breakpad *)ref;
|
||||
|
||||
if (breakpad && key && gKeyValueAllocator) {
|
||||
ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator);
|
||||
|
||||
NSString *prefixedKey = [NSString stringWithFormat:@"%@%@",
|
||||
@BREAKPAD_SERVER_PARAMETER_PREFIX, key];
|
||||
breakpad->RemoveKeyValue(prefixedKey);
|
||||
}
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadRemoveKeyValue() : error\n");
|
||||
}
|
||||
}
|
||||
//=============================================================================
|
||||
NSString *BreakpadKeyValue(BreakpadRef ref, NSString *key) {
|
||||
NSString *value = nil;
|
||||
|
@ -852,7 +912,7 @@ NSString *BreakpadKeyValue(BreakpadRef ref, NSString *key) {
|
|||
ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator);
|
||||
|
||||
value = breakpad->KeyValue(key);
|
||||
} catch(...) { // don't let exception leave this C API
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadKeyValue() : error\n");
|
||||
}
|
||||
|
||||
|
@ -870,7 +930,7 @@ void BreakpadRemoveKeyValue(BreakpadRef ref, NSString *key) {
|
|||
|
||||
breakpad->RemoveKeyValue(key);
|
||||
}
|
||||
} catch(...) { // don't let exception leave this C API
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadRemoveKeyValue() : error\n");
|
||||
}
|
||||
}
|
||||
|
@ -887,14 +947,15 @@ void BreakpadGenerateAndSendReport(BreakpadRef ref) {
|
|||
breakpad->GenerateAndSendReport();
|
||||
gBreakpadAllocator->Protect();
|
||||
}
|
||||
} catch(...) { // don't let exception leave this C API
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadGenerateAndSendReport() : error\n");
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void BreakpadSetFilterCallback(BreakpadRef ref,
|
||||
BreakpadFilterCallback callback) {
|
||||
BreakpadFilterCallback callback,
|
||||
void *context) {
|
||||
|
||||
try {
|
||||
Breakpad *breakpad = (Breakpad *)ref;
|
||||
|
@ -903,9 +964,9 @@ void BreakpadSetFilterCallback(BreakpadRef ref,
|
|||
// share the dictionary mutex here (we really don't need a mutex)
|
||||
ProtectedMemoryLocker locker(&gDictionaryMutex, gBreakpadAllocator);
|
||||
|
||||
breakpad->SetFilterCallback(callback);
|
||||
breakpad->SetFilterCallback(callback, context);
|
||||
}
|
||||
} catch(...) { // don't let exception leave this C API
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadSetFilterCallback() : error\n");
|
||||
}
|
||||
}
|
||||
|
@ -933,5 +994,4 @@ void BreakpadAddLogFile(BreakpadRef ref, NSString *logPathname) {
|
|||
}
|
||||
|
||||
BreakpadSetKeyValue(ref, logFileKey, logPathname);
|
||||
|
||||
}
|
||||
|
|
|
@ -69,15 +69,20 @@ extern NSString *const kDefaultServerType;
|
|||
NSMutableDictionary *parameters_; // Key value pairs of data (STRONG)
|
||||
NSData *minidumpContents_; // The data in the minidump (STRONG)
|
||||
NSData *logFileData_; // An NSdata for the tar,
|
||||
// bz2'd log file
|
||||
// bz2'd log file.
|
||||
NSMutableDictionary *serverDictionary_; // The dictionary mapping a
|
||||
// server type name to a
|
||||
// dictionary of URL
|
||||
// parameter names
|
||||
// dictionary of server
|
||||
// parameter names.
|
||||
NSMutableDictionary *socorroDictionary_; // The dictionary for
|
||||
// Socorro
|
||||
// Socorro.
|
||||
NSMutableDictionary *googleDictionary_; // The dictionary for
|
||||
// Google
|
||||
// Google.
|
||||
NSMutableDictionary *extraServerVars_; // A dictionary containing
|
||||
// extra key/value pairs
|
||||
// that are uploaded to the
|
||||
// crash server with the
|
||||
// minidump.
|
||||
}
|
||||
|
||||
// Stops the modal panel with an NSAlertDefaultReturn value. This is the action
|
||||
|
@ -95,9 +100,6 @@ extern NSString *const kDefaultServerType;
|
|||
- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView
|
||||
doCommandBySelector:(SEL)commandSelector;
|
||||
|
||||
// Helper method to set HTTP parameters based on server type
|
||||
- (BOOL)setPostParametersFromDictionary:(NSMutableDictionary *)crashParameters;
|
||||
|
||||
// Accessors to make bindings work
|
||||
- (NSString *)commentsValue;
|
||||
- (void)setCommentsValue:(NSString *)value;
|
||||
|
@ -105,7 +107,4 @@ extern NSString *const kDefaultServerType;
|
|||
- (NSString *)emailValue;
|
||||
- (void)setEmailValue:(NSString *)value;
|
||||
|
||||
// Initialization helper to create dictionaries mapping Breakpad
|
||||
// parameters to URL parameters
|
||||
- (void)createServerParameterDictionaries;
|
||||
@end
|
||||
|
|
|
@ -217,7 +217,24 @@ NSString *const kDefaultServerType = @"google";
|
|||
|
||||
// Returns a dictionary that can be used to map Breakpad parameter names to
|
||||
// URL parameter names.
|
||||
- (NSDictionary *)dictionaryForServerType:(NSString *)serverType;
|
||||
- (NSMutableDictionary *)dictionaryForServerType:(NSString *)serverType;
|
||||
|
||||
// Helper method to set HTTP parameters based on server type. This is
|
||||
// called right before the upload - crashParameters will contain, on exit,
|
||||
// URL parameters that should be sent with the minidump.
|
||||
- (BOOL)populateServerDictionary:(NSMutableDictionary *)crashParameters;
|
||||
|
||||
// Initialization helper to create dictionaries mapping Breakpad
|
||||
// parameters to URL parameters
|
||||
- (void)createServerParameterDictionaries;
|
||||
|
||||
// Accessor method for the URL parameter dictionary
|
||||
- (NSMutableDictionary *)urlParameterDictionary;
|
||||
|
||||
// This method adds a key/value pair to the dictionary that
|
||||
// will be uploaded to the crash server.
|
||||
- (void)addServerParameter:(id)value forKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
@implementation Reporter
|
||||
|
@ -308,7 +325,24 @@ NSString *const kDefaultServerType = @"google";
|
|||
id value = [[NSString alloc] initWithData:data
|
||||
encoding:NSUTF8StringEncoding];
|
||||
|
||||
[parameters_ setObject:value ? value : data forKey:key];
|
||||
// If the keyname is prefixed by BREAKPAD_SERVER_PARAMETER_PREFIX
|
||||
// that indicates that it should be uploaded to the server along
|
||||
// with the minidump, so we treat it specially.
|
||||
if ([key hasPrefix:@BREAKPAD_SERVER_PARAMETER_PREFIX]) {
|
||||
NSString *urlParameterKey =
|
||||
[key substringFromIndex:[@BREAKPAD_SERVER_PARAMETER_PREFIX length]];
|
||||
if ([urlParameterKey length]) {
|
||||
if (value) {
|
||||
[self addServerParameter:value
|
||||
forKey:urlParameterKey];
|
||||
} else {
|
||||
[self addServerParameter:data
|
||||
forKey:urlParameterKey];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
[parameters_ setObject:(value ? value : data) forKey:key];
|
||||
}
|
||||
[value release];
|
||||
}
|
||||
|
||||
|
@ -743,6 +777,7 @@ doCommandBySelector:(SEL)commandSelector {
|
|||
serverDictionary_ = [[NSMutableDictionary alloc] init];
|
||||
socorroDictionary_ = [[NSMutableDictionary alloc] init];
|
||||
googleDictionary_ = [[NSMutableDictionary alloc] init];
|
||||
extraServerVars_ = [[NSMutableDictionary alloc] init];
|
||||
|
||||
[serverDictionary_ setObject:socorroDictionary_ forKey:kSocorroServerType];
|
||||
[serverDictionary_ setObject:googleDictionary_ forKey:kGoogleServerType];
|
||||
|
@ -752,8 +787,6 @@ doCommandBySelector:(SEL)commandSelector {
|
|||
[googleDictionary_ setObject:@"comments" forKey:@BREAKPAD_COMMENTS];
|
||||
[googleDictionary_ setObject:@"prod" forKey:@BREAKPAD_PRODUCT];
|
||||
[googleDictionary_ setObject:@"ver" forKey:@BREAKPAD_VERSION];
|
||||
// TODO: just for testing, google's server doesn't support it
|
||||
[googleDictionary_ setObject:@"buildid" forKey:@BREAKPAD_BUILD_ID];
|
||||
|
||||
[socorroDictionary_ setObject:@"Comments" forKey:@BREAKPAD_COMMENTS];
|
||||
[socorroDictionary_ setObject:@"CrashTime"
|
||||
|
@ -766,21 +799,23 @@ doCommandBySelector:(SEL)commandSelector {
|
|||
forKey:@BREAKPAD_PRODUCT];
|
||||
[socorroDictionary_ setObject:@"ProductName"
|
||||
forKey:@BREAKPAD_PRODUCT];
|
||||
[socorroDictionary_ setObject:@"BuildID"
|
||||
forKey:@BREAKPAD_BUILD_ID];
|
||||
}
|
||||
|
||||
- (NSDictionary *)dictionaryForServerType:(NSString *)serverType {
|
||||
- (NSMutableDictionary *)dictionaryForServerType:(NSString *)serverType {
|
||||
if (serverType == nil || [serverType length] == 0) {
|
||||
return [serverDictionary_ objectForKey:kDefaultServerType];
|
||||
}
|
||||
return [serverDictionary_ objectForKey:serverType];
|
||||
}
|
||||
|
||||
// Helper method to set HTTP parameters based on server type
|
||||
- (BOOL)setPostParametersFromDictionary:(NSMutableDictionary *)crashParameters {
|
||||
- (NSMutableDictionary *)urlParameterDictionary {
|
||||
NSString *serverType = [parameters_ objectForKey:@BREAKPAD_SERVER_TYPE];
|
||||
NSDictionary *urlParameterNames = [self dictionaryForServerType:serverType];
|
||||
return [self dictionaryForServerType:serverType];
|
||||
|
||||
}
|
||||
|
||||
- (BOOL)populateServerDictionary:(NSMutableDictionary *)crashParameters {
|
||||
NSDictionary *urlParameterNames = [self urlParameterDictionary];
|
||||
|
||||
id key;
|
||||
NSEnumerator *enumerator = [parameters_ keyEnumerator];
|
||||
|
@ -802,16 +837,31 @@ doCommandBySelector:(SEL)commandSelector {
|
|||
forKey:urlParameter];
|
||||
}
|
||||
}
|
||||
|
||||
// Now, add the parameters that were added by the application.
|
||||
enumerator = [extraServerVars_ keyEnumerator];
|
||||
|
||||
while ((key = [enumerator nextObject])) {
|
||||
NSString *urlParameterName = (NSString *)key;
|
||||
NSString *urlParameterValue =
|
||||
[extraServerVars_ objectForKey:urlParameterName];
|
||||
[crashParameters setObject:urlParameterValue
|
||||
forKey:urlParameterName];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)addServerParameter:(id)value forKey:(NSString *)key {
|
||||
[extraServerVars_ setObject:value forKey:key];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (void)report {
|
||||
NSURL *url = [NSURL URLWithString:[parameters_ objectForKey:@BREAKPAD_URL]];
|
||||
HTTPMultipartUpload *upload = [[HTTPMultipartUpload alloc] initWithURL:url];
|
||||
NSMutableDictionary *uploadParameters = [NSMutableDictionary dictionary];
|
||||
|
||||
if (![self setPostParametersFromDictionary:uploadParameters]) {
|
||||
if (![self populateServerDictionary:uploadParameters]) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -886,6 +936,7 @@ doCommandBySelector:(SEL)commandSelector {
|
|||
[googleDictionary_ release];
|
||||
[socorroDictionary_ release];
|
||||
[serverDictionary_ release];
|
||||
[extraServerVars_ release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
|
|
@ -234,6 +234,9 @@
|
|||
NSLog(@"Shouldn't find BreakpadKeyValue (key2)");
|
||||
}
|
||||
|
||||
BreakpadAddUploadParameter(breakpad_,
|
||||
@"MeaningOfLife",
|
||||
@"42");
|
||||
[NSThread detachNewThreadSelector:@selector(anotherThread)
|
||||
toTarget:self withObject:nil];
|
||||
|
||||
|
|
|
@ -42,6 +42,13 @@
|
|||
<string>YES</string>
|
||||
<key>BreakpadVendor</key>
|
||||
<string>Foo Bar Corp, Incorporated, LTD, LLC</string>
|
||||
<key>BreakpadServerParameters</key>
|
||||
<dict>
|
||||
<key>Param1</key>
|
||||
<string>Value1</string>
|
||||
<key>Param2</key>
|
||||
<string>Value2</string>
|
||||
</dict>
|
||||
<key>LSUIElement</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
|
|
216
src/client/mac/tests/BreakpadFramework_Test.mm
Normal file
216
src/client/mac/tests/BreakpadFramework_Test.mm
Normal file
|
@ -0,0 +1,216 @@
|
|||
// Copyright (c) 2009, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// BreakpadFramework_Test.mm
|
||||
// Test case file for Breakpad.h/mm.
|
||||
//
|
||||
|
||||
#import "GTMSenTestCase.h"
|
||||
#import "Breakpad.h"
|
||||
|
||||
#include <mach/mach.h>
|
||||
|
||||
@interface BreakpadFramework_Test : GTMTestCase {
|
||||
@private
|
||||
int last_exception_code_;
|
||||
int last_exception_type_;
|
||||
mach_port_t last_exception_thread_;
|
||||
// We're not using Obj-C BOOL because we need to interop with
|
||||
// Breakpad's callback.
|
||||
bool shouldHandleException_;
|
||||
}
|
||||
|
||||
// This method is used by a callback used by test cases to determine
|
||||
// whether to return true or false to Breakpad when handling an
|
||||
// exception.
|
||||
- (bool)shouldHandleException;
|
||||
// This method returns a minimal dictionary that has what
|
||||
// Breakpad needs to initialize.
|
||||
- (NSMutableDictionary *)breakpadInitializationDictionary;
|
||||
// This method is used by the exception handling callback
|
||||
// to communicate to test cases the properites of the last
|
||||
// exception.
|
||||
- (void)setLastExceptionType:(int)type andCode:(int)code
|
||||
andThread:(mach_port_t)thread;
|
||||
@end
|
||||
|
||||
// Callback for Breakpad exceptions
|
||||
bool myBreakpadCallback(int exception_type,
|
||||
int exception_code,
|
||||
mach_port_t crashing_thread,
|
||||
void *context);
|
||||
|
||||
bool myBreakpadCallback(int exception_type,
|
||||
int exception_code,
|
||||
mach_port_t crashing_thread,
|
||||
void *context) {
|
||||
BreakpadFramework_Test *testCaseClass =
|
||||
(BreakpadFramework_Test *)context;
|
||||
[testCaseClass setLastExceptionType:exception_type
|
||||
andCode:exception_code
|
||||
andThread:crashing_thread];
|
||||
bool shouldHandleException =
|
||||
[testCaseClass shouldHandleException];
|
||||
NSLog(@"Callback returning %d", shouldHandleException);
|
||||
return shouldHandleException;
|
||||
}
|
||||
const int kNoLastExceptionCode = -1;
|
||||
const int kNoLastExceptionType = -1;
|
||||
const mach_port_t kNoLastExceptionThread = MACH_PORT_NULL;
|
||||
|
||||
@implementation BreakpadFramework_Test
|
||||
- (void) initializeExceptionStateVariables {
|
||||
last_exception_code_ = kNoLastExceptionCode;
|
||||
last_exception_type_ = kNoLastExceptionType;
|
||||
last_exception_thread_ = kNoLastExceptionThread;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *)breakpadInitializationDictionary {
|
||||
NSMutableDictionary *breakpadParams =
|
||||
[NSMutableDictionary dictionaryWithCapacity:3];
|
||||
|
||||
[breakpadParams setObject:@"UnitTests" forKey:@BREAKPAD_PRODUCT];
|
||||
[breakpadParams setObject:@"1.0" forKey:@BREAKPAD_VERSION];
|
||||
[breakpadParams setObject:@"http://staging" forKey:@BREAKPAD_URL];
|
||||
return breakpadParams;
|
||||
}
|
||||
|
||||
- (bool)shouldHandleException {
|
||||
return shouldHandleException_;
|
||||
}
|
||||
|
||||
- (void)setLastExceptionType:(int)type
|
||||
andCode:(int)code
|
||||
andThread:(mach_port_t)thread {
|
||||
last_exception_type_ = type;
|
||||
last_exception_code_ = code;
|
||||
last_exception_thread_ = thread;
|
||||
}
|
||||
|
||||
// Test that the parameters mark required actually enable Breakpad to
|
||||
// be initialized.
|
||||
- (void)testBreakpadInstantiationWithRequiredParameters {
|
||||
BreakpadRef b = BreakpadCreate([self breakpadInitializationDictionary]);
|
||||
STAssertNotNULL(b, @"BreakpadCreate failed with required parameters");
|
||||
BreakpadRelease(b);
|
||||
}
|
||||
|
||||
// Test that Breakpad fails to initialize cleanly when required
|
||||
// parameters are not present.
|
||||
- (void)testBreakpadInstantiationWithoutRequiredParameters {
|
||||
NSMutableDictionary *breakpadDictionary =
|
||||
[self breakpadInitializationDictionary];
|
||||
|
||||
// Skip setting version, so that BreakpadCreate fails.
|
||||
[breakpadDictionary removeObjectForKey:@BREAKPAD_VERSION];
|
||||
BreakpadRef b = BreakpadCreate(breakpadDictionary);
|
||||
STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
|
||||
" parameter!");
|
||||
|
||||
breakpadDictionary = [self breakpadInitializationDictionary];
|
||||
// Now test with no product
|
||||
[breakpadDictionary removeObjectForKey:@BREAKPAD_PRODUCT];
|
||||
b = BreakpadCreate(breakpadDictionary);
|
||||
STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
|
||||
" parameter!");
|
||||
|
||||
breakpadDictionary = [self breakpadInitializationDictionary];
|
||||
// Now test with no URL
|
||||
[breakpadDictionary removeObjectForKey:@BREAKPAD_URL];
|
||||
b = BreakpadCreate(breakpadDictionary);
|
||||
STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
|
||||
" parameter!");
|
||||
BreakpadRelease(b);
|
||||
}
|
||||
|
||||
// Test to ensure that when we call BreakpadAddUploadParameter,
|
||||
// it's added to the dictionary correctly(this test depends on
|
||||
// some internal details of Breakpad, namely, the special prefix
|
||||
// that it uses to figure out which key/value pairs to upload).
|
||||
- (void)testAddingBreakpadServerVariable {
|
||||
NSMutableDictionary *breakpadDictionary =
|
||||
[self breakpadInitializationDictionary];
|
||||
|
||||
BreakpadRef b = BreakpadCreate(breakpadDictionary);
|
||||
STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!");
|
||||
|
||||
BreakpadAddUploadParameter(b,
|
||||
@"key",
|
||||
@"value");
|
||||
|
||||
// Test that it did not add the key/value directly, e.g. without
|
||||
// prepending the key with the prefix.
|
||||
STAssertNil(BreakpadKeyValue(b, @"key"),
|
||||
@"AddUploadParameter added key directly to dictionary"
|
||||
" instead of prepending it!");
|
||||
|
||||
NSString *prependedKeyname =
|
||||
[@BREAKPAD_SERVER_PARAMETER_PREFIX stringByAppendingString:@"key"];
|
||||
|
||||
STAssertEqualStrings(BreakpadKeyValue(b, prependedKeyname),
|
||||
@"value",
|
||||
@"Calling BreakpadAddUploadParameter did not prepend "
|
||||
"key name");
|
||||
BreakpadRelease(b);
|
||||
}
|
||||
|
||||
// Test that when we do on-demand minidump generation,
|
||||
// the exception code/type/thread are set properly.
|
||||
- (void)testFilterCallbackReturnsFalse {
|
||||
NSMutableDictionary *breakpadDictionary =
|
||||
[self breakpadInitializationDictionary];
|
||||
|
||||
BreakpadRef b = BreakpadCreate(breakpadDictionary);
|
||||
STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!");
|
||||
BreakpadSetFilterCallback(b, &myBreakpadCallback, self);
|
||||
|
||||
// This causes the callback to return false, meaning
|
||||
// Breakpad won't take the exception
|
||||
shouldHandleException_ = false;
|
||||
|
||||
[self initializeExceptionStateVariables];
|
||||
STAssertEquals(last_exception_type_, kNoLastExceptionType,
|
||||
@"Last exception type not initialized correctly.");
|
||||
STAssertEquals(last_exception_code_, kNoLastExceptionCode,
|
||||
@"Last exception code not initialized correctly.");
|
||||
STAssertEquals(last_exception_thread_, kNoLastExceptionThread,
|
||||
@"Last exception thread is not initialized correctly.");
|
||||
|
||||
// Cause Breakpad's exception handler to be invoked.
|
||||
BreakpadGenerateAndSendReport(b);
|
||||
|
||||
STAssertEquals(last_exception_type_, 0,
|
||||
@"Last exception type is not 0 for on demand");
|
||||
STAssertEquals(last_exception_code_, 0,
|
||||
@"Last exception code is not 0 for on demand");
|
||||
STAssertEquals(last_exception_thread_, (mach_port_t)0,
|
||||
@"Last exception thread is not 0 for on demand");
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in a new issue