diff options
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/client/mac/tests/crash_generation_server_test.cc')
-rw-r--r-- | toolkit/crashreporter/google-breakpad/src/client/mac/tests/crash_generation_server_test.cc | 398 |
1 files changed, 0 insertions, 398 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/tests/crash_generation_server_test.cc b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/crash_generation_server_test.cc deleted file mode 100644 index 0164f4a29..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/mac/tests/crash_generation_server_test.cc +++ /dev/null @@ -1,398 +0,0 @@ -// 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. -// -// crash_generation_server_test.cc -// Unit tests for CrashGenerationServer - -#include <dirent.h> -#include <glob.h> -#include <stdint.h> -#include <sys/wait.h> -#include <unistd.h> - -#include <string> - -#include "breakpad_googletest_includes.h" -#include "client/mac/crash_generation/client_info.h" -#include "client/mac/crash_generation/crash_generation_client.h" -#include "client/mac/crash_generation/crash_generation_server.h" -#include "client/mac/handler/exception_handler.h" -#include "client/mac/tests/spawn_child_process.h" -#include "common/tests/auto_tempdir.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::ClientInfo; -using google_breakpad::CrashGenerationClient; -using google_breakpad::CrashGenerationServer; -using google_breakpad::ExceptionHandler; -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 testing::Test; -using namespace google_breakpad_test; - -class CrashGenerationServerTest : public Test { -public: - // The port name to receive messages on - char mach_port_name[128]; - // Filename of the last dump that was generated - string last_dump_name; - // PID of the child process - pid_t child_pid; - // A temp dir - AutoTempDir temp_dir; - // Counter just to ensure that we don't hit the same port again - static int i; - bool filter_callback_called; - - void SetUp() { - sprintf(mach_port_name, - "com.google.breakpad.ServerTest.%d.%d", getpid(), - CrashGenerationServerTest::i++); - child_pid = (pid_t)-1; - filter_callback_called = false; - } -}; -int CrashGenerationServerTest::i = 0; - -// Test that starting and stopping a server works -TEST_F(CrashGenerationServerTest, testStartStopServer) { - CrashGenerationServer server(mach_port_name, - NULL, // filter callback - NULL, // filter context - NULL, // dump callback - NULL, // dump context - NULL, // exit callback - NULL, // exit context - false, // generate dumps - ""); // dump path - ASSERT_TRUE(server.Start()); - ASSERT_TRUE(server.Stop()); -} - -// Test that requesting a dump via CrashGenerationClient works -// Test without actually dumping -TEST_F(CrashGenerationServerTest, testRequestDumpNoDump) { - CrashGenerationServer server(mach_port_name, - NULL, // filter callback - NULL, // filter context - NULL, // dump callback - NULL, // dump context - NULL, // exit callback - NULL, // exit context - false, // don't generate dumps - temp_dir.path()); // dump path - ASSERT_TRUE(server.Start()); - - pid_t pid = fork(); - ASSERT_NE(-1, pid); - if (pid == 0) { - CrashGenerationClient client(mach_port_name); - bool result = client.RequestDump(); - exit(result ? 0 : 1); - } - - int ret; - ASSERT_EQ(pid, waitpid(pid, &ret, 0)); - EXPECT_TRUE(WIFEXITED(ret)); - EXPECT_EQ(0, WEXITSTATUS(ret)); - EXPECT_TRUE(server.Stop()); - // check that no minidump was written - string pattern = temp_dir.path() + "/*"; - glob_t dirContents; - ret = glob(pattern.c_str(), GLOB_NOSORT, NULL, &dirContents); - EXPECT_EQ(GLOB_NOMATCH, ret); - if (ret != GLOB_NOMATCH) - globfree(&dirContents); -} - -void dumpCallback(void *context, const ClientInfo &client_info, - const std::string &file_path) { - if (context) { - CrashGenerationServerTest* self = - reinterpret_cast<CrashGenerationServerTest*>(context); - if (!file_path.empty()) - self->last_dump_name = file_path; - self->child_pid = client_info.pid(); - } -} - -void *RequestDump(void *context) { - CrashGenerationClient client((const char*)context); - bool result = client.RequestDump(); - return (void*)(result ? 0 : 1); -} - -// Test that actually writing a minidump works -TEST_F(CrashGenerationServerTest, testRequestDump) { - CrashGenerationServer server(mach_port_name, - NULL, // filter callback - NULL, // filter context - dumpCallback, // dump callback - this, // dump context - NULL, // exit callback - NULL, // exit context - true, // generate dumps - temp_dir.path()); // dump path - ASSERT_TRUE(server.Start()); - - pid_t pid = fork(); - ASSERT_NE(-1, pid); - if (pid == 0) { - // Have to spawn off a separate thread to request the dump, - // because MinidumpGenerator assumes the handler thread is not - // the only thread - pthread_t thread; - if (pthread_create(&thread, NULL, RequestDump, (void*)mach_port_name) != 0) - exit(1); - void* result; - pthread_join(thread, &result); - exit(reinterpret_cast<intptr_t>(result)); - } - - int ret; - ASSERT_EQ(pid, waitpid(pid, &ret, 0)); - EXPECT_TRUE(WIFEXITED(ret)); - EXPECT_EQ(0, WEXITSTATUS(ret)); - EXPECT_TRUE(server.Stop()); - // check that minidump was written - ASSERT_FALSE(last_dump_name.empty()); - struct stat st; - EXPECT_EQ(0, stat(last_dump_name.c_str(), &st)); - EXPECT_LT(0, st.st_size); - // check client's PID - ASSERT_EQ(pid, child_pid); -} - -static void Crasher() { - int *a = (int*)0x42; - - fprintf(stdout, "Going to crash...\n"); - fprintf(stdout, "A = %d", *a); -} - -// Test that crashing a child process with an OOP ExceptionHandler installed -// results in a minidump being written by the CrashGenerationServer in -// the parent. -TEST_F(CrashGenerationServerTest, testChildProcessCrash) { - CrashGenerationServer server(mach_port_name, - NULL, // filter callback - NULL, // filter context - dumpCallback, // dump callback - this, // dump context - NULL, // exit callback - NULL, // exit context - true, // generate dumps - temp_dir.path()); // dump path - ASSERT_TRUE(server.Start()); - - pid_t pid = fork(); - ASSERT_NE(-1, pid); - if (pid == 0) { - // Instantiate an OOP exception handler. - ExceptionHandler eh("", NULL, NULL, NULL, true, mach_port_name); - Crasher(); - // not reached - exit(0); - } - - int ret; - ASSERT_EQ(pid, waitpid(pid, &ret, 0)); - EXPECT_FALSE(WIFEXITED(ret)); - EXPECT_TRUE(server.Stop()); - // check that minidump was written - ASSERT_FALSE(last_dump_name.empty()); - struct stat st; - EXPECT_EQ(0, stat(last_dump_name.c_str(), &st)); - EXPECT_LT(0, st.st_size); - - // Read the minidump, sanity check some data. - Minidump minidump(last_dump_name.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()); -} - -#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) && \ - (defined(__x86_64__) || defined(__i386__)) -// Test that crashing a child process of a different architecture -// produces a valid minidump. -TEST_F(CrashGenerationServerTest, testChildProcessCrashCrossArchitecture) { - CrashGenerationServer server(mach_port_name, - NULL, // filter callback - NULL, // filter context - dumpCallback, // dump callback - this, // dump context - NULL, // exit callback - NULL, // exit context - true, // generate dumps - temp_dir.path()); // dump path - ASSERT_TRUE(server.Start()); - - // Spawn a child process - string helper_path = GetHelperPath(); - const char* argv[] = { - helper_path.c_str(), - "crash", - mach_port_name, - NULL - }; - pid_t pid = spawn_child_process(argv); - ASSERT_NE(-1, pid); - - int ret; - ASSERT_EQ(pid, waitpid(pid, &ret, 0)); - EXPECT_FALSE(WIFEXITED(ret)); - EXPECT_TRUE(server.Stop()); - // check that minidump was written - ASSERT_FALSE(last_dump_name.empty()); - struct stat st; - EXPECT_EQ(0, stat(last_dump_name.c_str(), &st)); - EXPECT_LT(0, st.st_size); - -const MDCPUArchitecture kExpectedArchitecture = -#if defined(__x86_64__) - MD_CPU_ARCHITECTURE_X86 -#elif defined(__i386__) - MD_CPU_ARCHITECTURE_AMD64 -#endif - ; -const uint32_t kExpectedContext = -#if defined(__i386__) - MD_CONTEXT_AMD64 -#elif defined(__x86_64__) - MD_CONTEXT_X86 -#endif - ; - - // Read the minidump, sanity check some data. - Minidump minidump(last_dump_name.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(kExpectedArchitecture, 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(kExpectedContext, context->GetContextCPU()); - - MinidumpModuleList* module_list = minidump.GetModuleList(); - ASSERT_TRUE(module_list); - const MinidumpModule* main_module = module_list->GetMainModule(); - ASSERT_TRUE(main_module); - EXPECT_EQ(helper_path, main_module->code_file()); -} -#endif - -bool filter_callback(void* context) { - CrashGenerationServerTest* self = - reinterpret_cast<CrashGenerationServerTest*>(context); - self->filter_callback_called = true; - // veto dump generation - return false; -} - -// Test that a filter callback can veto minidump writing. -TEST_F(CrashGenerationServerTest, testFilter) { - CrashGenerationServer server(mach_port_name, - filter_callback, // filter callback - this, // filter context - dumpCallback, // dump callback - this, // dump context - NULL, // exit callback - NULL, // exit context - true, // generate dumps - temp_dir.path()); // dump path - ASSERT_TRUE(server.Start()); - - pid_t pid = fork(); - ASSERT_NE(-1, pid); - if (pid == 0) { - // Instantiate an OOP exception handler. - ExceptionHandler eh("", NULL, NULL, NULL, true, mach_port_name); - Crasher(); - // not reached - exit(0); - } - - int ret; - ASSERT_EQ(pid, waitpid(pid, &ret, 0)); - EXPECT_FALSE(WIFEXITED(ret)); - EXPECT_TRUE(server.Stop()); - - // check that no minidump was written - EXPECT_TRUE(last_dump_name.empty()); - EXPECT_TRUE(filter_callback_called); -} - -} // namespace |