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 |