OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "components/cast_channel/cast_socket.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include <utility> | |
10 #include <vector> | |
11 | |
12 #include "base/location.h" | |
13 #include "base/macros.h" | |
14 #include "base/memory/ptr_util.h" | |
15 #include "base/memory/weak_ptr.h" | |
16 #include "base/message_loop/message_loop.h" | |
17 #include "base/run_loop.h" | |
18 #include "base/single_thread_task_runner.h" | |
19 #include "base/strings/string_number_conversions.h" | |
20 #include "base/sys_byteorder.h" | |
21 #include "base/threading/thread_task_runner_handle.h" | |
22 #include "base/timer/mock_timer.h" | |
23 #include "components/cast_channel/cast_auth_util.h" | |
24 #include "components/cast_channel/cast_framer.h" | |
25 #include "components/cast_channel/cast_message_util.h" | |
26 #include "components/cast_channel/cast_test_util.h" | |
27 #include "components/cast_channel/cast_transport.h" | |
28 #include "components/cast_channel/logger.h" | |
29 #include "components/cast_channel/proto/cast_channel.pb.h" | |
30 #include "components/cast_channel/proto/logging.pb.h" | |
31 #include "net/base/address_list.h" | |
32 #include "net/base/net_errors.h" | |
33 #include "net/log/test_net_log.h" | |
34 #include "net/socket/socket_test_util.h" | |
35 #include "net/socket/ssl_client_socket.h" | |
36 #include "net/socket/tcp_client_socket.h" | |
37 #include "net/ssl/ssl_info.h" | |
38 #include "net/test/cert_test_util.h" | |
39 #include "net/test/test_data_directory.h" | |
40 #include "testing/gmock/include/gmock/gmock.h" | |
41 #include "testing/gtest/include/gtest/gtest.h" | |
42 | |
43 const int64_t kDistantTimeoutMillis = 100000; // 100 seconds (never hit). | |
44 | |
45 using ::cast_channel::ChannelError; | |
46 using ::cast_channel::ChannelAuthType; | |
47 using ::cast_channel::ReadyState; | |
48 using ::testing::_; | |
49 using ::testing::A; | |
50 using ::testing::DoAll; | |
51 using ::testing::Invoke; | |
52 using ::testing::InvokeArgument; | |
53 using ::testing::NotNull; | |
54 using ::testing::Return; | |
55 using ::testing::SaveArg; | |
56 | |
57 namespace cast_channel { | |
58 const char kAuthNamespace[] = "urn:x-cast:com.google.cast.tp.deviceauth"; | |
59 | |
60 // Returns an auth challenge message inline. | |
61 CastMessage CreateAuthChallenge() { | |
62 CastMessage output; | |
63 CreateAuthChallengeMessage(&output, AuthContext::Create()); | |
64 return output; | |
65 } | |
66 | |
67 // Returns an auth challenge response message inline. | |
68 CastMessage CreateAuthReply() { | |
69 CastMessage output; | |
70 output.set_protocol_version(CastMessage::CASTV2_1_0); | |
71 output.set_source_id("sender-0"); | |
72 output.set_destination_id("receiver-0"); | |
73 output.set_payload_type(CastMessage::BINARY); | |
74 output.set_payload_binary("abcd"); | |
75 output.set_namespace_(kAuthNamespace); | |
76 return output; | |
77 } | |
78 | |
79 CastMessage CreateTestMessage() { | |
80 CastMessage test_message; | |
81 test_message.set_protocol_version(CastMessage::CASTV2_1_0); | |
82 test_message.set_namespace_("ns"); | |
83 test_message.set_source_id("source"); | |
84 test_message.set_destination_id("dest"); | |
85 test_message.set_payload_type(CastMessage::STRING); | |
86 test_message.set_payload_utf8("payload"); | |
87 return test_message; | |
88 } | |
89 | |
90 class MockTCPSocket : public net::TCPClientSocket { | |
91 public: | |
92 explicit MockTCPSocket(const net::MockConnect& connect_data) | |
93 : TCPClientSocket(net::AddressList(), | |
94 nullptr, | |
95 nullptr, | |
96 net::NetLogSource()), | |
97 connect_data_(connect_data), | |
98 do_nothing_(false) {} | |
99 | |
100 explicit MockTCPSocket(bool do_nothing) | |
101 : TCPClientSocket(net::AddressList(), | |
102 nullptr, | |
103 nullptr, | |
104 net::NetLogSource()) { | |
105 CHECK(do_nothing); | |
106 do_nothing_ = do_nothing; | |
107 } | |
108 | |
109 virtual int Connect(const net::CompletionCallback& callback) { | |
110 if (do_nothing_) { | |
111 // Stall the I/O event loop. | |
112 return net::ERR_IO_PENDING; | |
113 } | |
114 | |
115 if (connect_data_.mode == net::ASYNC) { | |
116 CHECK_NE(connect_data_.result, net::ERR_IO_PENDING); | |
117 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
118 FROM_HERE, base::Bind(callback, connect_data_.result)); | |
119 return net::ERR_IO_PENDING; | |
120 } else { | |
121 return connect_data_.result; | |
122 } | |
123 } | |
124 | |
125 virtual bool SetKeepAlive(bool enable, int delay) { | |
126 // Always return true in tests | |
127 return true; | |
128 } | |
129 | |
130 virtual bool SetNoDelay(bool no_delay) { | |
131 // Always return true in tests | |
132 return true; | |
133 } | |
134 | |
135 MOCK_METHOD3(Read, int(net::IOBuffer*, int, const net::CompletionCallback&)); | |
136 MOCK_METHOD3(Write, int(net::IOBuffer*, int, const net::CompletionCallback&)); | |
137 | |
138 virtual void Disconnect() { | |
139 // Do nothing in tests | |
140 } | |
141 | |
142 private: | |
143 net::MockConnect connect_data_; | |
144 bool do_nothing_; | |
145 | |
146 DISALLOW_COPY_AND_ASSIGN(MockTCPSocket); | |
147 }; | |
148 | |
149 class MockDelegate : public CastTransport::Delegate { | |
150 public: | |
151 MockDelegate() {} | |
152 virtual ~MockDelegate() {} | |
153 MOCK_METHOD1(OnError, void(ChannelError error_state)); | |
154 MOCK_METHOD1(OnMessage, void(const CastMessage& message)); | |
155 MOCK_METHOD0(Start, void()); | |
156 | |
157 private: | |
158 DISALLOW_COPY_AND_ASSIGN(MockDelegate); | |
159 }; | |
160 | |
161 class CompleteHandler { | |
162 public: | |
163 CompleteHandler() {} | |
164 MOCK_METHOD1(OnCloseComplete, void(int result)); | |
165 MOCK_METHOD1(OnConnectComplete, void(ChannelError error_state)); | |
166 MOCK_METHOD1(OnWriteComplete, void(int result)); | |
167 MOCK_METHOD1(OnReadComplete, void(int result)); | |
168 | |
169 private: | |
170 DISALLOW_COPY_AND_ASSIGN(CompleteHandler); | |
171 }; | |
172 | |
173 class TestCastSocket : public CastSocketImpl { | |
174 public: | |
175 static std::unique_ptr<TestCastSocket> CreateSecure( | |
176 Logger* logger, | |
177 uint64_t device_capabilities = cast_channel::CastDeviceCapability::NONE) { | |
178 return std::unique_ptr<TestCastSocket>(new TestCastSocket( | |
179 CreateIPEndPointForTest(), ChannelAuthType::SSL_VERIFIED, | |
180 kDistantTimeoutMillis, logger, device_capabilities)); | |
181 } | |
182 | |
183 TestCastSocket(const net::IPEndPoint& ip_endpoint, | |
184 ChannelAuthType channel_auth, | |
185 int64_t timeout_ms, | |
186 Logger* logger, | |
187 uint64_t device_capabilities) | |
188 : TestCastSocket(ip_endpoint, | |
189 channel_auth, | |
190 timeout_ms, | |
191 logger, | |
192 new net::TestNetLog(), | |
193 device_capabilities) {} | |
194 | |
195 TestCastSocket(const net::IPEndPoint& ip_endpoint, | |
196 ChannelAuthType channel_auth, | |
197 int64_t timeout_ms, | |
198 Logger* logger, | |
199 net::TestNetLog* capturing_net_log, | |
200 uint64_t device_capabilities) | |
201 : CastSocketImpl("some_extension_id", | |
202 ip_endpoint, | |
203 channel_auth, | |
204 capturing_net_log, | |
205 base::TimeDelta::FromMilliseconds(timeout_ms), | |
206 false, | |
207 logger, | |
208 device_capabilities, | |
209 AuthContext::Create()), | |
210 capturing_net_log_(capturing_net_log), | |
211 ip_(ip_endpoint), | |
212 extract_cert_result_(true), | |
213 verify_challenge_result_(true), | |
214 verify_challenge_disallow_(false), | |
215 tcp_unresponsive_(false), | |
216 mock_timer_(new base::MockTimer(false, false)), | |
217 mock_transport_(nullptr) {} | |
218 | |
219 ~TestCastSocket() override {} | |
220 | |
221 void SetupMockTransport() { | |
222 mock_transport_ = new MockCastTransport; | |
223 SetTransportForTesting(base::WrapUnique(mock_transport_)); | |
224 } | |
225 | |
226 // Socket connection helpers. | |
227 void SetupTcpConnect(net::IoMode mode, int result) { | |
228 tcp_connect_data_.reset(new net::MockConnect(mode, result)); | |
229 } | |
230 void SetupSslConnect(net::IoMode mode, int result) { | |
231 ssl_connect_data_.reset(new net::MockConnect(mode, result)); | |
232 } | |
233 | |
234 // Socket I/O helpers. | |
235 void AddWriteResult(const net::MockWrite& write) { writes_.push_back(write); } | |
236 void AddWriteResult(net::IoMode mode, int result) { | |
237 AddWriteResult(net::MockWrite(mode, result)); | |
238 } | |
239 void AddWriteResultForData(net::IoMode mode, const std::string& msg) { | |
240 AddWriteResult(mode, msg.size()); | |
241 } | |
242 void AddReadResult(const net::MockRead& read) { reads_.push_back(read); } | |
243 void AddReadResult(net::IoMode mode, int result) { | |
244 AddReadResult(net::MockRead(mode, result)); | |
245 } | |
246 void AddReadResultForData(net::IoMode mode, const std::string& data) { | |
247 AddReadResult(net::MockRead(mode, data.c_str(), data.size())); | |
248 } | |
249 | |
250 // Helpers for modifying other connection-related behaviors. | |
251 void SetupTcpConnectUnresponsive() { tcp_unresponsive_ = true; } | |
252 | |
253 void SetExtractCertResult(bool value) { extract_cert_result_ = value; } | |
254 | |
255 void SetVerifyChallengeResult(bool value) { | |
256 verify_challenge_result_ = value; | |
257 } | |
258 | |
259 void TriggerTimeout() { mock_timer_->Fire(); } | |
260 | |
261 bool TestVerifyChannelPolicyNone() { | |
262 AuthResult authResult; | |
263 return VerifyChannelPolicy(authResult); | |
264 } | |
265 | |
266 bool TestVerifyChannelPolicyAudioOnly() { | |
267 AuthResult authResult; | |
268 authResult.channel_policies |= AuthResult::POLICY_AUDIO_ONLY; | |
269 return VerifyChannelPolicy(authResult); | |
270 } | |
271 | |
272 void DisallowVerifyChallengeResult() { verify_challenge_disallow_ = true; } | |
273 | |
274 MockCastTransport* GetMockTransport() { | |
275 CHECK(mock_transport_); | |
276 return mock_transport_; | |
277 } | |
278 | |
279 private: | |
280 std::unique_ptr<net::TCPClientSocket> CreateTcpSocket() override { | |
281 if (tcp_unresponsive_) { | |
282 return std::unique_ptr<net::TCPClientSocket>(new MockTCPSocket(true)); | |
283 } else { | |
284 net::MockConnect* connect_data = tcp_connect_data_.get(); | |
285 connect_data->peer_addr = ip_; | |
286 return std::unique_ptr<net::TCPClientSocket>( | |
287 new MockTCPSocket(*connect_data)); | |
288 } | |
289 } | |
290 | |
291 std::unique_ptr<net::SSLClientSocket> CreateSslSocket( | |
292 std::unique_ptr<net::StreamSocket> socket) override { | |
293 net::MockConnect* connect_data = ssl_connect_data_.get(); | |
294 connect_data->peer_addr = ip_; | |
295 | |
296 ssl_data_.reset(new net::StaticSocketDataProvider( | |
297 reads_.data(), reads_.size(), writes_.data(), writes_.size())); | |
298 ssl_data_->set_connect_data(*connect_data); | |
299 // NOTE: net::MockTCPClientSocket inherits from net::SSLClientSocket !! | |
300 return std::unique_ptr<net::SSLClientSocket>(new net::MockTCPClientSocket( | |
301 net::AddressList(), capturing_net_log_.get(), ssl_data_.get())); | |
302 } | |
303 | |
304 scoped_refptr<net::X509Certificate> ExtractPeerCert() override { | |
305 return extract_cert_result_ | |
306 ? net::ImportCertFromFile(net::GetTestCertsDirectory(), | |
307 "ok_cert.pem") | |
308 : nullptr; | |
309 } | |
310 | |
311 bool VerifyChallengeReply() override { | |
312 EXPECT_FALSE(verify_challenge_disallow_); | |
313 return verify_challenge_result_; | |
314 } | |
315 | |
316 base::Timer* GetTimer() override { return mock_timer_.get(); } | |
317 | |
318 std::unique_ptr<net::TestNetLog> capturing_net_log_; | |
319 net::IPEndPoint ip_; | |
320 // Simulated connect data | |
321 std::unique_ptr<net::MockConnect> tcp_connect_data_; | |
322 std::unique_ptr<net::MockConnect> ssl_connect_data_; | |
323 // Simulated read / write data | |
324 std::vector<net::MockWrite> writes_; | |
325 std::vector<net::MockRead> reads_; | |
326 std::unique_ptr<net::SocketDataProvider> ssl_data_; | |
327 // Simulated result of peer cert extraction. | |
328 bool extract_cert_result_; | |
329 // Simulated result of verifying challenge reply. | |
330 bool verify_challenge_result_; | |
331 bool verify_challenge_disallow_; | |
332 // If true, makes TCP connection process stall. For timeout testing. | |
333 bool tcp_unresponsive_; | |
334 std::unique_ptr<base::MockTimer> mock_timer_; | |
335 MockCastTransport* mock_transport_; | |
336 | |
337 DISALLOW_COPY_AND_ASSIGN(TestCastSocket); | |
338 }; | |
339 | |
340 class CastSocketTest : public testing::Test { | |
341 public: | |
342 CastSocketTest() : logger_(new Logger()), delegate_(new MockDelegate) {} | |
343 ~CastSocketTest() override {} | |
344 | |
345 void SetUp() override { EXPECT_CALL(*delegate_, OnMessage(_)).Times(0); } | |
346 | |
347 void TearDown() override { | |
348 if (socket_.get()) { | |
349 EXPECT_CALL(handler_, OnCloseComplete(net::OK)); | |
350 socket_->Close(base::Bind(&CompleteHandler::OnCloseComplete, | |
351 base::Unretained(&handler_))); | |
352 } | |
353 } | |
354 | |
355 void CreateCastSocketSecure() { | |
356 socket_ = TestCastSocket::CreateSecure(logger_); | |
357 } | |
358 | |
359 void HandleAuthHandshake() { | |
360 socket_->SetupMockTransport(); | |
361 CastMessage challenge_proto = CreateAuthChallenge(); | |
362 EXPECT_CALL(*socket_->GetMockTransport(), | |
363 SendMessage(EqualsProto(challenge_proto), _)) | |
364 .WillOnce(PostCompletionCallbackTask<1>(net::OK)); | |
365 EXPECT_CALL(*socket_->GetMockTransport(), Start()); | |
366 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::NONE)); | |
367 socket_->Connect(std::move(delegate_), | |
368 base::Bind(&CompleteHandler::OnConnectComplete, | |
369 base::Unretained(&handler_))); | |
370 RunPendingTasks(); | |
371 socket_->GetMockTransport()->current_delegate()->OnMessage( | |
372 CreateAuthReply()); | |
373 RunPendingTasks(); | |
374 } | |
375 | |
376 protected: | |
377 // Runs all pending tasks in the message loop. | |
378 void RunPendingTasks() { | |
379 base::RunLoop run_loop; | |
380 run_loop.RunUntilIdle(); | |
381 } | |
382 | |
383 base::MessageLoop message_loop_; | |
384 Logger* logger_; | |
385 std::unique_ptr<TestCastSocket> socket_; | |
386 CompleteHandler handler_; | |
387 std::unique_ptr<MockDelegate> delegate_; | |
388 | |
389 private: | |
390 DISALLOW_COPY_AND_ASSIGN(CastSocketTest); | |
391 }; | |
392 | |
393 // Tests that the following connection flow works: | |
394 // - TCP connection succeeds (async) | |
395 // - SSL connection succeeds (async) | |
396 // - Cert is extracted successfully | |
397 // - Challenge request is sent (async) | |
398 // - Challenge response is received (async) | |
399 // - Credentials are verified successfuly | |
400 TEST_F(CastSocketTest, TestConnectFullSecureFlowAsync) { | |
401 CreateCastSocketSecure(); | |
402 socket_->SetupTcpConnect(net::ASYNC, net::OK); | |
403 socket_->SetupSslConnect(net::ASYNC, net::OK); | |
404 | |
405 HandleAuthHandshake(); | |
406 | |
407 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); | |
408 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); | |
409 } | |
410 | |
411 // Tests that the following connection flow works: | |
412 // - TCP connection succeeds (sync) | |
413 // - SSL connection succeeds (sync) | |
414 // - Cert is extracted successfully | |
415 // - Challenge request is sent (sync) | |
416 // - Challenge response is received (sync) | |
417 // - Credentials are verified successfuly | |
418 TEST_F(CastSocketTest, TestConnectFullSecureFlowSync) { | |
419 CreateCastSocketSecure(); | |
420 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); | |
421 socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK); | |
422 | |
423 HandleAuthHandshake(); | |
424 | |
425 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); | |
426 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); | |
427 } | |
428 | |
429 // Test that an AuthMessage with a mangled namespace triggers cancelation | |
430 // of the connection event loop. | |
431 TEST_F(CastSocketTest, TestConnectAuthMessageCorrupted) { | |
432 CreateCastSocketSecure(); | |
433 socket_->SetupMockTransport(); | |
434 | |
435 socket_->SetupTcpConnect(net::ASYNC, net::OK); | |
436 socket_->SetupSslConnect(net::ASYNC, net::OK); | |
437 | |
438 CastMessage challenge_proto = CreateAuthChallenge(); | |
439 EXPECT_CALL(*socket_->GetMockTransport(), | |
440 SendMessage(EqualsProto(challenge_proto), _)) | |
441 .WillOnce(PostCompletionCallbackTask<1>(net::OK)); | |
442 EXPECT_CALL(*socket_->GetMockTransport(), Start()); | |
443 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::TRANSPORT_ERROR)); | |
444 socket_->Connect(std::move(delegate_), | |
445 base::Bind(&CompleteHandler::OnConnectComplete, | |
446 base::Unretained(&handler_))); | |
447 RunPendingTasks(); | |
448 CastMessage mangled_auth_reply = CreateAuthReply(); | |
449 mangled_auth_reply.set_namespace_("BOGUS_NAMESPACE"); | |
450 | |
451 socket_->GetMockTransport()->current_delegate()->OnMessage( | |
452 mangled_auth_reply); | |
453 RunPendingTasks(); | |
454 | |
455 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
456 EXPECT_EQ(ChannelError::TRANSPORT_ERROR, socket_->error_state()); | |
457 | |
458 // Verifies that the CastSocket's resources were torn down during channel | |
459 // close. (see http://crbug.com/504078) | |
460 EXPECT_EQ(nullptr, socket_->transport()); | |
461 } | |
462 | |
463 // Test connection error - TCP connect fails (async) | |
464 TEST_F(CastSocketTest, TestConnectTcpConnectErrorAsync) { | |
465 CreateCastSocketSecure(); | |
466 | |
467 socket_->SetupTcpConnect(net::ASYNC, net::ERR_FAILED); | |
468 | |
469 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_ERROR)); | |
470 socket_->Connect(std::move(delegate_), | |
471 base::Bind(&CompleteHandler::OnConnectComplete, | |
472 base::Unretained(&handler_))); | |
473 RunPendingTasks(); | |
474 | |
475 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
476 EXPECT_EQ(ChannelError::CONNECT_ERROR, socket_->error_state()); | |
477 } | |
478 | |
479 // Test connection error - TCP connect fails (sync) | |
480 TEST_F(CastSocketTest, TestConnectTcpConnectErrorSync) { | |
481 CreateCastSocketSecure(); | |
482 | |
483 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::ERR_FAILED); | |
484 | |
485 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_ERROR)); | |
486 socket_->Connect(std::move(delegate_), | |
487 base::Bind(&CompleteHandler::OnConnectComplete, | |
488 base::Unretained(&handler_))); | |
489 RunPendingTasks(); | |
490 | |
491 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
492 EXPECT_EQ(ChannelError::CONNECT_ERROR, socket_->error_state()); | |
493 } | |
494 | |
495 // Test connection error - timeout | |
496 TEST_F(CastSocketTest, TestConnectTcpTimeoutError) { | |
497 CreateCastSocketSecure(); | |
498 socket_->SetupTcpConnectUnresponsive(); | |
499 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_TIMEOUT)); | |
500 EXPECT_CALL(*delegate_, OnError(ChannelError::CONNECT_TIMEOUT)); | |
501 socket_->Connect(std::move(delegate_), | |
502 base::Bind(&CompleteHandler::OnConnectComplete, | |
503 base::Unretained(&handler_))); | |
504 RunPendingTasks(); | |
505 | |
506 EXPECT_EQ(ReadyState::CONNECTING, socket_->ready_state()); | |
507 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); | |
508 socket_->TriggerTimeout(); | |
509 RunPendingTasks(); | |
510 | |
511 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
512 EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); | |
513 } | |
514 | |
515 // Test connection error - TCP socket returns timeout | |
516 TEST_F(CastSocketTest, TestConnectTcpSocketTimeoutError) { | |
517 CreateCastSocketSecure(); | |
518 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::ERR_CONNECTION_TIMED_OUT); | |
519 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_TIMEOUT)); | |
520 EXPECT_CALL(*delegate_, OnError(ChannelError::CONNECT_TIMEOUT)); | |
521 socket_->Connect(std::move(delegate_), | |
522 base::Bind(&CompleteHandler::OnConnectComplete, | |
523 base::Unretained(&handler_))); | |
524 RunPendingTasks(); | |
525 | |
526 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
527 EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); | |
528 EXPECT_EQ(net::ERR_CONNECTION_TIMED_OUT, | |
529 logger_->GetLastErrors(socket_->id()).net_return_value); | |
530 } | |
531 | |
532 // Test connection error - SSL connect fails (async) | |
533 TEST_F(CastSocketTest, TestConnectSslConnectErrorAsync) { | |
534 CreateCastSocketSecure(); | |
535 | |
536 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); | |
537 socket_->SetupSslConnect(net::SYNCHRONOUS, net::ERR_FAILED); | |
538 | |
539 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::AUTHENTICATION_ERROR)); | |
540 socket_->Connect(std::move(delegate_), | |
541 base::Bind(&CompleteHandler::OnConnectComplete, | |
542 base::Unretained(&handler_))); | |
543 RunPendingTasks(); | |
544 | |
545 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
546 EXPECT_EQ(ChannelError::AUTHENTICATION_ERROR, socket_->error_state()); | |
547 } | |
548 | |
549 // Test connection error - SSL connect fails (sync) | |
550 TEST_F(CastSocketTest, TestConnectSslConnectErrorSync) { | |
551 CreateCastSocketSecure(); | |
552 | |
553 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); | |
554 socket_->SetupSslConnect(net::SYNCHRONOUS, net::ERR_FAILED); | |
555 | |
556 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::AUTHENTICATION_ERROR)); | |
557 socket_->Connect(std::move(delegate_), | |
558 base::Bind(&CompleteHandler::OnConnectComplete, | |
559 base::Unretained(&handler_))); | |
560 RunPendingTasks(); | |
561 | |
562 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
563 EXPECT_EQ(ChannelError::AUTHENTICATION_ERROR, socket_->error_state()); | |
564 EXPECT_EQ(net::ERR_FAILED, | |
565 logger_->GetLastErrors(socket_->id()).net_return_value); | |
566 } | |
567 | |
568 // Test connection error - SSL connect times out (sync) | |
569 TEST_F(CastSocketTest, TestConnectSslConnectTimeoutSync) { | |
570 CreateCastSocketSecure(); | |
571 | |
572 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); | |
573 socket_->SetupSslConnect(net::SYNCHRONOUS, net::ERR_CONNECTION_TIMED_OUT); | |
574 | |
575 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_TIMEOUT)); | |
576 socket_->Connect(std::move(delegate_), | |
577 base::Bind(&CompleteHandler::OnConnectComplete, | |
578 base::Unretained(&handler_))); | |
579 RunPendingTasks(); | |
580 | |
581 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
582 EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); | |
583 EXPECT_EQ(net::ERR_CONNECTION_TIMED_OUT, | |
584 logger_->GetLastErrors(socket_->id()).net_return_value); | |
585 } | |
586 | |
587 // Test connection error - SSL connect times out (async) | |
588 TEST_F(CastSocketTest, TestConnectSslConnectTimeoutAsync) { | |
589 CreateCastSocketSecure(); | |
590 | |
591 socket_->SetupTcpConnect(net::ASYNC, net::OK); | |
592 socket_->SetupSslConnect(net::ASYNC, net::ERR_CONNECTION_TIMED_OUT); | |
593 | |
594 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_TIMEOUT)); | |
595 socket_->Connect(std::move(delegate_), | |
596 base::Bind(&CompleteHandler::OnConnectComplete, | |
597 base::Unretained(&handler_))); | |
598 RunPendingTasks(); | |
599 | |
600 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
601 EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); | |
602 } | |
603 | |
604 // Test connection error - challenge send fails | |
605 TEST_F(CastSocketTest, TestConnectChallengeSendError) { | |
606 CreateCastSocketSecure(); | |
607 socket_->SetupMockTransport(); | |
608 | |
609 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); | |
610 socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK); | |
611 EXPECT_CALL(*socket_->GetMockTransport(), | |
612 SendMessage(EqualsProto(CreateAuthChallenge()), _)) | |
613 .WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET)); | |
614 | |
615 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CAST_SOCKET_ERROR)); | |
616 socket_->Connect(std::move(delegate_), | |
617 base::Bind(&CompleteHandler::OnConnectComplete, | |
618 base::Unretained(&handler_))); | |
619 RunPendingTasks(); | |
620 | |
621 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
622 EXPECT_EQ(ChannelError::CAST_SOCKET_ERROR, socket_->error_state()); | |
623 } | |
624 | |
625 // Test connection error - connection is destroyed after the challenge is | |
626 // sent, with the async result still lurking in the task queue. | |
627 TEST_F(CastSocketTest, TestConnectDestroyedAfterChallengeSent) { | |
628 CreateCastSocketSecure(); | |
629 socket_->SetupMockTransport(); | |
630 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); | |
631 socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK); | |
632 EXPECT_CALL(*socket_->GetMockTransport(), | |
633 SendMessage(EqualsProto(CreateAuthChallenge()), _)) | |
634 .WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET)); | |
635 socket_->Connect(std::move(delegate_), | |
636 base::Bind(&CompleteHandler::OnConnectComplete, | |
637 base::Unretained(&handler_))); | |
638 socket_.reset(); | |
639 RunPendingTasks(); | |
640 } | |
641 | |
642 // Test connection error - challenge reply receive fails | |
643 TEST_F(CastSocketTest, TestConnectChallengeReplyReceiveError) { | |
644 CreateCastSocketSecure(); | |
645 socket_->SetupMockTransport(); | |
646 | |
647 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); | |
648 socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK); | |
649 EXPECT_CALL(*socket_->GetMockTransport(), | |
650 SendMessage(EqualsProto(CreateAuthChallenge()), _)) | |
651 .WillOnce(PostCompletionCallbackTask<1>(net::OK)); | |
652 socket_->AddReadResult(net::SYNCHRONOUS, net::ERR_FAILED); | |
653 EXPECT_CALL(*delegate_, OnError(ChannelError::CAST_SOCKET_ERROR)); | |
654 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CAST_SOCKET_ERROR)); | |
655 EXPECT_CALL(*socket_->GetMockTransport(), Start()); | |
656 socket_->Connect(std::move(delegate_), | |
657 base::Bind(&CompleteHandler::OnConnectComplete, | |
658 base::Unretained(&handler_))); | |
659 RunPendingTasks(); | |
660 socket_->GetMockTransport()->current_delegate()->OnError( | |
661 ChannelError::CAST_SOCKET_ERROR); | |
662 RunPendingTasks(); | |
663 | |
664 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
665 EXPECT_EQ(ChannelError::CAST_SOCKET_ERROR, socket_->error_state()); | |
666 } | |
667 | |
668 TEST_F(CastSocketTest, TestConnectChallengeVerificationFails) { | |
669 CreateCastSocketSecure(); | |
670 socket_->SetupMockTransport(); | |
671 socket_->SetupTcpConnect(net::ASYNC, net::OK); | |
672 socket_->SetupSslConnect(net::ASYNC, net::OK); | |
673 socket_->SetVerifyChallengeResult(false); | |
674 | |
675 EXPECT_CALL(*delegate_, OnError(ChannelError::AUTHENTICATION_ERROR)); | |
676 CastMessage challenge_proto = CreateAuthChallenge(); | |
677 EXPECT_CALL(*socket_->GetMockTransport(), | |
678 SendMessage(EqualsProto(challenge_proto), _)) | |
679 .WillOnce(PostCompletionCallbackTask<1>(net::OK)); | |
680 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::AUTHENTICATION_ERROR)); | |
681 EXPECT_CALL(*socket_->GetMockTransport(), Start()); | |
682 socket_->Connect(std::move(delegate_), | |
683 base::Bind(&CompleteHandler::OnConnectComplete, | |
684 base::Unretained(&handler_))); | |
685 RunPendingTasks(); | |
686 socket_->GetMockTransport()->current_delegate()->OnMessage(CreateAuthReply()); | |
687 RunPendingTasks(); | |
688 | |
689 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); | |
690 EXPECT_EQ(ChannelError::AUTHENTICATION_ERROR, socket_->error_state()); | |
691 } | |
692 | |
693 // Sends message data through an actual non-mocked CastTransport object, | |
694 // testing the two components in integration. | |
695 TEST_F(CastSocketTest, TestConnectEndToEndWithRealTransportAsync) { | |
696 CreateCastSocketSecure(); | |
697 socket_->SetupTcpConnect(net::ASYNC, net::OK); | |
698 socket_->SetupSslConnect(net::ASYNC, net::OK); | |
699 | |
700 // Set low-level auth challenge expectations. | |
701 CastMessage challenge = CreateAuthChallenge(); | |
702 std::string challenge_str; | |
703 EXPECT_TRUE(MessageFramer::Serialize(challenge, &challenge_str)); | |
704 socket_->AddWriteResultForData(net::ASYNC, challenge_str); | |
705 | |
706 // Set low-level auth reply expectations. | |
707 CastMessage reply = CreateAuthReply(); | |
708 std::string reply_str; | |
709 EXPECT_TRUE(MessageFramer::Serialize(reply, &reply_str)); | |
710 socket_->AddReadResultForData(net::ASYNC, reply_str); | |
711 socket_->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); | |
712 | |
713 CastMessage test_message = CreateTestMessage(); | |
714 std::string test_message_str; | |
715 EXPECT_TRUE(MessageFramer::Serialize(test_message, &test_message_str)); | |
716 socket_->AddWriteResultForData(net::ASYNC, test_message_str); | |
717 | |
718 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::NONE)); | |
719 socket_->Connect(std::move(delegate_), | |
720 base::Bind(&CompleteHandler::OnConnectComplete, | |
721 base::Unretained(&handler_))); | |
722 RunPendingTasks(); | |
723 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); | |
724 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); | |
725 | |
726 // Send the test message through a real transport object. | |
727 EXPECT_CALL(handler_, OnWriteComplete(net::OK)); | |
728 socket_->transport()->SendMessage( | |
729 test_message, base::Bind(&CompleteHandler::OnWriteComplete, | |
730 base::Unretained(&handler_))); | |
731 RunPendingTasks(); | |
732 | |
733 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); | |
734 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); | |
735 } | |
736 | |
737 // Same as TestConnectEndToEndWithRealTransportAsync, except synchronous. | |
738 TEST_F(CastSocketTest, TestConnectEndToEndWithRealTransportSync) { | |
739 CreateCastSocketSecure(); | |
740 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); | |
741 socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK); | |
742 | |
743 // Set low-level auth challenge expectations. | |
744 CastMessage challenge = CreateAuthChallenge(); | |
745 std::string challenge_str; | |
746 EXPECT_TRUE(MessageFramer::Serialize(challenge, &challenge_str)); | |
747 socket_->AddWriteResultForData(net::SYNCHRONOUS, challenge_str); | |
748 | |
749 // Set low-level auth reply expectations. | |
750 CastMessage reply = CreateAuthReply(); | |
751 std::string reply_str; | |
752 EXPECT_TRUE(MessageFramer::Serialize(reply, &reply_str)); | |
753 socket_->AddReadResultForData(net::SYNCHRONOUS, reply_str); | |
754 socket_->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); | |
755 | |
756 CastMessage test_message = CreateTestMessage(); | |
757 std::string test_message_str; | |
758 EXPECT_TRUE(MessageFramer::Serialize(test_message, &test_message_str)); | |
759 socket_->AddWriteResultForData(net::SYNCHRONOUS, test_message_str); | |
760 | |
761 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::NONE)); | |
762 socket_->Connect(std::move(delegate_), | |
763 base::Bind(&CompleteHandler::OnConnectComplete, | |
764 base::Unretained(&handler_))); | |
765 RunPendingTasks(); | |
766 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); | |
767 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); | |
768 | |
769 // Send the test message through a real transport object. | |
770 EXPECT_CALL(handler_, OnWriteComplete(net::OK)); | |
771 socket_->transport()->SendMessage( | |
772 test_message, base::Bind(&CompleteHandler::OnWriteComplete, | |
773 base::Unretained(&handler_))); | |
774 RunPendingTasks(); | |
775 | |
776 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); | |
777 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); | |
778 } | |
779 | |
780 } // namespace cast_channel | |
OLD | NEW |