exception_handler_server_test.cc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Copyright 2015 The Crashpad Authors. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "util/win/exception_handler_server.h"
  15. #include <windows.h>
  16. #include <sys/types.h>
  17. #include <string>
  18. #include <vector>
  19. #include "base/macros.h"
  20. #include "base/strings/utf_string_conversions.h"
  21. #include "client/crashpad_client.h"
  22. #include "gtest/gtest.h"
  23. #include "test/win/win_child_process.h"
  24. #include "util/thread/thread.h"
  25. #include "util/win/address_types.h"
  26. #include "util/win/registration_protocol_win.h"
  27. #include "util/win/scoped_handle.h"
  28. namespace crashpad {
  29. namespace test {
  30. namespace {
  31. // Runs the ExceptionHandlerServer on a background thread.
  32. class RunServerThread : public Thread {
  33. public:
  34. // Instantiates a thread which will invoke server->Run(delegate).
  35. RunServerThread(ExceptionHandlerServer* server,
  36. ExceptionHandlerServer::Delegate* delegate)
  37. : server_(server), delegate_(delegate) {}
  38. ~RunServerThread() override {}
  39. private:
  40. // Thread:
  41. void ThreadMain() override { server_->Run(delegate_); }
  42. ExceptionHandlerServer* server_;
  43. ExceptionHandlerServer::Delegate* delegate_;
  44. DISALLOW_COPY_AND_ASSIGN(RunServerThread);
  45. };
  46. class TestDelegate : public ExceptionHandlerServer::Delegate {
  47. public:
  48. explicit TestDelegate(HANDLE server_ready) : server_ready_(server_ready) {}
  49. ~TestDelegate() override {}
  50. void ExceptionHandlerServerStarted() override {
  51. SetEvent(server_ready_);
  52. }
  53. unsigned int ExceptionHandlerServerException(
  54. HANDLE process,
  55. WinVMAddress exception_information_address,
  56. WinVMAddress debug_critical_section_address) override {
  57. return 0;
  58. }
  59. void WaitForStart() { WaitForSingleObject(server_ready_, INFINITE); }
  60. private:
  61. HANDLE server_ready_; // weak
  62. DISALLOW_COPY_AND_ASSIGN(TestDelegate);
  63. };
  64. class ExceptionHandlerServerTest : public testing::Test {
  65. public:
  66. ExceptionHandlerServerTest()
  67. : server_(true),
  68. pipe_name_(L"\\\\.\\pipe\\test_name"),
  69. server_ready_(CreateEvent(nullptr, false, false, nullptr)),
  70. delegate_(server_ready_.get()),
  71. server_thread_(&server_, &delegate_) {
  72. server_.SetPipeName(pipe_name_);
  73. }
  74. TestDelegate& delegate() { return delegate_; }
  75. ExceptionHandlerServer& server() { return server_; }
  76. Thread& server_thread() { return server_thread_; }
  77. const std::wstring& pipe_name() const { return pipe_name_; }
  78. private:
  79. ExceptionHandlerServer server_;
  80. std::wstring pipe_name_;
  81. ScopedKernelHANDLE server_ready_;
  82. TestDelegate delegate_;
  83. RunServerThread server_thread_;
  84. DISALLOW_COPY_AND_ASSIGN(ExceptionHandlerServerTest);
  85. };
  86. // During destruction, ensures that the server is stopped and the background
  87. // thread joined.
  88. class ScopedStopServerAndJoinThread {
  89. public:
  90. ScopedStopServerAndJoinThread(ExceptionHandlerServer* server, Thread* thread)
  91. : server_(server), thread_(thread) {}
  92. ~ScopedStopServerAndJoinThread() {
  93. server_->Stop();
  94. thread_->Join();
  95. }
  96. private:
  97. ExceptionHandlerServer* server_;
  98. Thread* thread_;
  99. DISALLOW_COPY_AND_ASSIGN(ScopedStopServerAndJoinThread);
  100. };
  101. TEST_F(ExceptionHandlerServerTest, Instantiate) {
  102. }
  103. TEST_F(ExceptionHandlerServerTest, StartAndStop) {
  104. server_thread().Start();
  105. ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread(
  106. &server(), &server_thread());
  107. ASSERT_NO_FATAL_FAILURE(delegate().WaitForStart());
  108. }
  109. TEST_F(ExceptionHandlerServerTest, StopWhileConnected) {
  110. server_thread().Start();
  111. ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread(
  112. &server(), &server_thread());
  113. ASSERT_NO_FATAL_FAILURE(delegate().WaitForStart());
  114. CrashpadClient client;
  115. client.SetHandlerIPCPipe(pipe_name());
  116. // Leaving this scope causes the server to be stopped, while the connection
  117. // is still open.
  118. }
  119. std::wstring ReadWString(FileHandle handle) {
  120. size_t length = 0;
  121. EXPECT_TRUE(LoggingReadFileExactly(handle, &length, sizeof(length)));
  122. std::wstring str(length, L'\0');
  123. if (length > 0) {
  124. EXPECT_TRUE(
  125. LoggingReadFileExactly(handle, &str[0], length * sizeof(str[0])));
  126. }
  127. return str;
  128. }
  129. void WriteWString(FileHandle handle, const std::wstring& str) {
  130. size_t length = str.size();
  131. EXPECT_TRUE(LoggingWriteFile(handle, &length, sizeof(length)));
  132. if (length > 0) {
  133. EXPECT_TRUE(LoggingWriteFile(handle, &str[0], length * sizeof(str[0])));
  134. }
  135. }
  136. class TestClient final : public WinChildProcess {
  137. public:
  138. TestClient() : WinChildProcess() {}
  139. ~TestClient() {}
  140. private:
  141. int Run() override {
  142. std::wstring pipe_name = ReadWString(ReadPipeHandle());
  143. CrashpadClient client;
  144. if (!client.SetHandlerIPCPipe(pipe_name)) {
  145. ADD_FAILURE();
  146. return EXIT_FAILURE;
  147. }
  148. WriteWString(WritePipeHandle(), L"OK");
  149. return EXIT_SUCCESS;
  150. }
  151. DISALLOW_COPY_AND_ASSIGN(TestClient);
  152. };
  153. TEST_F(ExceptionHandlerServerTest, MultipleConnections) {
  154. WinChildProcess::EntryPoint<TestClient>();
  155. std::unique_ptr<WinChildProcess::Handles> handles_1 =
  156. WinChildProcess::Launch();
  157. std::unique_ptr<WinChildProcess::Handles> handles_2 =
  158. WinChildProcess::Launch();
  159. std::unique_ptr<WinChildProcess::Handles> handles_3 =
  160. WinChildProcess::Launch();
  161. // Must ensure the delegate outlasts the server.
  162. {
  163. server_thread().Start();
  164. ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread(
  165. &server(), &server_thread());
  166. ASSERT_NO_FATAL_FAILURE(delegate().WaitForStart());
  167. // Tell all the children where to connect.
  168. WriteWString(handles_1->write.get(), pipe_name());
  169. WriteWString(handles_2->write.get(), pipe_name());
  170. WriteWString(handles_3->write.get(), pipe_name());
  171. ASSERT_EQ(ReadWString(handles_3->read.get()), L"OK");
  172. ASSERT_EQ(ReadWString(handles_2->read.get()), L"OK");
  173. ASSERT_EQ(ReadWString(handles_1->read.get()), L"OK");
  174. }
  175. }
  176. } // namespace
  177. } // namespace test
  178. } // namespace crashpad