OLD | NEW |
| (Empty) |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "remoting/host/security_key/security_key_ipc_server.h" | |
6 | |
7 #include <memory> | |
8 #include <string> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/bind_helpers.h" | |
12 #include "base/callback.h" | |
13 #include "base/macros.h" | |
14 #include "base/message_loop/message_loop.h" | |
15 #include "base/run_loop.h" | |
16 #include "ipc/ipc_channel.h" | |
17 #include "remoting/host/security_key/fake_security_key_ipc_client.h" | |
18 #include "remoting/host/security_key/security_key_ipc_constants.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | |
20 | |
21 namespace { | |
22 const int kTestConnectionId = 42; | |
23 const int kInitialConnectTimeoutMs = 250; | |
24 const int kConnectionTimeoutErrorDeltaMs = 100; | |
25 const int kLargeMessageSizeBytes = 256 * 1024; | |
26 } // namespace | |
27 | |
28 namespace remoting { | |
29 | |
30 class SecurityKeyIpcServerTest : public testing::Test { | |
31 public: | |
32 SecurityKeyIpcServerTest(); | |
33 ~SecurityKeyIpcServerTest() override; | |
34 | |
35 // Passed to the object used for testing to be called back to signal | |
36 // completion of an IPC channel state change or reception of an IPC message. | |
37 void OperationComplete(); | |
38 | |
39 // Used as a callback to signal receipt of a security key request message. | |
40 void SendRequestToClient(int connection_id, const std::string& data); | |
41 | |
42 protected: | |
43 // Returns a unique IPC channel name which prevents conflicts when running | |
44 // tests concurrently. | |
45 std::string GetUniqueTestChannelName(); | |
46 | |
47 // Waits until the current |run_loop_| instance is signaled, then resets it. | |
48 void WaitForOperationComplete(); | |
49 | |
50 // IPC tests require a valid MessageLoop to run. | |
51 base::MessageLoopForIO message_loop_; | |
52 | |
53 // Used to allow |message_loop_| to run during tests. The instance is reset | |
54 // after each stage of the tests has been completed. | |
55 std::unique_ptr<base::RunLoop> run_loop_; | |
56 | |
57 // The object under test. | |
58 std::unique_ptr<SecurityKeyIpcServer> security_key_ipc_server_; | |
59 | |
60 // Used to validate the object under test uses the correct ID when | |
61 // communicating over the IPC channel. | |
62 int last_connection_id_received_ = -1; | |
63 | |
64 // Stores the contents of the last IPC message received for validation. | |
65 std::string last_message_received_; | |
66 | |
67 private: | |
68 DISALLOW_COPY_AND_ASSIGN(SecurityKeyIpcServerTest); | |
69 }; | |
70 | |
71 SecurityKeyIpcServerTest::SecurityKeyIpcServerTest() | |
72 : run_loop_(new base::RunLoop()) { | |
73 uint32_t peer_session_id = UINT32_MAX; | |
74 #if defined(OS_WIN) | |
75 EXPECT_TRUE(ProcessIdToSessionId(GetCurrentProcessId(), | |
76 reinterpret_cast<DWORD*>(&peer_session_id))); | |
77 #endif // defined(OS_WIN) | |
78 | |
79 security_key_ipc_server_ = remoting::SecurityKeyIpcServer::Create( | |
80 kTestConnectionId, peer_session_id, | |
81 base::TimeDelta::FromMilliseconds(kInitialConnectTimeoutMs), | |
82 base::Bind(&SecurityKeyIpcServerTest::SendRequestToClient, | |
83 base::Unretained(this)), | |
84 base::Bind(&SecurityKeyIpcServerTest::OperationComplete, | |
85 base::Unretained(this))); | |
86 } | |
87 | |
88 SecurityKeyIpcServerTest::~SecurityKeyIpcServerTest() {} | |
89 | |
90 void SecurityKeyIpcServerTest::OperationComplete() { | |
91 run_loop_->Quit(); | |
92 } | |
93 | |
94 void SecurityKeyIpcServerTest::WaitForOperationComplete() { | |
95 run_loop_->Run(); | |
96 run_loop_.reset(new base::RunLoop()); | |
97 } | |
98 | |
99 void SecurityKeyIpcServerTest::SendRequestToClient(int connection_id, | |
100 const std::string& data) { | |
101 last_connection_id_received_ = connection_id; | |
102 last_message_received_ = data; | |
103 OperationComplete(); | |
104 } | |
105 | |
106 std::string SecurityKeyIpcServerTest::GetUniqueTestChannelName() { | |
107 return GetChannelNamePathPrefixForTest() + "Super_Awesome_Test_Channel." + | |
108 IPC::Channel::GenerateUniqueRandomChannelID(); | |
109 } | |
110 | |
111 TEST_F(SecurityKeyIpcServerTest, HandleSingleSecurityKeyRequest) { | |
112 std::string channel_name(GetUniqueTestChannelName()); | |
113 ASSERT_TRUE(security_key_ipc_server_->CreateChannel( | |
114 channel_name, | |
115 /*request_timeout=*/base::TimeDelta::FromMilliseconds(500))); | |
116 | |
117 // Create a fake client and connect to the IPC server channel. | |
118 FakeSecurityKeyIpcClient fake_ipc_client(base::Bind( | |
119 &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this))); | |
120 ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name)); | |
121 WaitForOperationComplete(); | |
122 | |
123 ASSERT_TRUE(fake_ipc_client.ipc_channel_connected()); | |
124 | |
125 // Send a request from the IPC client to the IPC server. | |
126 std::string request_data("Blergh!"); | |
127 fake_ipc_client.SendSecurityKeyRequestViaIpc(request_data); | |
128 WaitForOperationComplete(); | |
129 | |
130 // Verify the request was received. | |
131 ASSERT_EQ(kTestConnectionId, last_connection_id_received_); | |
132 ASSERT_EQ(request_data, last_message_received_); | |
133 | |
134 // Send a response from the IPC server to the IPC client. | |
135 std::string response_data("Blargh!"); | |
136 ASSERT_TRUE(security_key_ipc_server_->SendResponse(response_data)); | |
137 WaitForOperationComplete(); | |
138 | |
139 // Verify the request was received. | |
140 ASSERT_EQ(response_data, fake_ipc_client.last_message_received()); | |
141 | |
142 // Typically the client will be the one to close the connection. | |
143 fake_ipc_client.CloseIpcConnection(); | |
144 } | |
145 | |
146 TEST_F(SecurityKeyIpcServerTest, HandleLargeSecurityKeyRequest) { | |
147 std::string channel_name(GetUniqueTestChannelName()); | |
148 ASSERT_TRUE(security_key_ipc_server_->CreateChannel( | |
149 channel_name, | |
150 /*request_timeout=*/base::TimeDelta::FromMilliseconds(500))); | |
151 | |
152 // Create a fake client and connect to the IPC server channel. | |
153 FakeSecurityKeyIpcClient fake_ipc_client(base::Bind( | |
154 &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this))); | |
155 ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name)); | |
156 WaitForOperationComplete(); | |
157 | |
158 ASSERT_TRUE(fake_ipc_client.ipc_channel_connected()); | |
159 | |
160 // Send a request from the IPC client to the IPC server. | |
161 std::string request_data(kLargeMessageSizeBytes, 'Y'); | |
162 fake_ipc_client.SendSecurityKeyRequestViaIpc(request_data); | |
163 WaitForOperationComplete(); | |
164 | |
165 // Verify the request was received. | |
166 ASSERT_EQ(kTestConnectionId, last_connection_id_received_); | |
167 ASSERT_EQ(request_data, last_message_received_); | |
168 | |
169 // Send a response from the IPC server to the IPC client. | |
170 std::string response_data(kLargeMessageSizeBytes, 'Z'); | |
171 ASSERT_TRUE(security_key_ipc_server_->SendResponse(response_data)); | |
172 WaitForOperationComplete(); | |
173 | |
174 // Verify the request was received. | |
175 ASSERT_EQ(response_data, fake_ipc_client.last_message_received()); | |
176 | |
177 // Typically the client will be the one to close the connection. | |
178 fake_ipc_client.CloseIpcConnection(); | |
179 } | |
180 | |
181 TEST_F(SecurityKeyIpcServerTest, HandleReallyLargeSecurityKeyRequest) { | |
182 std::string channel_name(GetUniqueTestChannelName()); | |
183 ASSERT_TRUE(security_key_ipc_server_->CreateChannel( | |
184 channel_name, | |
185 /*request_timeout=*/base::TimeDelta::FromMilliseconds(500))); | |
186 | |
187 // Create a fake client and connect to the IPC server channel. | |
188 FakeSecurityKeyIpcClient fake_ipc_client(base::Bind( | |
189 &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this))); | |
190 ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name)); | |
191 WaitForOperationComplete(); | |
192 | |
193 ASSERT_TRUE(fake_ipc_client.ipc_channel_connected()); | |
194 | |
195 // Send a request from the IPC client to the IPC server. | |
196 std::string request_data(kLargeMessageSizeBytes * 2, 'Y'); | |
197 fake_ipc_client.SendSecurityKeyRequestViaIpc(request_data); | |
198 WaitForOperationComplete(); | |
199 | |
200 // Verify the request was received. | |
201 ASSERT_EQ(kTestConnectionId, last_connection_id_received_); | |
202 ASSERT_EQ(request_data, last_message_received_); | |
203 | |
204 // Send a response from the IPC server to the IPC client. | |
205 std::string response_data(kLargeMessageSizeBytes * 2, 'Z'); | |
206 ASSERT_TRUE(security_key_ipc_server_->SendResponse(response_data)); | |
207 WaitForOperationComplete(); | |
208 | |
209 // Verify the request was received. | |
210 ASSERT_EQ(response_data, fake_ipc_client.last_message_received()); | |
211 | |
212 // Typically the client will be the one to close the connection. | |
213 fake_ipc_client.CloseIpcConnection(); | |
214 } | |
215 | |
216 TEST_F(SecurityKeyIpcServerTest, HandleMultipleSecurityKeyRequests) { | |
217 std::string channel_name(GetUniqueTestChannelName()); | |
218 ASSERT_TRUE(security_key_ipc_server_->CreateChannel( | |
219 channel_name, | |
220 /*request_timeout=*/base::TimeDelta::FromMilliseconds(500))); | |
221 | |
222 // Create a fake client and connect to the IPC server channel. | |
223 FakeSecurityKeyIpcClient fake_ipc_client(base::Bind( | |
224 &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this))); | |
225 ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name)); | |
226 WaitForOperationComplete(); | |
227 | |
228 ASSERT_TRUE(fake_ipc_client.ipc_channel_connected()); | |
229 | |
230 // Send a request from the IPC client to the IPC server. | |
231 std::string request_data_1("Blergh!"); | |
232 fake_ipc_client.SendSecurityKeyRequestViaIpc(request_data_1); | |
233 WaitForOperationComplete(); | |
234 | |
235 // Verify the request was received. | |
236 ASSERT_EQ(kTestConnectionId, last_connection_id_received_); | |
237 ASSERT_EQ(request_data_1, last_message_received_); | |
238 | |
239 // Send a response from the IPC server to the IPC client. | |
240 std::string response_data_1("Blargh!"); | |
241 ASSERT_TRUE(security_key_ipc_server_->SendResponse(response_data_1)); | |
242 WaitForOperationComplete(); | |
243 | |
244 // Verify the response was received. | |
245 ASSERT_EQ(response_data_1, fake_ipc_client.last_message_received()); | |
246 | |
247 // Send a request from the IPC client to the IPC server. | |
248 std::string request_data_2("Bleh!"); | |
249 fake_ipc_client.SendSecurityKeyRequestViaIpc(request_data_2); | |
250 WaitForOperationComplete(); | |
251 | |
252 // Verify the request was received. | |
253 ASSERT_EQ(kTestConnectionId, last_connection_id_received_); | |
254 ASSERT_EQ(request_data_2, last_message_received_); | |
255 | |
256 // Send a response from the IPC server to the IPC client. | |
257 std::string response_data_2("Meh!"); | |
258 ASSERT_TRUE(security_key_ipc_server_->SendResponse(response_data_2)); | |
259 WaitForOperationComplete(); | |
260 | |
261 // Verify the response was received. | |
262 ASSERT_EQ(response_data_2, fake_ipc_client.last_message_received()); | |
263 | |
264 // Typically the client will be the one to close the connection. | |
265 fake_ipc_client.CloseIpcConnection(); | |
266 } | |
267 | |
268 TEST_F(SecurityKeyIpcServerTest, InitialIpcConnectionTimeout) { | |
269 // Create a channel, then wait for the done callback to be called indicating | |
270 // the connection was closed. This test simulates the IPC Server being | |
271 // created but the client failing to connect to it. | |
272 std::string channel_name(GetUniqueTestChannelName()); | |
273 ASSERT_TRUE(security_key_ipc_server_->CreateChannel( | |
274 channel_name, | |
275 /*request_timeout=*/base::TimeDelta::FromMilliseconds(500))); | |
276 base::Time start_time(base::Time::NowFromSystemTime()); | |
277 WaitForOperationComplete(); | |
278 base::TimeDelta elapsed_time = base::Time::NowFromSystemTime() - start_time; | |
279 | |
280 ASSERT_NEAR(elapsed_time.InMilliseconds(), kInitialConnectTimeoutMs, | |
281 kConnectionTimeoutErrorDeltaMs); | |
282 } | |
283 | |
284 TEST_F(SecurityKeyIpcServerTest, NoSecurityKeyRequestTimeout) { | |
285 // Create a channel and connect to it via IPC but do not send a request. | |
286 // The channel should be closed and cleaned up if the IPC client does not | |
287 // issue a request within the specified timeout period. | |
288 std::string channel_name(GetUniqueTestChannelName()); | |
289 ASSERT_TRUE(security_key_ipc_server_->CreateChannel( | |
290 channel_name, | |
291 /*request_timeout=*/base::TimeDelta::FromMilliseconds(500))); | |
292 | |
293 // Create a fake client and connect to the IPC server channel. | |
294 FakeSecurityKeyIpcClient fake_ipc_client(base::Bind( | |
295 &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this))); | |
296 ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name)); | |
297 WaitForOperationComplete(); | |
298 | |
299 ASSERT_TRUE(fake_ipc_client.ipc_channel_connected()); | |
300 | |
301 // Now that a connection has been established, we wait for the timeout. | |
302 base::Time start_time(base::Time::NowFromSystemTime()); | |
303 WaitForOperationComplete(); | |
304 base::TimeDelta elapsed_time = base::Time::NowFromSystemTime() - start_time; | |
305 | |
306 ASSERT_NEAR(elapsed_time.InMilliseconds(), kInitialConnectTimeoutMs, | |
307 kConnectionTimeoutErrorDeltaMs); | |
308 } | |
309 | |
310 TEST_F(SecurityKeyIpcServerTest, SecurityKeyResponseTimeout) { | |
311 // Create a channel, connect to it via IPC, and issue a request, but do | |
312 // not send a response. This simulates a client-side timeout. | |
313 base::TimeDelta request_timeout(base::TimeDelta::FromMilliseconds(50)); | |
314 std::string channel_name(GetUniqueTestChannelName()); | |
315 ASSERT_TRUE( | |
316 security_key_ipc_server_->CreateChannel(channel_name, request_timeout)); | |
317 | |
318 // Create a fake client and connect to the IPC server channel. | |
319 FakeSecurityKeyIpcClient fake_ipc_client(base::Bind( | |
320 &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this))); | |
321 ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name)); | |
322 WaitForOperationComplete(); | |
323 | |
324 ASSERT_TRUE(fake_ipc_client.ipc_channel_connected()); | |
325 | |
326 // Now that a connection has been established, we issue a request and | |
327 // then wait for the timeout. | |
328 std::string request_data("I can haz Auth?"); | |
329 fake_ipc_client.SendSecurityKeyRequestViaIpc(request_data); | |
330 WaitForOperationComplete(); | |
331 | |
332 // Leave the request hanging until it times out... | |
333 base::Time start_time(base::Time::NowFromSystemTime()); | |
334 WaitForOperationComplete(); | |
335 base::TimeDelta elapsed_time = base::Time::NowFromSystemTime() - start_time; | |
336 | |
337 ASSERT_NEAR(elapsed_time.InMilliseconds(), request_timeout.InMilliseconds(), | |
338 kConnectionTimeoutErrorDeltaMs); | |
339 } | |
340 | |
341 TEST_F(SecurityKeyIpcServerTest, SendResponseTimeout) { | |
342 // Create a channel, connect to it via IPC, issue a request, and send | |
343 // a response, but do not close the channel after that. The connection | |
344 // should be terminated after the initial timeout period has elapsed. | |
345 base::TimeDelta request_timeout(base::TimeDelta::FromMilliseconds(500)); | |
346 std::string channel_name(GetUniqueTestChannelName()); | |
347 ASSERT_TRUE( | |
348 security_key_ipc_server_->CreateChannel(channel_name, request_timeout)); | |
349 | |
350 // Create a fake client and connect to the IPC server channel. | |
351 FakeSecurityKeyIpcClient fake_ipc_client(base::Bind( | |
352 &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this))); | |
353 ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name)); | |
354 WaitForOperationComplete(); | |
355 | |
356 ASSERT_TRUE(fake_ipc_client.ipc_channel_connected()); | |
357 | |
358 // Issue a request. | |
359 std::string request_data("Auth me yo!"); | |
360 fake_ipc_client.SendSecurityKeyRequestViaIpc(request_data); | |
361 WaitForOperationComplete(); | |
362 | |
363 // Send a response from the IPC server to the IPC client. | |
364 std::string response_data("OK, the secret code is 1-2-3-4-5"); | |
365 ASSERT_TRUE(security_key_ipc_server_->SendResponse(response_data)); | |
366 WaitForOperationComplete(); | |
367 | |
368 // Now wait for the timeout period for the connection to be torn down. | |
369 base::Time start_time(base::Time::NowFromSystemTime()); | |
370 WaitForOperationComplete(); | |
371 base::TimeDelta elapsed_time = base::Time::NowFromSystemTime() - start_time; | |
372 | |
373 ASSERT_NEAR(elapsed_time.InMilliseconds(), request_timeout.InMilliseconds(), | |
374 kConnectionTimeoutErrorDeltaMs); | |
375 } | |
376 | |
377 #if defined(OS_WIN) | |
378 TEST_F(SecurityKeyIpcServerTest, IpcConnectionFailsFromInvalidSession) { | |
379 uint32_t peer_session_id = UINT32_MAX; | |
380 ASSERT_TRUE(ProcessIdToSessionId(GetCurrentProcessId(), | |
381 reinterpret_cast<DWORD*>(&peer_session_id))); | |
382 peer_session_id++; | |
383 | |
384 // Reinitialize the object under test. | |
385 security_key_ipc_server_ = remoting::SecurityKeyIpcServer::Create( | |
386 kTestConnectionId, peer_session_id, | |
387 base::TimeDelta::FromMilliseconds(kInitialConnectTimeoutMs), | |
388 base::Bind(&SecurityKeyIpcServerTest::SendRequestToClient, | |
389 base::Unretained(this)), | |
390 base::Bind(&base::DoNothing)); | |
391 | |
392 base::TimeDelta request_timeout(base::TimeDelta::FromMilliseconds(500)); | |
393 std::string channel_name(GetUniqueTestChannelName()); | |
394 ASSERT_TRUE( | |
395 security_key_ipc_server_->CreateChannel(channel_name, request_timeout)); | |
396 | |
397 // Create a fake client and attempt to connect to the IPC server channel. | |
398 FakeSecurityKeyIpcClient fake_ipc_client(base::Bind( | |
399 &SecurityKeyIpcServerTest::OperationComplete, base::Unretained(this))); | |
400 ASSERT_TRUE(fake_ipc_client.ConnectViaIpc(channel_name)); | |
401 WaitForOperationComplete(); | |
402 WaitForOperationComplete(); | |
403 | |
404 // Verify the connection failed. | |
405 ASSERT_FALSE(fake_ipc_client.ipc_channel_connected()); | |
406 } | |
407 #endif // defined(OS_WIN) | |
408 | |
409 } // namespace remoting | |
OLD | NEW |