Integration test for Windows exception handler/minidump generation.
R=hannah tang A=nealsid git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@358 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
6e525cbfbb
commit
f4f249e544
3 changed files with 440 additions and 0 deletions
|
@ -10,6 +10,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_report_sender", "send
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_generation", "crash_generation\crash_generation.vcproj", "{A820AF62-6239-4693-8430-4F516C1838F4}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exception_handler_test", "handler\exception_handler_test\exception_handler_test.vcproj", "{89094A11-CF25-4037-AF43-EACFA751405E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
|
@ -42,6 +44,14 @@ Global
|
|||
{A820AF62-6239-4693-8430-4F516C1838F4}.Release|Win32.Build.0 = Release|Win32
|
||||
{A820AF62-6239-4693-8430-4F516C1838F4}.ReleaseStaticCRT|Win32.ActiveCfg = ReleaseStaticCRT|Win32
|
||||
{A820AF62-6239-4693-8430-4F516C1838F4}.ReleaseStaticCRT|Win32.Build.0 = ReleaseStaticCRT|Win32
|
||||
{89094A11-CF25-4037-AF43-EACFA751405E}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{89094A11-CF25-4037-AF43-EACFA751405E}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{89094A11-CF25-4037-AF43-EACFA751405E}.DebugStaticCRT|Win32.ActiveCfg = Debug|Win32
|
||||
{89094A11-CF25-4037-AF43-EACFA751405E}.DebugStaticCRT|Win32.Build.0 = Debug|Win32
|
||||
{89094A11-CF25-4037-AF43-EACFA751405E}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{89094A11-CF25-4037-AF43-EACFA751405E}.Release|Win32.Build.0 = Release|Win32
|
||||
{89094A11-CF25-4037-AF43-EACFA751405E}.ReleaseStaticCRT|Win32.ActiveCfg = Release|Win32
|
||||
{89094A11-CF25-4037-AF43-EACFA751405E}.ReleaseStaticCRT|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
// 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 "breakpad_googletest_includes.h"
|
||||
#include "client/windows/crash_generation/crash_generation_server.h"
|
||||
#include "client/windows/handler/exception_handler.h"
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
#include <strsafe.h>
|
||||
#include <objbase.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
namespace {
|
||||
const wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashTest\\TestCaseServer";
|
||||
const char kSuccessIndicator[] = "success";
|
||||
const char kFailureIndicator[] = "failure";
|
||||
|
||||
// Utility function to test for a path's existence.
|
||||
BOOL DoesPathExist(const TCHAR *path_name);
|
||||
|
||||
class ExceptionHandlerDeathTest : 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();
|
||||
// A helper method that tests can use to crash.
|
||||
void DoCrash();
|
||||
};
|
||||
|
||||
void ExceptionHandlerDeathTest::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(),
|
||||
(int)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);
|
||||
}
|
||||
|
||||
BOOL DoesPathExist(const TCHAR *path_name) {
|
||||
DWORD flags = GetFileAttributes(path_name);
|
||||
if (flags == INVALID_FILE_ATTRIBUTES) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool MinidumpWrittenCallback(const wchar_t* dump_path,
|
||||
const wchar_t* minidump_id,
|
||||
void* context,
|
||||
EXCEPTION_POINTERS* exinfo,
|
||||
MDRawAssertionInfo* assertion,
|
||||
bool succeeded) {
|
||||
if (succeeded && DoesPathExist(dump_path)) {
|
||||
fprintf(stderr, kSuccessIndicator);
|
||||
} else {
|
||||
fprintf(stderr, kFailureIndicator);
|
||||
}
|
||||
// If we don't flush, the output doesn't get sent before
|
||||
// this process dies.
|
||||
fflush(stderr);
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
TEST_F(ExceptionHandlerDeathTest, InProcTest) {
|
||||
// For the in-proc test, we just need to instantiate an exception
|
||||
// handler in in-proc mode, and crash. Since the entire test is
|
||||
// reexecuted in the child process, we don't have to worry about
|
||||
// the semantics of the exception handler being inherited/not
|
||||
// inherited across CreateProcess().
|
||||
ASSERT_TRUE(DoesPathExist(temp_path_));
|
||||
google_breakpad::ExceptionHandler *exc =
|
||||
new google_breakpad::ExceptionHandler(
|
||||
temp_path_, NULL, &MinidumpWrittenCallback, NULL,
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL);
|
||||
int *i = NULL;
|
||||
ASSERT_DEATH((*i)++, kSuccessIndicator);
|
||||
delete exc;
|
||||
}
|
||||
|
||||
static bool gDumpCallbackCalled = false;
|
||||
|
||||
void clientDumpCallback(void *dump_context,
|
||||
const google_breakpad::ClientInfo *client_info,
|
||||
const std::wstring *dump_path){
|
||||
|
||||
gDumpCallbackCalled = true;
|
||||
}
|
||||
|
||||
void ExceptionHandlerDeathTest::DoCrash() {
|
||||
google_breakpad::ExceptionHandler *exc =
|
||||
new google_breakpad::ExceptionHandler(
|
||||
temp_path_, NULL, NULL, NULL,
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL, MiniDumpNormal, kPipeName,
|
||||
NULL);
|
||||
// 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());
|
||||
int *i = NULL;
|
||||
printf("%d\n", (*i)++);
|
||||
}
|
||||
|
||||
TEST_F(ExceptionHandlerDeathTest, OutOfProcTest) {
|
||||
// We can take advantage of a detail of google test here to save some
|
||||
// complexity in testing: when you do a death test, it actually forks.
|
||||
// So we can make the main test harness the crash generation server,
|
||||
// and call ASSERT_DEATH on a NULL dereference, it to expecting test
|
||||
// the out of process scenario, since it's happening in a different
|
||||
// process! This is different from the above because, above, we pass
|
||||
// a NULL pipe name, and we also don't start a crash generation server.
|
||||
|
||||
ASSERT_TRUE(DoesPathExist(temp_path_));
|
||||
std::wstring dump_path(temp_path_);
|
||||
google_breakpad::CrashGenerationServer server(
|
||||
kPipeName, NULL, NULL, NULL, &clientDumpCallback, NULL, NULL, NULL, true,
|
||||
&dump_path);
|
||||
|
||||
// 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_FALSE(gDumpCallbackCalled);
|
||||
ASSERT_DEATH(this->DoCrash(), "");
|
||||
EXPECT_TRUE(gDumpCallbackCalled);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,266 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="exception_handler_test"
|
||||
ProjectGUID="{89094A11-CF25-4037-AF43-EACFA751405E}"
|
||||
RootNamespace="exception_handler_test"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description=""
|
||||
CommandLine=""
|
||||
Outputs=""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\..\..\testing;..\..\..\..\testing\include;..\..\..\..\testing\gtest;..\..\..\..\testing\gtest\include;..\..\..\..\"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0500"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="Running tests"
|
||||
CommandLine="$(OutDir)\$(ProjectName).exe"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\..\..\testing;..\..\..\..\testing\include;..\..\..\..\testing\gtest;..\..\..\..\testing\gtest\include;..\..\..\..\"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0500"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="Running tests"
|
||||
CommandLine="$(OutDir)\$(ProjectName).exe"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\crash_generation\client_info.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\crash_generation\crash_generation_client.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\crash_generation\crash_generation_server.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\exception_handler.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\exception_handler_test.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\testing\gtest\src\gtest-all.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\testing\gtest\src\gtest_main.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\common\windows\guid_string.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\crash_generation\minidump_generator.cc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\crash_generation\client_info.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\crash_generation\crash_generation_client.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\crash_generation\crash_generation_server.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\exception_handler.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\common\windows\guid_string.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\crash_generation\minidump_generator.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
Loading…
Reference in a new issue