OLD | NEW |
(Empty) | |
| 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 |
| 15 #include "handler/win/registration_server.h" |
| 16 |
| 17 #include <windows.h> |
| 18 |
| 19 #include <vector> |
| 20 |
| 21 #include "base/basictypes.h" |
| 22 #include "base/strings/string16.h" |
| 23 #include "client/crashpad_info.h" |
| 24 #include "client/registration_protocol_win.h" |
| 25 #include "gtest/gtest.h" |
| 26 #include "handler/win/registration_test_base.h" |
| 27 #include "util/thread/thread.h" |
| 28 #include "util/win/address_types.h" |
| 29 #include "util/win/scoped_handle.h" |
| 30 |
| 31 namespace crashpad { |
| 32 namespace test { |
| 33 namespace { |
| 34 |
| 35 // Runs the RegistrationServer on a background thread. |
| 36 class RunServerThread : public Thread { |
| 37 public: |
| 38 // Instantiates a thread which will invoke server->Run(pipe_name, delegate). |
| 39 RunServerThread(RegistrationServer* server, |
| 40 const base::string16& pipe_name, |
| 41 RegistrationServer::Delegate* delegate) |
| 42 : server_(server), pipe_name_(pipe_name), delegate_(delegate) {} |
| 43 ~RunServerThread() override {} |
| 44 |
| 45 private: |
| 46 // Thread: |
| 47 void ThreadMain() override { server_->Run(pipe_name_, delegate_); } |
| 48 |
| 49 RegistrationServer* server_; |
| 50 base::string16 pipe_name_; |
| 51 RegistrationServer::Delegate* delegate_; |
| 52 |
| 53 DISALLOW_COPY_AND_ASSIGN(RunServerThread); |
| 54 }; |
| 55 |
| 56 class RegistrationServerTest : public RegistrationTestBase { |
| 57 public: |
| 58 RegistrationServerTest() |
| 59 : server_(), server_thread_(&server_, pipe_name(), &delegate()) {} |
| 60 |
| 61 RegistrationServer& server() { return server_; } |
| 62 Thread& server_thread() { return server_thread_; } |
| 63 |
| 64 private: |
| 65 RegistrationServer server_; |
| 66 RunServerThread server_thread_; |
| 67 |
| 68 DISALLOW_COPY_AND_ASSIGN(RegistrationServerTest); |
| 69 }; |
| 70 |
| 71 // During destruction, ensures that the server is stopped and the background |
| 72 // thread joined. |
| 73 class ScopedStopServerAndJoinThread { |
| 74 public: |
| 75 explicit ScopedStopServerAndJoinThread(RegistrationServer* server, |
| 76 Thread* thread) |
| 77 : server_(server), thread_(thread) {} |
| 78 ~ScopedStopServerAndJoinThread() { |
| 79 server_->Stop(); |
| 80 thread_->Join(); |
| 81 } |
| 82 |
| 83 private: |
| 84 RegistrationServer* server_; |
| 85 Thread* thread_; |
| 86 DISALLOW_COPY_AND_ASSIGN(ScopedStopServerAndJoinThread); |
| 87 }; |
| 88 |
| 89 TEST_F(RegistrationServerTest, Instantiate) { |
| 90 } |
| 91 |
| 92 TEST_F(RegistrationServerTest, StartAndStop) { |
| 93 server_thread().Start(); |
| 94 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread( |
| 95 &server(), &server_thread()); |
| 96 ASSERT_NO_FATAL_FAILURE(delegate().WaitForStart()); |
| 97 } |
| 98 |
| 99 TEST_F(RegistrationServerTest, StopWhileConnected) { |
| 100 ScopedFileHANDLE connection; |
| 101 { |
| 102 server_thread().Start(); |
| 103 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread( |
| 104 &server(), &server_thread()); |
| 105 ASSERT_NO_FATAL_FAILURE(delegate().WaitForStart()); |
| 106 connection = Connect(); |
| 107 ASSERT_TRUE(connection.is_valid()); |
| 108 // Leaving this scope causes the server to be stopped, while the connection |
| 109 // is still open. |
| 110 } |
| 111 } |
| 112 |
| 113 TEST_F(RegistrationServerTest, Register) { |
| 114 RegistrationRequest request = {0}; |
| 115 RegistrationResponse response = {0}; |
| 116 CrashpadInfo crashpad_info; |
| 117 request.client_process_id = GetCurrentProcessId(); |
| 118 request.crashpad_info_address = |
| 119 reinterpret_cast<WinVMAddress>(&crashpad_info); |
| 120 |
| 121 server_thread().Start(); |
| 122 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread( |
| 123 &server(), &server_thread()); |
| 124 |
| 125 ASSERT_NO_FATAL_FAILURE(delegate().WaitForStart()); |
| 126 |
| 127 ASSERT_TRUE(SendRequest(Connect(), &request, sizeof(request), &response)); |
| 128 |
| 129 ASSERT_EQ(1, delegate().registered_processes().size()); |
| 130 VerifyRegistration(*delegate().registered_processes()[0], request, response); |
| 131 } |
| 132 |
| 133 TEST_F(RegistrationServerTest, ForgedClientId) { |
| 134 // Skip this test on pre-Vista as the forged PID detection is not supported |
| 135 // there. |
| 136 OSVERSIONINFO vi = {0}; |
| 137 vi.dwOSVersionInfoSize = sizeof(vi); |
| 138 GetVersionEx(&vi); |
| 139 if (vi.dwMajorVersion < 6) |
| 140 return; |
| 141 |
| 142 RegistrationRequest request = {0}; |
| 143 RegistrationResponse response = {0}; |
| 144 CrashpadInfo crashpad_info; |
| 145 // Note that we forge the PID here. |
| 146 request.client_process_id = GetCurrentProcessId() + 1; |
| 147 request.crashpad_info_address = |
| 148 reinterpret_cast<WinVMAddress>(&crashpad_info); |
| 149 |
| 150 server_thread().Start(); |
| 151 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread( |
| 152 &server(), &server_thread()); |
| 153 |
| 154 ASSERT_NO_FATAL_FAILURE(delegate().WaitForStart()); |
| 155 |
| 156 ASSERT_FALSE(SendRequest(Connect(), &request, sizeof(request), &response)); |
| 157 ASSERT_EQ(0, delegate().registered_processes().size()); |
| 158 |
| 159 // Correct the PID and verify that this was the only reason we failed. |
| 160 request.client_process_id = GetCurrentProcessId(); |
| 161 ASSERT_TRUE(SendRequest(Connect(), &request, sizeof(request), &response)); |
| 162 ASSERT_EQ(1, delegate().registered_processes().size()); |
| 163 VerifyRegistration(*delegate().registered_processes()[0], request, response); |
| 164 } |
| 165 |
| 166 TEST_F(RegistrationServerTest, RegisterClientFails) { |
| 167 RegistrationRequest request = {0}; |
| 168 RegistrationResponse response = {0}; |
| 169 CrashpadInfo crashpad_info; |
| 170 request.client_process_id = GetCurrentProcessId(); |
| 171 request.crashpad_info_address = |
| 172 reinterpret_cast<WinVMAddress>(&crashpad_info); |
| 173 |
| 174 server_thread().Start(); |
| 175 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread( |
| 176 &server(), &server_thread()); |
| 177 |
| 178 ASSERT_NO_FATAL_FAILURE(delegate().WaitForStart()); |
| 179 |
| 180 // Simulate some failures |
| 181 delegate().set_fail_mode(true); |
| 182 for (int i = 0; i < 10; ++i) { |
| 183 ASSERT_FALSE(SendRequest(Connect(), &request, sizeof(request), &response)); |
| 184 ASSERT_EQ(0, delegate().registered_processes().size()); |
| 185 } |
| 186 |
| 187 // Now verify that a valid response may still be processed. |
| 188 delegate().set_fail_mode(false); |
| 189 ASSERT_TRUE(SendRequest(Connect(), &request, sizeof(request), &response)); |
| 190 |
| 191 ASSERT_EQ(1, delegate().registered_processes().size()); |
| 192 VerifyRegistration(*delegate().registered_processes()[0], request, response); |
| 193 } |
| 194 |
| 195 TEST_F(RegistrationServerTest, BadRequests) { |
| 196 server_thread().Start(); |
| 197 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread( |
| 198 &server(), &server_thread()); |
| 199 ASSERT_NO_FATAL_FAILURE(delegate().WaitForStart()); |
| 200 |
| 201 RegistrationRequest request = {0}; |
| 202 RegistrationResponse response = {0}; |
| 203 CrashpadInfo crashpad_info; |
| 204 request.client_process_id = GetCurrentProcessId(); |
| 205 request.crashpad_info_address = |
| 206 reinterpret_cast<WinVMAddress>(&crashpad_info); |
| 207 |
| 208 // Concatenate a valid request with a single byte of garbage. |
| 209 std::vector<char> extra_long; |
| 210 extra_long.insert(extra_long.begin(), |
| 211 reinterpret_cast<char*>(&request), |
| 212 reinterpret_cast<char*>(&request) + sizeof(request)); |
| 213 extra_long.push_back('x'); |
| 214 |
| 215 for (int i = 0; i < 10; ++i) { |
| 216 ASSERT_FALSE(SendRequest(Connect(), "a", 1, &response)); |
| 217 ASSERT_FALSE(SendRequest( |
| 218 Connect(), extra_long.data(), extra_long.size(), &response)); |
| 219 ASSERT_TRUE(Connect().is_valid()); |
| 220 } |
| 221 |
| 222 // Now verify that a valid response may still be processed. |
| 223 |
| 224 ASSERT_TRUE(SendRequest(Connect(), &request, sizeof(request), &response)); |
| 225 |
| 226 ASSERT_EQ(1, delegate().registered_processes().size()); |
| 227 VerifyRegistration(*delegate().registered_processes()[0], request, response); |
| 228 } |
| 229 |
| 230 TEST_F(RegistrationServerTest, OverlappingRequests) { |
| 231 server_thread().Start(); |
| 232 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread( |
| 233 &server(), &server_thread()); |
| 234 ASSERT_NO_FATAL_FAILURE(delegate().WaitForStart()); |
| 235 |
| 236 RegistrationRequest request = {0}; |
| 237 RegistrationResponse response_1 = {0}; |
| 238 RegistrationResponse response_2 = {0}; |
| 239 RegistrationResponse response_3 = {0}; |
| 240 CrashpadInfo crashpad_info; |
| 241 request.client_process_id = GetCurrentProcessId(); |
| 242 request.crashpad_info_address = |
| 243 reinterpret_cast<WinVMAddress>(&crashpad_info); |
| 244 |
| 245 ScopedFileHANDLE connection_1 = Connect(); |
| 246 ASSERT_TRUE(connection_1.is_valid()); |
| 247 ScopedFileHANDLE connection_2 = Connect(); |
| 248 ASSERT_TRUE(connection_2.is_valid()); |
| 249 ScopedFileHANDLE connection_3 = Connect(); |
| 250 ASSERT_TRUE(connection_3.is_valid()); |
| 251 |
| 252 ASSERT_FALSE(SendRequest(connection_1.Pass(), "a", 1, &response_1)); |
| 253 |
| 254 ASSERT_TRUE( |
| 255 SendRequest(connection_2.Pass(), &request, sizeof(request), &response_2)); |
| 256 |
| 257 ASSERT_TRUE(Connect().is_valid()); |
| 258 |
| 259 ASSERT_TRUE( |
| 260 SendRequest(connection_3.Pass(), &request, sizeof(request), &response_3)); |
| 261 |
| 262 ASSERT_EQ(2, delegate().registered_processes().size()); |
| 263 VerifyRegistration( |
| 264 *delegate().registered_processes()[0], request, response_2); |
| 265 VerifyRegistration( |
| 266 *delegate().registered_processes()[1], request, response_3); |
| 267 } |
| 268 |
| 269 } // namespace |
| 270 } // namespace test |
| 271 } // namespace crashpad |
OLD | NEW |