exception_handler_test.cc revision 9220e0baf1f59c067e82495d697306cc460c4e8c
1f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// Copyright 2009, Google Inc. 2f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// All rights reserved. 3f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// 4f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// Redistribution and use in source and binary forms, with or without 5f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// modification, are permitted provided that the following conditions are 6f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// met: 7f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// 8f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// * Redistributions of source code must retain the above copyright 9f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// notice, this list of conditions and the following disclaimer. 10f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// * Redistributions in binary form must reproduce the above 11f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// copyright notice, this list of conditions and the following disclaimer 12f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// in the documentation and/or other materials provided with the 13f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// distribution. 14f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// * Neither the name of Google Inc. nor the names of its 15f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// contributors may be used to endorse or promote products derived from 16f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// this software without specific prior written permission. 17f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// 18f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 30f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <windows.h> 31f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <dbghelp.h> 32f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <strsafe.h> 33f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <objbase.h> 34f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid#include <shellapi.h> 35f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 369220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek#include <string> 379220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek 38ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com#include "../../../breakpad_googletest_includes.h" 399220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek#include "../../../../common/windows/string_utils-inl.h" 409220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek#include "../../../../google_breakpad/processor/minidump.h" 41ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com#include "../crash_generation/crash_generation_server.h" 42ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com#include "../handler/exception_handler.h" 438cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com#include "dump_analysis.h" // NOLINT 44ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com 45f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidnamespace { 469220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek 479220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekusing std::wstring; 489220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekusing namespace google_breakpad; 499220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek 50f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidconst wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashTest\\TestCaseServer"; 51f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidconst char kSuccessIndicator[] = "success"; 52f4f249e54475c88e5c0092633c2c31dd9ce18712nealsidconst char kFailureIndicator[] = "failure"; 53f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 548cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comconst MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>( 558cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com MiniDumpWithFullMemory | // Full memory from process. 568cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com MiniDumpWithProcessThreadData | // Get PEB and TEB. 578cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com MiniDumpWithHandleData); // Get all handle information. 58f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 598cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comclass ExceptionHandlerTest : public ::testing::Test { 60ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com protected: 61f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid // Member variable for each test that they can use 62f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid // for temporary storage. 63f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid TCHAR temp_path_[MAX_PATH]; 648cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 65f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid // Actually constructs a temp path name. 66f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid virtual void SetUp(); 678cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 688cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // Deletes temporary files. 698cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com virtual void TearDown(); 708cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 71bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com void DoCrashInvalidParameter(); 72bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com void DoCrashPureVirtualCall(); 738cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 748cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // Utility function to test for a path's existence. 758cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com static BOOL DoesPathExist(const TCHAR *path_name); 768cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 778cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // Client callback. 788cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com static void ClientDumpCallback( 798cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com void *dump_context, 808cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com const google_breakpad::ClientInfo *client_info, 818cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com const std::wstring *dump_path); 828cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 839220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek static bool DumpCallback(const wchar_t* dump_path, 849220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek const wchar_t* minidump_id, 859220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek void* context, 869220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek EXCEPTION_POINTERS* exinfo, 879220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek MDRawAssertionInfo* assertion, 889220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek bool succeeded); 899220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek 908cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com static std::wstring dump_file; 918cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com static std::wstring full_dump_file; 92f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid}; 93f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 948cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comstd::wstring ExceptionHandlerTest::dump_file; 958cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comstd::wstring ExceptionHandlerTest::full_dump_file; 968cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 978cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comvoid ExceptionHandlerTest::SetUp() { 98f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid const ::testing::TestInfo* const test_info = 99f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid ::testing::UnitTest::GetInstance()->current_test_info(); 100f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid TCHAR temp_path[MAX_PATH] = { '\0' }; 101f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid TCHAR test_name_wide[MAX_PATH] = { '\0' }; 102f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid // We want the temporary directory to be what the OS returns 103ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com // to us, + the test case name. 104f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid GetTempPath(MAX_PATH, temp_path); 105f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid // THe test case name is exposed to use as a c-style string, 106f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid // But we might be working in UNICODE here on Windows. 107ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com int dwRet = MultiByteToWideChar(CP_ACP, 0, test_info->name(), 108ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com strlen(test_info->name()), 109ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com test_name_wide, 110ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com MAX_PATH); 111f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid if (!dwRet) { 112f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid assert(false); 113f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid } 114f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide); 115f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid CreateDirectory(temp_path_, NULL); 116f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid} 117f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 1188cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comvoid ExceptionHandlerTest::TearDown() { 1198cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com if (!dump_file.empty()) { 1208cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com ::DeleteFile(dump_file.c_str()); 1218cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com dump_file = L""; 1228cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com } 1238cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com if (!full_dump_file.empty()) { 1248cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com ::DeleteFile(full_dump_file.c_str()); 1258cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com full_dump_file = L""; 1268cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com } 1278cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com} 1288cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 1298cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comBOOL ExceptionHandlerTest::DoesPathExist(const TCHAR *path_name) { 130f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid DWORD flags = GetFileAttributes(path_name); 131f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid if (flags == INVALID_FILE_ATTRIBUTES) { 132f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid return FALSE; 133f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid } 134f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid return TRUE; 135f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid} 136f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 1379220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// static 1388cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comvoid ExceptionHandlerTest::ClientDumpCallback( 1398cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com void *dump_context, 1408cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com const google_breakpad::ClientInfo *client_info, 1419220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek const wstring *dump_path) { 1428cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com dump_file = *dump_path; 1438cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // Create the full dump file name from the dump path. 1448cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com full_dump_file = dump_file.substr(0, dump_file.length() - 4) + L"-full.dmp"; 145f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid} 146f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 1479220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// static 1489220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekbool ExceptionHandlerTest::DumpCallback(const wchar_t* dump_path, 1499220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek const wchar_t* minidump_id, 1509220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek void* context, 1519220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek EXCEPTION_POINTERS* exinfo, 1529220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek MDRawAssertionInfo* assertion, 1539220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek bool succeeded) { 1549220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek dump_file = dump_path; 1559220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek dump_file += L"\\"; 1569220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek dump_file += minidump_id; 1579220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek dump_file += L".dmp"; 1589220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek return succeeded; 1599220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek} 1609220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek 161bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comvoid ExceptionHandlerTest::DoCrashInvalidParameter() { 162ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com google_breakpad::ExceptionHandler *exc = 1638cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com new google_breakpad::ExceptionHandler( 1648cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com temp_path_, NULL, NULL, NULL, 1658cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER, 1668cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com kFullDumpType, kPipeName, NULL); 167f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 1688cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // Disable the message box for assertions 1698cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com _CrtSetReportMode(_CRT_ASSERT, 0); 170f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 171f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid // Although this is executing in the child process of the death test, 172ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com // if it's not true we'll still get an error rather than the crash 173f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid // being expected. 174f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid ASSERT_TRUE(exc->IsOutOfProcess()); 1758cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com printf(NULL); 176f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid} 177f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 178bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 179bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comstruct PureVirtualCallBase { 180bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com PureVirtualCallBase() { 181bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // We have to reinterpret so the linker doesn't get confused because the 182bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // method isn't defined. 183bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com reinterpret_cast<PureVirtualCallBase*>(this)->PureFunction(); 184bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com } 185bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com virtual ~PureVirtualCallBase() {} 186bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com virtual void PureFunction() const = 0; 187bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com}; 188bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comstruct PureVirtualCall : public PureVirtualCallBase { 189bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com PureVirtualCall() { PureFunction(); } 190bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com virtual void PureFunction() const {} 191bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com}; 192bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 193bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comvoid ExceptionHandlerTest::DoCrashPureVirtualCall() { 194bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com google_breakpad::ExceptionHandler *exc = 195bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com new google_breakpad::ExceptionHandler( 196bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com temp_path_, NULL, NULL, NULL, 197bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com google_breakpad::ExceptionHandler::HANDLER_PURECALL, 198bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com kFullDumpType, kPipeName, NULL); 199bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 200bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // Disable the message box for assertions 201bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com _CrtSetReportMode(_CRT_ASSERT, 0); 202bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 203bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // Although this is executing in the child process of the death test, 204bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // if it's not true we'll still get an error rather than the crash 205bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // being expected. 206bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com ASSERT_TRUE(exc->IsOutOfProcess()); 207bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 208bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // Create a new frame to ensure PureVirtualCall is not optimized to some 209bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // other line in this function. 210bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com { 211bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com PureVirtualCall instance; 212bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com } 213bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com} 214bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 2158cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com// This test validates that the minidump is written correctly. 2168cf0a52becf937650056dad55769a2d85d30f75dhansl@google.comTEST_F(ExceptionHandlerTest, InvalidParameterMiniDumpTest) { 2178cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com ASSERT_TRUE(DoesPathExist(temp_path_)); 218f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid 2198cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // Call with a bad argument 220f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid ASSERT_TRUE(DoesPathExist(temp_path_)); 2219220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek wstring dump_path(temp_path_); 222f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid google_breakpad::CrashGenerationServer server( 2238cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, true, 2248cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com &dump_path); 2258cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 2268cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com ASSERT_TRUE(dump_file.empty() && full_dump_file.empty()); 227ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com 228f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid // This HAS to be EXPECT_, because when this test case is executed in the 229f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid // child process, the server registration will fail due to the named pipe 230f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid // being the same. 231f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid EXPECT_TRUE(server.Start()); 232bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_EXIT(DoCrashInvalidParameter(), ::testing::ExitedWithCode(0), ""); 233bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty()); 234bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com ASSERT_TRUE(DoesPathExist(dump_file.c_str())); 235bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 236bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // Verify the dump for infos. 237bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com DumpAnalysis mini(dump_file); 238bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com DumpAnalysis full(full_dump_file); 239bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 240bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // The dump should have all of these streams. 241bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(mini.HasStream(ThreadListStream)); 242bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(full.HasStream(ThreadListStream)); 243bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(mini.HasStream(ModuleListStream)); 244bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(full.HasStream(ModuleListStream)); 245bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(mini.HasStream(ExceptionStream)); 246bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(full.HasStream(ExceptionStream)); 247bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(mini.HasStream(SystemInfoStream)); 248bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(full.HasStream(SystemInfoStream)); 249bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(mini.HasStream(MiscInfoStream)); 250bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(full.HasStream(MiscInfoStream)); 251bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(mini.HasStream(HandleDataStream)); 252bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(full.HasStream(HandleDataStream)); 253bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 254bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // We expect PEB and TEBs in this dump. 255bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(mini.HasTebs() || full.HasTebs()); 256bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(mini.HasPeb() || full.HasPeb()); 257bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 258bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // Minidump should have a memory listing, but no 64-bit memory. 259bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(mini.HasStream(MemoryListStream)); 260bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(mini.HasStream(Memory64ListStream)); 261bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 262bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(full.HasStream(MemoryListStream)); 263bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(full.HasStream(Memory64ListStream)); 264bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 265bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // This is the only place we don't use OR because we want both not 266bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // to have the streams. 267bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(mini.HasStream(ThreadExListStream)); 268bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(full.HasStream(ThreadExListStream)); 269bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(mini.HasStream(CommentStreamA)); 270bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(full.HasStream(CommentStreamA)); 271bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(mini.HasStream(CommentStreamW)); 272bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(full.HasStream(CommentStreamW)); 273bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(mini.HasStream(FunctionTableStream)); 274bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(full.HasStream(FunctionTableStream)); 275bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); 276bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(full.HasStream(MemoryInfoListStream)); 277bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); 278bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(full.HasStream(ThreadInfoListStream)); 279bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); 280bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(full.HasStream(HandleOperationListStream)); 281bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(mini.HasStream(TokenStream)); 282bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_FALSE(full.HasStream(TokenStream)); 283bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com} 284bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 285bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 286bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com// This test validates that the minidump is written correctly. 287bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.comTEST_F(ExceptionHandlerTest, PureVirtualCallMiniDumpTest) { 288bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com ASSERT_TRUE(DoesPathExist(temp_path_)); 289bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 290bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // Call with a bad argument 291bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com ASSERT_TRUE(DoesPathExist(temp_path_)); 2929220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek wstring dump_path(temp_path_); 293bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com google_breakpad::CrashGenerationServer server( 294bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, true, 295bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com &dump_path); 296bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 297bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com ASSERT_TRUE(dump_file.empty() && full_dump_file.empty()); 298bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com 299bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // This HAS to be EXPECT_, because when this test case is executed in the 300bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // child process, the server registration will fail due to the named pipe 301bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com // being the same. 302bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_TRUE(server.Start()); 303bcf885c8079b1742bfd93de722afceb26237ce4fhansl@google.com EXPECT_EXIT(DoCrashPureVirtualCall(), ::testing::ExitedWithCode(0), ""); 3048cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty()); 3058cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com ASSERT_TRUE(DoesPathExist(dump_file.c_str())); 3068cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 3078cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // Verify the dump for infos. 3088cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com DumpAnalysis mini(dump_file); 3098cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com DumpAnalysis full(full_dump_file); 3108cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 3118cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // The dump should have all of these streams. 3128cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(mini.HasStream(ThreadListStream)); 3138cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(full.HasStream(ThreadListStream)); 3148cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(mini.HasStream(ModuleListStream)); 3158cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(full.HasStream(ModuleListStream)); 3168cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(mini.HasStream(ExceptionStream)); 3178cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(full.HasStream(ExceptionStream)); 3188cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(mini.HasStream(SystemInfoStream)); 3198cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(full.HasStream(SystemInfoStream)); 3208cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(mini.HasStream(MiscInfoStream)); 3218cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(full.HasStream(MiscInfoStream)); 3228cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(mini.HasStream(HandleDataStream)); 3238cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(full.HasStream(HandleDataStream)); 3248cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 3258cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // We expect PEB and TEBs in this dump. 3268cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(mini.HasTebs() || full.HasTebs()); 3278cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(mini.HasPeb() || full.HasPeb()); 3288cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 3298cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // Minidump should have a memory listing, but no 64-bit memory. 3308cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(mini.HasStream(MemoryListStream)); 3318cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(mini.HasStream(Memory64ListStream)); 3328cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 3338cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(full.HasStream(MemoryListStream)); 3348cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_TRUE(full.HasStream(Memory64ListStream)); 3358cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com 3368cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // This is the only place we don't use OR because we want both not 3378cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com // to have the streams. 3388cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(mini.HasStream(ThreadExListStream)); 3398cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(full.HasStream(ThreadExListStream)); 3408cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(mini.HasStream(CommentStreamA)); 3418cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(full.HasStream(CommentStreamA)); 3428cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(mini.HasStream(CommentStreamW)); 3438cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(full.HasStream(CommentStreamW)); 3448cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(mini.HasStream(FunctionTableStream)); 3458cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(full.HasStream(FunctionTableStream)); 3468cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); 3478cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(full.HasStream(MemoryInfoListStream)); 3488cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); 3498cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(full.HasStream(ThreadInfoListStream)); 3508cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); 3518cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(full.HasStream(HandleOperationListStream)); 3528cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(mini.HasStream(TokenStream)); 3538cf0a52becf937650056dad55769a2d85d30f75dhansl@google.com EXPECT_FALSE(full.HasStream(TokenStream)); 354f4f249e54475c88e5c0092633c2c31dd9ce18712nealsid} 3559220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek 3569220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// Test that writing a minidump produces a valid minidump containing 3579220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek// some expected structures. 3589220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarekTEST_F(ExceptionHandlerTest, WriteMinidumpTest) { 3599220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek ExceptionHandler handler(temp_path_, 3609220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek NULL, 3619220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek DumpCallback, 3629220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek NULL, 3639220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek ExceptionHandler::HANDLER_ALL); 3649220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek ASSERT_TRUE(handler.WriteMinidump()); 3659220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek ASSERT_FALSE(dump_file.empty()); 3669220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek 3679220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek string minidump_filename; 3689220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file, 3699220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek &minidump_filename)); 3709220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek 3719220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek // Read the minidump and verify some info. 3729220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek Minidump minidump(minidump_filename); 3739220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek ASSERT_TRUE(minidump.Read()); 3749220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek //TODO(ted): more comprehensive tests... 375ffedcd49454ce56a8136489c2e60bb840e6205dahansl@google.com} 3769220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek 3779220e0baf1f59c067e82495d697306cc460c4e8cted.mielczarek} // namespace 378