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