aboutsummaryrefslogtreecommitdiff
path: root/src/client/windows/handler
diff options
context:
space:
mode:
authornealsid <nealsid@4c0a9323-5329-0410-9bdc-e9ce6186880e>2009-07-17 01:15:48 +0000
committernealsid <nealsid@4c0a9323-5329-0410-9bdc-e9ce6186880e>2009-07-17 01:15:48 +0000
commitf4f249e54475c88e5c0092633c2c31dd9ce18712 (patch)
tree8cc35761199b9184f6e39880cca85cd6a9e6a547 /src/client/windows/handler
parentAdd stack-dumping logic to crash_report with -t switch (diff)
downloadbreakpad-f4f249e54475c88e5c0092633c2c31dd9ce18712.tar.xz
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
Diffstat (limited to 'src/client/windows/handler')
-rw-r--r--src/client/windows/handler/exception_handler_test/exception_handler_test.cc164
-rw-r--r--src/client/windows/handler/exception_handler_test/exception_handler_test.vcproj266
2 files changed, 430 insertions, 0 deletions
diff --git a/src/client/windows/handler/exception_handler_test/exception_handler_test.cc b/src/client/windows/handler/exception_handler_test/exception_handler_test.cc
new file mode 100644
index 00000000..2b7377ea
--- /dev/null
+++ b/src/client/windows/handler/exception_handler_test/exception_handler_test.cc
@@ -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);
+}
+} \ No newline at end of file
diff --git a/src/client/windows/handler/exception_handler_test/exception_handler_test.vcproj b/src/client/windows/handler/exception_handler_test/exception_handler_test.vcproj
new file mode 100644
index 00000000..4708d88e
--- /dev/null
+++ b/src/client/windows/handler/exception_handler_test/exception_handler_test.vcproj
@@ -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>