summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.cc')
-rw-r--r--toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.cc501
1 files changed, 0 insertions, 501 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.cc
deleted file mode 100644
index 55275323e..000000000
--- a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.cc
+++ /dev/null
@@ -1,501 +0,0 @@
-// Copyright 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.
-
-#include "client/windows/unittests/exception_handler_test.h"
-
-#include <windows.h>
-#include <dbghelp.h>
-#include <strsafe.h>
-#include <objbase.h>
-#include <shellapi.h>
-
-#include <string>
-
-#include "breakpad_googletest_includes.h"
-#include "client/windows/crash_generation/crash_generation_server.h"
-#include "client/windows/handler/exception_handler.h"
-#include "client/windows/unittests/dump_analysis.h" // NOLINT
-#include "common/windows/string_utils-inl.h"
-#include "google_breakpad/processor/minidump.h"
-
-namespace testing {
-
-DisableExceptionHandlerInScope::DisableExceptionHandlerInScope() {
- catch_exceptions_ = GTEST_FLAG(catch_exceptions);
- GTEST_FLAG(catch_exceptions) = false;
-}
-
-DisableExceptionHandlerInScope::~DisableExceptionHandlerInScope() {
- GTEST_FLAG(catch_exceptions) = catch_exceptions_;
-}
-
-} // namespace testing
-
-namespace {
-
-using std::wstring;
-using namespace google_breakpad;
-
-const wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashTest\\TestCaseServer";
-const char kSuccessIndicator[] = "success";
-const char kFailureIndicator[] = "failure";
-
-const MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>(
- MiniDumpWithFullMemory | // Full memory from process.
- MiniDumpWithProcessThreadData | // Get PEB and TEB.
- MiniDumpWithHandleData); // Get all handle information.
-
-class ExceptionHandlerTest : public ::testing::Test {
- protected:
- // Member variable for each test that they can use
- // for temporary storage.
- TCHAR temp_path_[MAX_PATH];
-
- // Actually constructs a temp path name.
- virtual void SetUp();
-
- // Deletes temporary files.
- virtual void TearDown();
-
- void DoCrashInvalidParameter();
- void DoCrashPureVirtualCall();
-
- // Utility function to test for a path's existence.
- static BOOL DoesPathExist(const TCHAR *path_name);
-
- // Client callback.
- static void ClientDumpCallback(
- void *dump_context,
- const google_breakpad::ClientInfo *client_info,
- const std::wstring *dump_path);
-
- static bool DumpCallback(const wchar_t* dump_path,
- const wchar_t* minidump_id,
- void* context,
- EXCEPTION_POINTERS* exinfo,
- MDRawAssertionInfo* assertion,
- bool succeeded);
-
- static std::wstring dump_file;
- static std::wstring full_dump_file;
-};
-
-std::wstring ExceptionHandlerTest::dump_file;
-std::wstring ExceptionHandlerTest::full_dump_file;
-
-void ExceptionHandlerTest::SetUp() {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
- TCHAR temp_path[MAX_PATH] = { '\0' };
- TCHAR test_name_wide[MAX_PATH] = { '\0' };
- // We want the temporary directory to be what the OS returns
- // to us, + the test case name.
- GetTempPath(MAX_PATH, temp_path);
- // THe test case name is exposed to use as a c-style string,
- // But we might be working in UNICODE here on Windows.
- int dwRet = MultiByteToWideChar(CP_ACP, 0, test_info->name(),
- strlen(test_info->name()),
- test_name_wide,
- MAX_PATH);
- if (!dwRet) {
- assert(false);
- }
- StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide);
- CreateDirectory(temp_path_, NULL);
-}
-
-void ExceptionHandlerTest::TearDown() {
- if (!dump_file.empty()) {
- ::DeleteFile(dump_file.c_str());
- dump_file = L"";
- }
- if (!full_dump_file.empty()) {
- ::DeleteFile(full_dump_file.c_str());
- full_dump_file = L"";
- }
-}
-
-BOOL ExceptionHandlerTest::DoesPathExist(const TCHAR *path_name) {
- DWORD flags = GetFileAttributes(path_name);
- if (flags == INVALID_FILE_ATTRIBUTES) {
- return FALSE;
- }
- return TRUE;
-}
-
-// static
-void ExceptionHandlerTest::ClientDumpCallback(
- void *dump_context,
- const google_breakpad::ClientInfo *client_info,
- const wstring *dump_path) {
- dump_file = *dump_path;
- // Create the full dump file name from the dump path.
- full_dump_file = dump_file.substr(0, dump_file.length() - 4) + L"-full.dmp";
-}
-
-// static
-bool ExceptionHandlerTest::DumpCallback(const wchar_t* dump_path,
- const wchar_t* minidump_id,
- void* context,
- EXCEPTION_POINTERS* exinfo,
- MDRawAssertionInfo* assertion,
- bool succeeded) {
- dump_file = dump_path;
- dump_file += L"\\";
- dump_file += minidump_id;
- dump_file += L".dmp";
- return succeeded;
-}
-
-void ExceptionHandlerTest::DoCrashInvalidParameter() {
- google_breakpad::ExceptionHandler *exc =
- new google_breakpad::ExceptionHandler(
- temp_path_, NULL, NULL, NULL,
- google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER,
- kFullDumpType, kPipeName, NULL);
-
- // Disable the message box for assertions
- _CrtSetReportMode(_CRT_ASSERT, 0);
-
- // Although this is executing in the child process of the death test,
- // if it's not true we'll still get an error rather than the crash
- // being expected.
- ASSERT_TRUE(exc->IsOutOfProcess());
- printf(NULL);
-}
-
-
-struct PureVirtualCallBase {
- PureVirtualCallBase() {
- // We have to reinterpret so the linker doesn't get confused because the
- // method isn't defined.
- reinterpret_cast<PureVirtualCallBase*>(this)->PureFunction();
- }
- virtual ~PureVirtualCallBase() {}
- virtual void PureFunction() const = 0;
-};
-struct PureVirtualCall : public PureVirtualCallBase {
- PureVirtualCall() { PureFunction(); }
- virtual void PureFunction() const {}
-};
-
-void ExceptionHandlerTest::DoCrashPureVirtualCall() {
- google_breakpad::ExceptionHandler *exc =
- new google_breakpad::ExceptionHandler(
- temp_path_, NULL, NULL, NULL,
- google_breakpad::ExceptionHandler::HANDLER_PURECALL,
- kFullDumpType, kPipeName, NULL);
-
- // Disable the message box for assertions
- _CrtSetReportMode(_CRT_ASSERT, 0);
-
- // Although this is executing in the child process of the death test,
- // if it's not true we'll still get an error rather than the crash
- // being expected.
- ASSERT_TRUE(exc->IsOutOfProcess());
-
- // Create a new frame to ensure PureVirtualCall is not optimized to some
- // other line in this function.
- {
- PureVirtualCall instance;
- }
-}
-
-// This test validates that the minidump is written correctly.
-TEST_F(ExceptionHandlerTest, InvalidParameterMiniDumpTest) {
- ASSERT_TRUE(DoesPathExist(temp_path_));
-
- // Call with a bad argument
- ASSERT_TRUE(DoesPathExist(temp_path_));
- wstring dump_path(temp_path_);
- google_breakpad::CrashGenerationServer server(
- kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL,
- NULL, true, &dump_path);
-
- ASSERT_TRUE(dump_file.empty() && full_dump_file.empty());
-
- // This HAS to be EXPECT_, because when this test case is executed in the
- // child process, the server registration will fail due to the named pipe
- // being the same.
- EXPECT_TRUE(server.Start());
- EXPECT_EXIT(DoCrashInvalidParameter(), ::testing::ExitedWithCode(0), "");
- ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty());
- ASSERT_TRUE(DoesPathExist(dump_file.c_str()));
-
- // Verify the dump for infos.
- DumpAnalysis mini(dump_file);
- DumpAnalysis full(full_dump_file);
-
- // The dump should have all of these streams.
- EXPECT_TRUE(mini.HasStream(ThreadListStream));
- EXPECT_TRUE(full.HasStream(ThreadListStream));
- EXPECT_TRUE(mini.HasStream(ModuleListStream));
- EXPECT_TRUE(full.HasStream(ModuleListStream));
- EXPECT_TRUE(mini.HasStream(ExceptionStream));
- EXPECT_TRUE(full.HasStream(ExceptionStream));
- EXPECT_TRUE(mini.HasStream(SystemInfoStream));
- EXPECT_TRUE(full.HasStream(SystemInfoStream));
- EXPECT_TRUE(mini.HasStream(MiscInfoStream));
- EXPECT_TRUE(full.HasStream(MiscInfoStream));
- EXPECT_TRUE(mini.HasStream(HandleDataStream));
- EXPECT_TRUE(full.HasStream(HandleDataStream));
-
- // We expect PEB and TEBs in this dump.
- EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
- EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
-
- // Minidump should have a memory listing, but no 64-bit memory.
- EXPECT_TRUE(mini.HasStream(MemoryListStream));
- EXPECT_FALSE(mini.HasStream(Memory64ListStream));
-
- EXPECT_FALSE(full.HasStream(MemoryListStream));
- EXPECT_TRUE(full.HasStream(Memory64ListStream));
-
- // This is the only place we don't use OR because we want both not
- // to have the streams.
- EXPECT_FALSE(mini.HasStream(ThreadExListStream));
- EXPECT_FALSE(full.HasStream(ThreadExListStream));
- EXPECT_FALSE(mini.HasStream(CommentStreamA));
- EXPECT_FALSE(full.HasStream(CommentStreamA));
- EXPECT_FALSE(mini.HasStream(CommentStreamW));
- EXPECT_FALSE(full.HasStream(CommentStreamW));
- EXPECT_FALSE(mini.HasStream(FunctionTableStream));
- EXPECT_FALSE(full.HasStream(FunctionTableStream));
- EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
- EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
- EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
- EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
- EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
- EXPECT_FALSE(full.HasStream(HandleOperationListStream));
- EXPECT_FALSE(mini.HasStream(TokenStream));
- EXPECT_FALSE(full.HasStream(TokenStream));
-}
-
-
-// This test validates that the minidump is written correctly.
-TEST_F(ExceptionHandlerTest, PureVirtualCallMiniDumpTest) {
- ASSERT_TRUE(DoesPathExist(temp_path_));
-
- // Call with a bad argument
- ASSERT_TRUE(DoesPathExist(temp_path_));
- wstring dump_path(temp_path_);
- google_breakpad::CrashGenerationServer server(
- kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL,
- NULL, true, &dump_path);
-
- ASSERT_TRUE(dump_file.empty() && full_dump_file.empty());
-
- // This HAS to be EXPECT_, because when this test case is executed in the
- // child process, the server registration will fail due to the named pipe
- // being the same.
- EXPECT_TRUE(server.Start());
- EXPECT_EXIT(DoCrashPureVirtualCall(), ::testing::ExitedWithCode(0), "");
- ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty());
- ASSERT_TRUE(DoesPathExist(dump_file.c_str()));
-
- // Verify the dump for infos.
- DumpAnalysis mini(dump_file);
- DumpAnalysis full(full_dump_file);
-
- // The dump should have all of these streams.
- EXPECT_TRUE(mini.HasStream(ThreadListStream));
- EXPECT_TRUE(full.HasStream(ThreadListStream));
- EXPECT_TRUE(mini.HasStream(ModuleListStream));
- EXPECT_TRUE(full.HasStream(ModuleListStream));
- EXPECT_TRUE(mini.HasStream(ExceptionStream));
- EXPECT_TRUE(full.HasStream(ExceptionStream));
- EXPECT_TRUE(mini.HasStream(SystemInfoStream));
- EXPECT_TRUE(full.HasStream(SystemInfoStream));
- EXPECT_TRUE(mini.HasStream(MiscInfoStream));
- EXPECT_TRUE(full.HasStream(MiscInfoStream));
- EXPECT_TRUE(mini.HasStream(HandleDataStream));
- EXPECT_TRUE(full.HasStream(HandleDataStream));
-
- // We expect PEB and TEBs in this dump.
- EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
- EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
-
- // Minidump should have a memory listing, but no 64-bit memory.
- EXPECT_TRUE(mini.HasStream(MemoryListStream));
- EXPECT_FALSE(mini.HasStream(Memory64ListStream));
-
- EXPECT_FALSE(full.HasStream(MemoryListStream));
- EXPECT_TRUE(full.HasStream(Memory64ListStream));
-
- // This is the only place we don't use OR because we want both not
- // to have the streams.
- EXPECT_FALSE(mini.HasStream(ThreadExListStream));
- EXPECT_FALSE(full.HasStream(ThreadExListStream));
- EXPECT_FALSE(mini.HasStream(CommentStreamA));
- EXPECT_FALSE(full.HasStream(CommentStreamA));
- EXPECT_FALSE(mini.HasStream(CommentStreamW));
- EXPECT_FALSE(full.HasStream(CommentStreamW));
- EXPECT_FALSE(mini.HasStream(FunctionTableStream));
- EXPECT_FALSE(full.HasStream(FunctionTableStream));
- EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
- EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
- EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
- EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
- EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
- EXPECT_FALSE(full.HasStream(HandleOperationListStream));
- EXPECT_FALSE(mini.HasStream(TokenStream));
- EXPECT_FALSE(full.HasStream(TokenStream));
-}
-
-// Test that writing a minidump produces a valid minidump containing
-// some expected structures.
-TEST_F(ExceptionHandlerTest, WriteMinidumpTest) {
- ExceptionHandler handler(temp_path_,
- NULL,
- DumpCallback,
- NULL,
- ExceptionHandler::HANDLER_ALL);
-
- // Disable GTest SEH handler
- testing::DisableExceptionHandlerInScope disable_exception_handler;
-
- ASSERT_TRUE(handler.WriteMinidump());
- ASSERT_FALSE(dump_file.empty());
-
- string minidump_filename;
- ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file,
- &minidump_filename));
-
- // Read the minidump and verify some info.
- Minidump minidump(minidump_filename);
- ASSERT_TRUE(minidump.Read());
- // TODO(ted): more comprehensive tests...
-}
-
-// Test that an additional memory region can be included in the minidump.
-TEST_F(ExceptionHandlerTest, AdditionalMemory) {
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- const uint32_t kMemorySize = si.dwPageSize;
-
- // Get some heap memory.
- uint8_t* memory = new uint8_t[kMemorySize];
- const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
- ASSERT_TRUE(memory);
-
- // Stick some data into the memory so the contents can be verified.
- for (uint32_t i = 0; i < kMemorySize; ++i) {
- memory[i] = i % 255;
- }
-
- ExceptionHandler handler(temp_path_,
- NULL,
- DumpCallback,
- NULL,
- ExceptionHandler::HANDLER_ALL);
-
- // Disable GTest SEH handler
- testing::DisableExceptionHandlerInScope disable_exception_handler;
-
- // Add the memory region to the list of memory to be included.
- handler.RegisterAppMemory(memory, kMemorySize);
- ASSERT_TRUE(handler.WriteMinidump());
- ASSERT_FALSE(dump_file.empty());
-
- string minidump_filename;
- ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file,
- &minidump_filename));
-
- // Read the minidump. Ensure that the memory region is present
- Minidump minidump(minidump_filename);
- ASSERT_TRUE(minidump.Read());
-
- MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
- ASSERT_TRUE(dump_memory_list);
- const MinidumpMemoryRegion* region =
- dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
- ASSERT_TRUE(region);
-
- EXPECT_EQ(kMemoryAddress, region->GetBase());
- EXPECT_EQ(kMemorySize, region->GetSize());
-
- // Verify memory contents.
- EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize));
-
- delete[] memory;
-}
-
-// Test that a memory region that was previously registered
-// can be unregistered.
-TEST_F(ExceptionHandlerTest, AdditionalMemoryRemove) {
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- const uint32_t kMemorySize = si.dwPageSize;
-
- // Get some heap memory.
- uint8_t* memory = new uint8_t[kMemorySize];
- const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
- ASSERT_TRUE(memory);
-
- // Stick some data into the memory so the contents can be verified.
- for (uint32_t i = 0; i < kMemorySize; ++i) {
- memory[i] = i % 255;
- }
-
- ExceptionHandler handler(temp_path_,
- NULL,
- DumpCallback,
- NULL,
- ExceptionHandler::HANDLER_ALL);
-
- // Disable GTest SEH handler
- testing::DisableExceptionHandlerInScope disable_exception_handler;
-
- // Add the memory region to the list of memory to be included.
- handler.RegisterAppMemory(memory, kMemorySize);
-
- // ...and then remove it
- handler.UnregisterAppMemory(memory);
-
- ASSERT_TRUE(handler.WriteMinidump());
- ASSERT_FALSE(dump_file.empty());
-
- string minidump_filename;
- ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file,
- &minidump_filename));
-
- // Read the minidump. Ensure that the memory region is not present.
- Minidump minidump(minidump_filename);
- ASSERT_TRUE(minidump.Read());
-
- MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
- ASSERT_TRUE(dump_memory_list);
- const MinidumpMemoryRegion* region =
- dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
- EXPECT_FALSE(region);
-
- delete[] memory;
-}
-
-} // namespace