Index: src/client/windows/unittests/exception_handler_test.cc |
=================================================================== |
--- src/client/windows/unittests/exception_handler_test.cc (revision 0) |
+++ src/client/windows/unittests/exception_handler_test.cc (revision 0) |
@@ -0,0 +1,166 @@ |
+// 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 <windows.h> |
+#include <dbghelp.h> |
+#include <strsafe.h> |
+#include <objbase.h> |
+#include <shellapi.h> |
+ |
+#include "../../../breakpad_googletest_includes.h" |
+#include "../crash_generation/crash_generation_server.h" |
+#include "../handler/exception_handler.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(), |
+ 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); |
+} |
+} |
Property changes on: src\client\windows\unittests\exception_handler_test.cc |
___________________________________________________________________ |
Added: svn:executable |
+ * |