mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-11-24 09:15:43 +01:00
Add some unit tests for the mac MinidumpGenerator
R=mark at http://breakpad.appspot.com/240001/show git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@742 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
ef7262d477
commit
efbe428d83
@ -51,6 +51,8 @@
|
||||
8B4BDABE12012CEF009C7060 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B4BDAA7120124EA009C7060 /* libcrypto.dylib */; };
|
||||
8B4BDAC512012D05009C7060 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B4BDAA7120124EA009C7060 /* libcrypto.dylib */; };
|
||||
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
|
||||
D23F4B2E12A7E13200686C8D /* minidump_generator_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D23F4B2C12A7E13200686C8D /* minidump_generator_test.cc */; };
|
||||
D23F4B3312A7E17700686C8D /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2F9A41512131EF0002747C1 /* libgtest.a */; };
|
||||
D244536A12426F00009BBCE0 /* logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535112426EBB009BBCE0 /* logging.cc */; };
|
||||
D244536B12426F00009BBCE0 /* minidump.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535212426EBB009BBCE0 /* minidump.cc */; };
|
||||
D244536C12426F00009BBCE0 /* pathname_stripper.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535312426EBB009BBCE0 /* pathname_stripper.cc */; };
|
||||
@ -62,6 +64,10 @@
|
||||
D2A5DD301188633800081F03 /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53690ECCE3FD009BE4BA /* breakpad_nlist_64.cc */; };
|
||||
D2A5DD401188640400081F03 /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53690ECCE3FD009BE4BA /* breakpad_nlist_64.cc */; };
|
||||
D2A5DD411188642E00081F03 /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53690ECCE3FD009BE4BA /* breakpad_nlist_64.cc */; };
|
||||
D2C1DBE412AFC270006917BD /* logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535112426EBB009BBCE0 /* logging.cc */; };
|
||||
D2C1DBE512AFC270006917BD /* minidump.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535212426EBB009BBCE0 /* minidump.cc */; };
|
||||
D2C1DBE612AFC270006917BD /* pathname_stripper.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244535312426EBB009BBCE0 /* pathname_stripper.cc */; };
|
||||
D2C1DBE712AFC270006917BD /* basic_code_modules.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244534F12426E98009BBCE0 /* basic_code_modules.cc */; };
|
||||
D2F9A3D51212F87C002747C1 /* exception_handler_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F9A3D41212F87C002747C1 /* exception_handler_test.cc */; };
|
||||
D2F9A43D12131F55002747C1 /* gmock-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F9A43C12131F55002747C1 /* gmock-all.cc */; };
|
||||
D2F9A44012131F65002747C1 /* gtest_main.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F9A43E12131F65002747C1 /* gtest_main.cc */; };
|
||||
@ -135,7 +141,6 @@
|
||||
F93803D50F8083B7004D428B /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537C0ECCE635009BE4BA /* macho_utilities.cc */; };
|
||||
F93803D60F8083B7004D428B /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537E0ECCE635009BE4BA /* macho_walker.cc */; };
|
||||
F93803D70F8083B7004D428B /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53820ECCE635009BE4BA /* string_utilities.cc */; };
|
||||
F93803DA0F8083D8004D428B /* minidump_generator_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F93803D90F8083D8004D428B /* minidump_generator_test.cc */; };
|
||||
F93DE2D80F82A70E00608B94 /* minidump_file_writer_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = F93DE2D70F82A70E00608B94 /* minidump_file_writer_unittest.cc */; };
|
||||
F93DE2D90F82A73500608B94 /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C538F0ECCE70A009BE4BA /* minidump_file_writer.cc */; };
|
||||
F93DE2DA0F82A73500608B94 /* convert_UTF.c in Sources */ = {isa = PBXBuildFile; fileRef = F92C53870ECCE6C0009BE4BA /* convert_UTF.c */; };
|
||||
@ -312,6 +317,13 @@
|
||||
remoteGlobalIDString = D21F97D211CBA0F200239E38;
|
||||
remoteInfo = test_assembler_unittest;
|
||||
};
|
||||
D23F4B2F12A7E16200686C8D /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D2F9A41412131EF0002747C1;
|
||||
remoteInfo = gtest;
|
||||
};
|
||||
D2F9A44212131F80002747C1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
|
||||
@ -512,6 +524,7 @@
|
||||
8B31FFF611F0C90500FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
8B4BDAA7120124EA009C7060 /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcrypto.dylib; path = usr/lib/libcrypto.dylib; sourceTree = SDKROOT; };
|
||||
8DC2EF5B0486A6940098B216 /* Breakpad.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Breakpad.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D23F4B2C12A7E13200686C8D /* minidump_generator_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_generator_test.cc; path = tests/minidump_generator_test.cc; sourceTree = "<group>"; };
|
||||
D244534F12426E98009BBCE0 /* basic_code_modules.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = basic_code_modules.cc; path = ../../processor/basic_code_modules.cc; sourceTree = SOURCE_ROOT; };
|
||||
D244535112426EBB009BBCE0 /* logging.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = logging.cc; path = ../../processor/logging.cc; sourceTree = SOURCE_ROOT; };
|
||||
D244535212426EBB009BBCE0 /* minidump.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump.cc; path = ../../processor/minidump.cc; sourceTree = SOURCE_ROOT; };
|
||||
@ -602,7 +615,6 @@
|
||||
F92C56A70ECE04C5009BE4BA /* crash_report_sender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crash_report_sender.h; path = sender/crash_report_sender.h; sourceTree = "<group>"; };
|
||||
F92C56A80ECE04C5009BE4BA /* crash_report_sender.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = crash_report_sender.m; path = sender/crash_report_sender.m; sourceTree = "<group>"; };
|
||||
F93803BE0F80820F004D428B /* generator_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = generator_test; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F93803D90F8083D8004D428B /* minidump_generator_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_generator_test.cc; path = handler/minidump_generator_test.cc; sourceTree = "<group>"; };
|
||||
F93DE2D10F82A67300608B94 /* minidump_file_writer_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = minidump_file_writer_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F93DE2D70F82A70E00608B94 /* minidump_file_writer_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_file_writer_unittest.cc; path = ../minidump_file_writer_unittest.cc; sourceTree = SOURCE_ROOT; };
|
||||
F93DE32C0F82C55600608B94 /* handler_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = handler_test; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@ -696,6 +708,7 @@
|
||||
files = (
|
||||
8B31029411F0D54300FCF3E4 /* Foundation.framework in Frameworks */,
|
||||
8B4BDABE12012CEF009C7060 /* libcrypto.dylib in Frameworks */,
|
||||
D23F4B3312A7E17700686C8D /* libgtest.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -815,7 +828,6 @@
|
||||
F92C53590ECCE3BB009BE4BA /* handler */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F93803D90F8083D8004D428B /* minidump_generator_test.cc */,
|
||||
F92C53670ECCE3FD009BE4BA /* breakpad_exc_server.c */,
|
||||
F92C53680ECCE3FD009BE4BA /* breakpad_exc_server.h */,
|
||||
F92C53690ECCE3FD009BE4BA /* breakpad_nlist_64.cc */,
|
||||
@ -1009,6 +1021,7 @@
|
||||
F9C77DDF0F7DD7CF0045F7DB /* tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D23F4B2C12A7E13200686C8D /* minidump_generator_test.cc */,
|
||||
D2F9A4CE121336F7002747C1 /* crash_generation_server_test.cc */,
|
||||
D2F9A3D41212F87C002747C1 /* exception_handler_test.cc */,
|
||||
F9C77DE00F7DD7E30045F7DB /* SimpleStringDictionaryTest.h */,
|
||||
@ -1178,6 +1191,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D23F4B3012A7E16200686C8D /* PBXTargetDependency */,
|
||||
);
|
||||
name = generator_test;
|
||||
productName = generator_test;
|
||||
@ -1621,6 +1635,10 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D2C1DBE412AFC270006917BD /* logging.cc in Sources */,
|
||||
D2C1DBE512AFC270006917BD /* minidump.cc in Sources */,
|
||||
D2C1DBE612AFC270006917BD /* pathname_stripper.cc in Sources */,
|
||||
D2C1DBE712AFC270006917BD /* basic_code_modules.cc in Sources */,
|
||||
D2F9A4DF12133AD9002747C1 /* crash_generation_client.cc in Sources */,
|
||||
D2F9A4E012133AD9002747C1 /* crash_generation_server.cc in Sources */,
|
||||
D24BBD291211EDB100F3D417 /* MachIPC.mm in Sources */,
|
||||
@ -1636,7 +1654,7 @@
|
||||
F93803D50F8083B7004D428B /* macho_utilities.cc in Sources */,
|
||||
F93803D60F8083B7004D428B /* macho_walker.cc in Sources */,
|
||||
F93803D70F8083B7004D428B /* string_utilities.cc in Sources */,
|
||||
F93803DA0F8083D8004D428B /* minidump_generator_test.cc in Sources */,
|
||||
D23F4B2E12A7E13200686C8D /* minidump_generator_test.cc in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1733,6 +1751,11 @@
|
||||
name = minidump_upload;
|
||||
targetProxy = 8B31051E11F1010E00FCF3E4 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D23F4B3012A7E16200686C8D /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D2F9A41412131EF0002747C1 /* gtest */;
|
||||
targetProxy = D23F4B2F12A7E16200686C8D /* PBXContainerItemProxy */;
|
||||
};
|
||||
D2F9A44312131F80002747C1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D2F9A41412131EF0002747C1 /* gtest */;
|
||||
@ -2094,7 +2117,15 @@
|
||||
F93803C00F808210004D428B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = ../..;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "BP_LOGGING_INCLUDE=\\\"client/mac/tests/testlogging.h\\\"";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
../..,
|
||||
../../..,
|
||||
../../testing,
|
||||
../../testing/include,
|
||||
../../testing/gtest,
|
||||
../../testing/gtest/include,
|
||||
);
|
||||
PRODUCT_NAME = generator_test;
|
||||
};
|
||||
name = Debug;
|
||||
|
@ -1,81 +0,0 @@
|
||||
// Copyright (c) 2006, 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.
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include "minidump_generator.h"
|
||||
#include "minidump_file_writer.h"
|
||||
|
||||
using std::string;
|
||||
using google_breakpad::MinidumpGenerator;
|
||||
|
||||
static bool doneWritingReport = false;
|
||||
|
||||
static void *Reporter(void *) {
|
||||
char buffer[PATH_MAX];
|
||||
MinidumpGenerator md;
|
||||
|
||||
// Write it to the desktop
|
||||
snprintf(buffer,
|
||||
sizeof(buffer),
|
||||
"/tmp/test.dmp");
|
||||
|
||||
|
||||
fprintf(stdout, "Writing %s\n", buffer);
|
||||
unlink(buffer);
|
||||
md.Write(buffer);
|
||||
doneWritingReport = true;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void SleepyFunction() {
|
||||
while (!doneWritingReport) {
|
||||
usleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char * const argv[]) {
|
||||
pthread_t reporter_thread;
|
||||
|
||||
if (pthread_create(&reporter_thread, NULL, Reporter, NULL) == 0) {
|
||||
pthread_detach(reporter_thread);
|
||||
} else {
|
||||
perror("pthread_create");
|
||||
}
|
||||
|
||||
SleepyFunction();
|
||||
|
||||
return 0;
|
||||
}
|
@ -155,7 +155,7 @@ TEST_F(ExceptionHandlerTest, DumpChildProcess) {
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
// In the child process
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
|
||||
// Send parent process the task and thread ports.
|
||||
MachSendMessage child_message(0);
|
||||
@ -168,12 +168,12 @@ TEST_F(ExceptionHandlerTest, DumpChildProcess) {
|
||||
|
||||
// Wait for the parent process.
|
||||
uint8_t data;
|
||||
read(fds[1], &data, 1);
|
||||
read(fds[0], &data, 1);
|
||||
exit(0);
|
||||
}
|
||||
// In the parent process.
|
||||
ASSERT_NE(-1, pid);
|
||||
close(fds[1]);
|
||||
close(fds[0]);
|
||||
|
||||
// Read the child's task and thread ports.
|
||||
MachReceiveMessage child_message;
|
||||
@ -200,7 +200,7 @@ TEST_F(ExceptionHandlerTest, DumpChildProcess) {
|
||||
|
||||
// Unblock child process
|
||||
uint8_t data = 1;
|
||||
(void)write(fds[0], &data, 1);
|
||||
(void)write(fds[1], &data, 1);
|
||||
|
||||
// Child process should have exited with a zero status.
|
||||
int ret;
|
||||
|
251
src/client/mac/tests/minidump_generator_test.cc
Normal file
251
src/client/mac/tests/minidump_generator_test.cc
Normal file
@ -0,0 +1,251 @@
|
||||
// Copyright (c) 2010, 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.
|
||||
|
||||
// minidump_generator_test.cc: Unit tests for google_breakpad::MinidumpGenerator
|
||||
|
||||
#include <crt_externs.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "breakpad_googletest_includes.h"
|
||||
#include "client/mac/handler/minidump_generator.h"
|
||||
#include "client/mac/tests/auto_tempdir.h"
|
||||
#include "common/mac/MachIPC.h"
|
||||
#include "google_breakpad/processor/minidump.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
// This acts as the log sink for INFO logging from the processor
|
||||
// logging code. The logging output confuses XCode and makes it think
|
||||
// there are unit test failures. testlogging.h handles the overriding.
|
||||
std::ostringstream info_log;
|
||||
}
|
||||
|
||||
namespace {
|
||||
using std::string;
|
||||
using google_breakpad::AutoTempDir;
|
||||
using google_breakpad::MinidumpGenerator;
|
||||
using google_breakpad::MachPortSender;
|
||||
using google_breakpad::MachReceiveMessage;
|
||||
using google_breakpad::MachSendMessage;
|
||||
using google_breakpad::Minidump;
|
||||
using google_breakpad::MinidumpContext;
|
||||
using google_breakpad::MinidumpException;
|
||||
using google_breakpad::MinidumpModule;
|
||||
using google_breakpad::MinidumpModuleList;
|
||||
using google_breakpad::MinidumpSystemInfo;
|
||||
using google_breakpad::MinidumpThread;
|
||||
using google_breakpad::MinidumpThreadList;
|
||||
using google_breakpad::ReceivePort;
|
||||
using testing::Test;
|
||||
|
||||
const MDCPUArchitecture kNativeArchitecture =
|
||||
#if defined(__i386__)
|
||||
MD_CPU_ARCHITECTURE_X86
|
||||
#elif defined(__x86_64__)
|
||||
MD_CPU_ARCHITECTURE_AMD64
|
||||
#elif defined(__ppc__) || defined(__ppc64__)
|
||||
MD_CPU_ARCHITECTURE_PPC
|
||||
#else
|
||||
#error "This test has not been ported to this CPU architecture."
|
||||
#endif
|
||||
;
|
||||
|
||||
const u_int32_t kNativeContext =
|
||||
#if defined(__i386__)
|
||||
MD_CONTEXT_X86
|
||||
#elif defined(__x86_64__)
|
||||
MD_CONTEXT_AMD64
|
||||
#elif defined(__ppc__) || defined(__ppc64__)
|
||||
MD_CONTEXT_PPC
|
||||
#else
|
||||
#error "This test has not been ported to this CPU architecture."
|
||||
#endif
|
||||
;
|
||||
|
||||
static string GetExecutablePath() {
|
||||
char self_path[PATH_MAX];
|
||||
uint32_t size = sizeof(self_path);
|
||||
if (_NSGetExecutablePath(self_path, &size) != 0)
|
||||
return "";
|
||||
return self_path;
|
||||
}
|
||||
|
||||
class MinidumpGeneratorTest : public Test {
|
||||
public:
|
||||
AutoTempDir tempDir;
|
||||
};
|
||||
|
||||
static void *Junk(void* data) {
|
||||
bool* wait = reinterpret_cast<bool*>(data);
|
||||
while (!*wait) {
|
||||
usleep(10000);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TEST_F(MinidumpGeneratorTest, InProcess) {
|
||||
MinidumpGenerator generator;
|
||||
string dump_filename = MinidumpGenerator::UniqueNameInDirectory(tempDir.path,
|
||||
NULL);
|
||||
|
||||
// Run an extra thread since MinidumpGenerator assumes there
|
||||
// are 2 or more threads.
|
||||
pthread_t junk_thread;
|
||||
bool quit = false;
|
||||
ASSERT_EQ(0, pthread_create(&junk_thread, NULL, Junk, &quit));
|
||||
|
||||
ASSERT_TRUE(generator.Write(dump_filename.c_str()));
|
||||
// Ensure that minidump file exists and is > 0 bytes.
|
||||
struct stat st;
|
||||
ASSERT_EQ(0, stat(dump_filename.c_str(), &st));
|
||||
ASSERT_LT(0, st.st_size);
|
||||
|
||||
// join the background thread
|
||||
quit = true;
|
||||
pthread_join(junk_thread, NULL);
|
||||
|
||||
// Read the minidump, sanity check some data.
|
||||
Minidump minidump(dump_filename.c_str());
|
||||
ASSERT_TRUE(minidump.Read());
|
||||
|
||||
MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
|
||||
ASSERT_TRUE(system_info);
|
||||
const MDRawSystemInfo* raw_info = system_info->system_info();
|
||||
ASSERT_TRUE(raw_info);
|
||||
EXPECT_EQ(kNativeArchitecture, raw_info->processor_architecture);
|
||||
|
||||
MinidumpThreadList* thread_list = minidump.GetThreadList();
|
||||
ASSERT_TRUE(thread_list);
|
||||
ASSERT_EQ((unsigned int)1, thread_list->thread_count());
|
||||
|
||||
MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
|
||||
ASSERT_TRUE(main_thread);
|
||||
MinidumpContext* context = main_thread->GetContext();
|
||||
ASSERT_TRUE(context);
|
||||
EXPECT_EQ(kNativeContext, context->GetContextCPU());
|
||||
|
||||
MinidumpModuleList* module_list = minidump.GetModuleList();
|
||||
ASSERT_TRUE(module_list);
|
||||
const MinidumpModule* main_module = module_list->GetMainModule();
|
||||
ASSERT_TRUE(main_module);
|
||||
EXPECT_EQ(GetExecutablePath(), main_module->code_file());
|
||||
}
|
||||
|
||||
TEST_F(MinidumpGeneratorTest, OutOfProcess) {
|
||||
const int kTimeoutMs = 2000;
|
||||
// Create a mach port to receive the child task on.
|
||||
char machPortName[128];
|
||||
sprintf(machPortName, "MinidumpGeneratorTest.%d", getpid());
|
||||
ReceivePort parent_recv_port(machPortName);
|
||||
|
||||
// Give the child process a pipe to block on.
|
||||
int fds[2];
|
||||
ASSERT_EQ(0, pipe(fds));
|
||||
|
||||
// Fork off a child process to dump.
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
// In the child process
|
||||
close(fds[1]);
|
||||
|
||||
// Send parent process the task port.
|
||||
MachSendMessage child_message(0);
|
||||
child_message.AddDescriptor(mach_task_self());
|
||||
|
||||
MachPortSender child_sender(machPortName);
|
||||
if (child_sender.SendMessage(child_message, kTimeoutMs) != KERN_SUCCESS) {
|
||||
fprintf(stderr, "Error sending message from child process!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Wait for the parent process.
|
||||
uint8_t data;
|
||||
read(fds[0], &data, 1);
|
||||
exit(0);
|
||||
}
|
||||
// In the parent process.
|
||||
ASSERT_NE(-1, pid);
|
||||
close(fds[0]);
|
||||
|
||||
// Read the child's task port.
|
||||
MachReceiveMessage child_message;
|
||||
ASSERT_EQ(KERN_SUCCESS,
|
||||
parent_recv_port.WaitForMessage(&child_message, kTimeoutMs));
|
||||
mach_port_t child_task = child_message.GetTranslatedPort(0);
|
||||
ASSERT_NE((mach_port_t)MACH_PORT_NULL, child_task);
|
||||
|
||||
// Write a minidump of the child process.
|
||||
MinidumpGenerator generator(child_task, MACH_PORT_NULL);
|
||||
string dump_filename = MinidumpGenerator::UniqueNameInDirectory(tempDir.path,
|
||||
NULL);
|
||||
ASSERT_TRUE(generator.Write(dump_filename.c_str()));
|
||||
|
||||
// Ensure that minidump file exists and is > 0 bytes.
|
||||
struct stat st;
|
||||
ASSERT_EQ(0, stat(dump_filename.c_str(), &st));
|
||||
ASSERT_LT(0, st.st_size);
|
||||
|
||||
// Unblock child process
|
||||
uint8_t data = 1;
|
||||
(void)write(fds[1], &data, 1);
|
||||
|
||||
// Child process should have exited with a zero status.
|
||||
int ret;
|
||||
ASSERT_EQ(pid, waitpid(pid, &ret, 0));
|
||||
EXPECT_NE(0, WIFEXITED(ret));
|
||||
EXPECT_EQ(0, WEXITSTATUS(ret));
|
||||
|
||||
// Read the minidump, sanity check some data.
|
||||
Minidump minidump(dump_filename.c_str());
|
||||
ASSERT_TRUE(minidump.Read());
|
||||
|
||||
MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
|
||||
ASSERT_TRUE(system_info);
|
||||
const MDRawSystemInfo* raw_info = system_info->system_info();
|
||||
ASSERT_TRUE(raw_info);
|
||||
EXPECT_EQ(kNativeArchitecture, raw_info->processor_architecture);
|
||||
|
||||
MinidumpThreadList* thread_list = minidump.GetThreadList();
|
||||
ASSERT_TRUE(thread_list);
|
||||
ASSERT_EQ((unsigned int)1, thread_list->thread_count());
|
||||
|
||||
MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
|
||||
ASSERT_TRUE(main_thread);
|
||||
MinidumpContext* context = main_thread->GetContext();
|
||||
ASSERT_TRUE(context);
|
||||
EXPECT_EQ(kNativeContext, context->GetContextCPU());
|
||||
|
||||
MinidumpModuleList* module_list = minidump.GetModuleList();
|
||||
ASSERT_TRUE(module_list);
|
||||
const MinidumpModule* main_module = module_list->GetMainModule();
|
||||
ASSERT_TRUE(main_module);
|
||||
EXPECT_EQ(GetExecutablePath(), main_module->code_file());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user