aboutsummaryrefslogtreecommitdiff
path: root/src/client/windows/unittests/crash_generation_server_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/windows/unittests/crash_generation_server_test.cc')
-rw-r--r--src/client/windows/unittests/crash_generation_server_test.cc596
1 files changed, 298 insertions, 298 deletions
diff --git a/src/client/windows/unittests/crash_generation_server_test.cc b/src/client/windows/unittests/crash_generation_server_test.cc
index 75d0be97..ce49439c 100644
--- a/src/client/windows/unittests/crash_generation_server_test.cc
+++ b/src/client/windows/unittests/crash_generation_server_test.cc
@@ -1,298 +1,298 @@
-// Copyright 2010, 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 "testing/gtest/include/gtest/gtest.h"
-#include "testing/include/gmock/gmock.h"
-
-#include "client/windows/crash_generation/crash_generation_server.h"
-#include "client/windows/common/ipc_protocol.h"
-
-using testing::_;
-
-namespace {
-
-const wchar_t kPipeName[] =
- L"\\\\.\\pipe\\CrashGenerationServerTest\\TestCaseServer";
-
-const DWORD kPipeDesiredAccess = FILE_READ_DATA |
- FILE_WRITE_DATA |
- FILE_WRITE_ATTRIBUTES;
-
-const DWORD kPipeFlagsAndAttributes = SECURITY_IDENTIFICATION |
- SECURITY_SQOS_PRESENT;
-
-const DWORD kPipeMode = PIPE_READMODE_MESSAGE;
-
-int kCustomInfoCount = 2;
-
-google_breakpad::CustomInfoEntry kCustomInfoEntries[] = {
- google_breakpad::CustomInfoEntry(L"prod", L"CrashGenerationServerTest"),
- google_breakpad::CustomInfoEntry(L"ver", L"1.0"),
-};
-
-class CrashGenerationServerTest : public ::testing::Test {
- public:
- CrashGenerationServerTest()
- : crash_generation_server_(kPipeName,
- NULL,
- CallOnClientConnected, &mock_callbacks_,
- CallOnClientDumpRequested, &mock_callbacks_,
- CallOnClientExited, &mock_callbacks_,
- false,
- NULL),
- thread_id_(0),
- exception_pointers_(NULL) {
- memset(&assert_info_, 0, sizeof(assert_info_));
- }
-
- protected:
- class MockCrashGenerationServerCallbacks {
- public:
- MOCK_METHOD1(OnClientConnected,
- void(const google_breakpad::ClientInfo* client_info));
- MOCK_METHOD2(OnClientDumpRequested,
- void(const google_breakpad::ClientInfo* client_info,
- const std::wstring* file_path));
- MOCK_METHOD1(OnClientExited,
- void(const google_breakpad::ClientInfo* client_info));
- };
-
- enum ClientFault {
- NO_FAULT,
- CLOSE_AFTER_CONNECT,
- SEND_INVALID_REGISTRATION,
- TRUNCATE_REGISTRATION,
- CLOSE_AFTER_REGISTRATION,
- RESPONSE_BUFFER_TOO_SMALL,
- CLOSE_AFTER_RESPONSE,
- SEND_INVALID_ACK
- };
-
- void SetUp() {
- ASSERT_TRUE(crash_generation_server_.Start());
- }
-
- void FaultyClient(ClientFault fault_type) {
- HANDLE pipe = CreateFile(kPipeName,
- kPipeDesiredAccess,
- 0,
- NULL,
- OPEN_EXISTING,
- kPipeFlagsAndAttributes,
- NULL);
-
- if (pipe == INVALID_HANDLE_VALUE) {
- ASSERT_EQ(ERROR_PIPE_BUSY, GetLastError());
-
- // Cannot continue retrying if wait on pipe fails.
- ASSERT_TRUE(WaitNamedPipe(kPipeName, 500));
-
- pipe = CreateFile(kPipeName,
- kPipeDesiredAccess,
- 0,
- NULL,
- OPEN_EXISTING,
- kPipeFlagsAndAttributes,
- NULL);
- }
-
- ASSERT_NE(pipe, INVALID_HANDLE_VALUE);
-
- DWORD mode = kPipeMode;
- ASSERT_TRUE(SetNamedPipeHandleState(pipe, &mode, NULL, NULL));
-
- DoFaultyClient(fault_type, pipe);
-
- CloseHandle(pipe);
- }
-
- void DoTestFault(ClientFault fault) {
- EXPECT_CALL(mock_callbacks_, OnClientConnected(_)).Times(0);
- ASSERT_NO_FATAL_FAILURE(FaultyClient(fault));
- ASSERT_NO_FATAL_FAILURE(FaultyClient(fault));
- ASSERT_NO_FATAL_FAILURE(FaultyClient(fault));
-
- EXPECT_CALL(mock_callbacks_, OnClientConnected(_));
-
- ASSERT_NO_FATAL_FAILURE(FaultyClient(NO_FAULT));
-
- // Slight hack. The OnClientConnected is only invoked after the ack is
- // received by the server. At that point, the FaultyClient call has already
- // returned. The best way to wait until the server is done handling that is
- // to send one more ping, whose processing will be blocked by delivery of
- // the OnClientConnected message.
- ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT));
- }
-
- MockCrashGenerationServerCallbacks mock_callbacks_;
-
- private:
- // Depends on the caller to successfully open the pipe before invocation and
- // to close it immediately afterwards.
- void DoFaultyClient(ClientFault fault_type, HANDLE pipe) {
- if (fault_type == CLOSE_AFTER_CONNECT) {
- return;
- }
-
- google_breakpad::CustomClientInfo custom_info = {kCustomInfoEntries,
- kCustomInfoCount};
-
- google_breakpad::ProtocolMessage msg(
- fault_type == SEND_INVALID_REGISTRATION ?
- google_breakpad::MESSAGE_TAG_NONE :
- google_breakpad::MESSAGE_TAG_REGISTRATION_REQUEST,
- GetCurrentProcessId(),
- MiniDumpNormal,
- &thread_id_,
- &exception_pointers_,
- &assert_info_,
- custom_info,
- NULL,
- NULL,
- NULL);
-
- DWORD bytes_count = 0;
-
- ASSERT_TRUE(WriteFile(pipe,
- &msg,
- fault_type == TRUNCATE_REGISTRATION ?
- sizeof(msg) / 2 : sizeof(msg),
- &bytes_count,
- NULL));
-
- if (fault_type == CLOSE_AFTER_REGISTRATION) {
- return;
- }
-
- google_breakpad::ProtocolMessage reply;
-
- if (!ReadFile(pipe,
- &reply,
- fault_type == RESPONSE_BUFFER_TOO_SMALL ?
- sizeof(google_breakpad::ProtocolMessage) / 2 :
- sizeof(google_breakpad::ProtocolMessage),
- &bytes_count,
- NULL)) {
- switch (fault_type) {
- case TRUNCATE_REGISTRATION:
- case RESPONSE_BUFFER_TOO_SMALL:
- case SEND_INVALID_REGISTRATION:
- return;
-
- default:
- FAIL() << "Unexpectedly failed to register.";
- }
- }
-
- if (fault_type == CLOSE_AFTER_RESPONSE) {
- return;
- }
-
- google_breakpad::ProtocolMessage ack_msg;
- ack_msg.tag = google_breakpad::MESSAGE_TAG_REGISTRATION_ACK;
-
- ASSERT_TRUE(WriteFile(pipe,
- &ack_msg,
- SEND_INVALID_ACK ?
- sizeof(ack_msg) : sizeof(ack_msg) / 2,
- &bytes_count,
- NULL));
-
- return;
- }
-
- static void CallOnClientConnected(
- void* context, const google_breakpad::ClientInfo* client_info) {
- static_cast<MockCrashGenerationServerCallbacks*>(context)->
- OnClientConnected(client_info);
- }
-
- static void CallOnClientDumpRequested(
- void* context,
- const google_breakpad::ClientInfo* client_info,
- const std::wstring* file_path) {
- static_cast<MockCrashGenerationServerCallbacks*>(context)->
- OnClientDumpRequested(client_info, file_path);
- }
-
- static void CallOnClientExited(
- void* context, const google_breakpad::ClientInfo* client_info) {
- static_cast<MockCrashGenerationServerCallbacks*>(context)->
- OnClientExited(client_info);
- }
-
- DWORD thread_id_;
- EXCEPTION_POINTERS* exception_pointers_;
- MDRawAssertionInfo assert_info_;
-
- google_breakpad::CrashGenerationServer crash_generation_server_;
-};
-
-TEST_F(CrashGenerationServerTest, PingServerTest) {
- DoTestFault(CLOSE_AFTER_CONNECT);
-}
-
-TEST_F(CrashGenerationServerTest, InvalidRegistration) {
- DoTestFault(SEND_INVALID_REGISTRATION);
-}
-
-TEST_F(CrashGenerationServerTest, TruncateRegistration) {
- DoTestFault(TRUNCATE_REGISTRATION);
-}
-
-TEST_F(CrashGenerationServerTest, CloseAfterRegistration) {
- DoTestFault(CLOSE_AFTER_REGISTRATION);
-}
-
-TEST_F(CrashGenerationServerTest, ResponseBufferTooSmall) {
- DoTestFault(RESPONSE_BUFFER_TOO_SMALL);
-}
-
-TEST_F(CrashGenerationServerTest, CloseAfterResponse) {
- DoTestFault(CLOSE_AFTER_RESPONSE);
-}
-
-// It turns out that, as long as you send one byte, the ACK is accepted and
-// registration succeeds.
-TEST_F(CrashGenerationServerTest, SendInvalidAck) {
- EXPECT_CALL(mock_callbacks_, OnClientConnected(_));
- ASSERT_NO_FATAL_FAILURE(FaultyClient(SEND_INVALID_ACK));
-
- // See DoTestFault for an explanation of this line
- ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT));
-
- EXPECT_CALL(mock_callbacks_, OnClientConnected(_));
- ASSERT_NO_FATAL_FAILURE(FaultyClient(NO_FAULT));
-
- // See DoTestFault for an explanation of this line
- ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT));
-}
-
-} // anonymous namespace
+// Copyright 2010, 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 "testing/gtest/include/gtest/gtest.h"
+#include "testing/include/gmock/gmock.h"
+
+#include "client/windows/crash_generation/crash_generation_server.h"
+#include "client/windows/common/ipc_protocol.h"
+
+using testing::_;
+
+namespace {
+
+const wchar_t kPipeName[] =
+ L"\\\\.\\pipe\\CrashGenerationServerTest\\TestCaseServer";
+
+const DWORD kPipeDesiredAccess = FILE_READ_DATA |
+ FILE_WRITE_DATA |
+ FILE_WRITE_ATTRIBUTES;
+
+const DWORD kPipeFlagsAndAttributes = SECURITY_IDENTIFICATION |
+ SECURITY_SQOS_PRESENT;
+
+const DWORD kPipeMode = PIPE_READMODE_MESSAGE;
+
+int kCustomInfoCount = 2;
+
+google_breakpad::CustomInfoEntry kCustomInfoEntries[] = {
+ google_breakpad::CustomInfoEntry(L"prod", L"CrashGenerationServerTest"),
+ google_breakpad::CustomInfoEntry(L"ver", L"1.0"),
+};
+
+class CrashGenerationServerTest : public ::testing::Test {
+ public:
+ CrashGenerationServerTest()
+ : crash_generation_server_(kPipeName,
+ NULL,
+ CallOnClientConnected, &mock_callbacks_,
+ CallOnClientDumpRequested, &mock_callbacks_,
+ CallOnClientExited, &mock_callbacks_,
+ false,
+ NULL),
+ thread_id_(0),
+ exception_pointers_(NULL) {
+ memset(&assert_info_, 0, sizeof(assert_info_));
+ }
+
+ protected:
+ class MockCrashGenerationServerCallbacks {
+ public:
+ MOCK_METHOD1(OnClientConnected,
+ void(const google_breakpad::ClientInfo* client_info));
+ MOCK_METHOD2(OnClientDumpRequested,
+ void(const google_breakpad::ClientInfo* client_info,
+ const std::wstring* file_path));
+ MOCK_METHOD1(OnClientExited,
+ void(const google_breakpad::ClientInfo* client_info));
+ };
+
+ enum ClientFault {
+ NO_FAULT,
+ CLOSE_AFTER_CONNECT,
+ SEND_INVALID_REGISTRATION,
+ TRUNCATE_REGISTRATION,
+ CLOSE_AFTER_REGISTRATION,
+ RESPONSE_BUFFER_TOO_SMALL,
+ CLOSE_AFTER_RESPONSE,
+ SEND_INVALID_ACK
+ };
+
+ void SetUp() {
+ ASSERT_TRUE(crash_generation_server_.Start());
+ }
+
+ void FaultyClient(ClientFault fault_type) {
+ HANDLE pipe = CreateFile(kPipeName,
+ kPipeDesiredAccess,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ kPipeFlagsAndAttributes,
+ NULL);
+
+ if (pipe == INVALID_HANDLE_VALUE) {
+ ASSERT_EQ(ERROR_PIPE_BUSY, GetLastError());
+
+ // Cannot continue retrying if wait on pipe fails.
+ ASSERT_TRUE(WaitNamedPipe(kPipeName, 500));
+
+ pipe = CreateFile(kPipeName,
+ kPipeDesiredAccess,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ kPipeFlagsAndAttributes,
+ NULL);
+ }
+
+ ASSERT_NE(pipe, INVALID_HANDLE_VALUE);
+
+ DWORD mode = kPipeMode;
+ ASSERT_TRUE(SetNamedPipeHandleState(pipe, &mode, NULL, NULL));
+
+ DoFaultyClient(fault_type, pipe);
+
+ CloseHandle(pipe);
+ }
+
+ void DoTestFault(ClientFault fault) {
+ EXPECT_CALL(mock_callbacks_, OnClientConnected(_)).Times(0);
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(fault));
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(fault));
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(fault));
+
+ EXPECT_CALL(mock_callbacks_, OnClientConnected(_));
+
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(NO_FAULT));
+
+ // Slight hack. The OnClientConnected is only invoked after the ack is
+ // received by the server. At that point, the FaultyClient call has already
+ // returned. The best way to wait until the server is done handling that is
+ // to send one more ping, whose processing will be blocked by delivery of
+ // the OnClientConnected message.
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT));
+ }
+
+ MockCrashGenerationServerCallbacks mock_callbacks_;
+
+ private:
+ // Depends on the caller to successfully open the pipe before invocation and
+ // to close it immediately afterwards.
+ void DoFaultyClient(ClientFault fault_type, HANDLE pipe) {
+ if (fault_type == CLOSE_AFTER_CONNECT) {
+ return;
+ }
+
+ google_breakpad::CustomClientInfo custom_info = {kCustomInfoEntries,
+ kCustomInfoCount};
+
+ google_breakpad::ProtocolMessage msg(
+ fault_type == SEND_INVALID_REGISTRATION ?
+ google_breakpad::MESSAGE_TAG_NONE :
+ google_breakpad::MESSAGE_TAG_REGISTRATION_REQUEST,
+ GetCurrentProcessId(),
+ MiniDumpNormal,
+ &thread_id_,
+ &exception_pointers_,
+ &assert_info_,
+ custom_info,
+ NULL,
+ NULL,
+ NULL);
+
+ DWORD bytes_count = 0;
+
+ ASSERT_TRUE(WriteFile(pipe,
+ &msg,
+ fault_type == TRUNCATE_REGISTRATION ?
+ sizeof(msg) / 2 : sizeof(msg),
+ &bytes_count,
+ NULL));
+
+ if (fault_type == CLOSE_AFTER_REGISTRATION) {
+ return;
+ }
+
+ google_breakpad::ProtocolMessage reply;
+
+ if (!ReadFile(pipe,
+ &reply,
+ fault_type == RESPONSE_BUFFER_TOO_SMALL ?
+ sizeof(google_breakpad::ProtocolMessage) / 2 :
+ sizeof(google_breakpad::ProtocolMessage),
+ &bytes_count,
+ NULL)) {
+ switch (fault_type) {
+ case TRUNCATE_REGISTRATION:
+ case RESPONSE_BUFFER_TOO_SMALL:
+ case SEND_INVALID_REGISTRATION:
+ return;
+
+ default:
+ FAIL() << "Unexpectedly failed to register.";
+ }
+ }
+
+ if (fault_type == CLOSE_AFTER_RESPONSE) {
+ return;
+ }
+
+ google_breakpad::ProtocolMessage ack_msg;
+ ack_msg.tag = google_breakpad::MESSAGE_TAG_REGISTRATION_ACK;
+
+ ASSERT_TRUE(WriteFile(pipe,
+ &ack_msg,
+ SEND_INVALID_ACK ?
+ sizeof(ack_msg) : sizeof(ack_msg) / 2,
+ &bytes_count,
+ NULL));
+
+ return;
+ }
+
+ static void CallOnClientConnected(
+ void* context, const google_breakpad::ClientInfo* client_info) {
+ static_cast<MockCrashGenerationServerCallbacks*>(context)->
+ OnClientConnected(client_info);
+ }
+
+ static void CallOnClientDumpRequested(
+ void* context,
+ const google_breakpad::ClientInfo* client_info,
+ const std::wstring* file_path) {
+ static_cast<MockCrashGenerationServerCallbacks*>(context)->
+ OnClientDumpRequested(client_info, file_path);
+ }
+
+ static void CallOnClientExited(
+ void* context, const google_breakpad::ClientInfo* client_info) {
+ static_cast<MockCrashGenerationServerCallbacks*>(context)->
+ OnClientExited(client_info);
+ }
+
+ DWORD thread_id_;
+ EXCEPTION_POINTERS* exception_pointers_;
+ MDRawAssertionInfo assert_info_;
+
+ google_breakpad::CrashGenerationServer crash_generation_server_;
+};
+
+TEST_F(CrashGenerationServerTest, PingServerTest) {
+ DoTestFault(CLOSE_AFTER_CONNECT);
+}
+
+TEST_F(CrashGenerationServerTest, InvalidRegistration) {
+ DoTestFault(SEND_INVALID_REGISTRATION);
+}
+
+TEST_F(CrashGenerationServerTest, TruncateRegistration) {
+ DoTestFault(TRUNCATE_REGISTRATION);
+}
+
+TEST_F(CrashGenerationServerTest, CloseAfterRegistration) {
+ DoTestFault(CLOSE_AFTER_REGISTRATION);
+}
+
+TEST_F(CrashGenerationServerTest, ResponseBufferTooSmall) {
+ DoTestFault(RESPONSE_BUFFER_TOO_SMALL);
+}
+
+TEST_F(CrashGenerationServerTest, CloseAfterResponse) {
+ DoTestFault(CLOSE_AFTER_RESPONSE);
+}
+
+// It turns out that, as long as you send one byte, the ACK is accepted and
+// registration succeeds.
+TEST_F(CrashGenerationServerTest, SendInvalidAck) {
+ EXPECT_CALL(mock_callbacks_, OnClientConnected(_));
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(SEND_INVALID_ACK));
+
+ // See DoTestFault for an explanation of this line
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT));
+
+ EXPECT_CALL(mock_callbacks_, OnClientConnected(_));
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(NO_FAULT));
+
+ // See DoTestFault for an explanation of this line
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT));
+}
+
+} // anonymous namespace