Index: chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc |
diff --git a/chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc b/chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc |
index d9e4aee5f49dbc0b3e828c00602002a071065b54..7a880024a3b7bc6b847717fee31d324a67959bff 100644 |
--- a/chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc |
+++ b/chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc |
@@ -4,10 +4,12 @@ |
#include "chrome/browser/extensions/api/cast_channel/cast_socket.h" |
+#include "base/memory/weak_ptr.h" |
#include "base/message_loop/message_loop.h" |
#include "base/run_loop.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/sys_byteorder.h" |
+#include "base/timer/mock_timer.h" |
#include "chrome/browser/extensions/api/cast_channel/cast_channel.pb.h" |
#include "chrome/browser/extensions/api/cast_channel/cast_message_util.h" |
#include "net/base/address_list.h" |
@@ -21,6 +23,8 @@ |
#include "testing/gmock/include/gmock/gmock.h" |
#include "testing/gtest/include/gtest/gtest.h" |
+const int64 kDistantTimeoutMillis = 100000; // 100 seconds (never hit). |
+ |
using ::testing::_; |
using ::testing::A; |
using ::testing::DoAll; |
@@ -77,9 +81,21 @@ class MockTCPSocket : public net::TCPClientSocket { |
public: |
explicit MockTCPSocket(const net::MockConnect& connect_data) : |
TCPClientSocket(net::AddressList(), NULL, net::NetLog::Source()), |
- connect_data_(connect_data) { } |
+ connect_data_(connect_data), |
+ do_nothing_(false) { } |
+ |
+ explicit MockTCPSocket(bool do_nothing) : |
+ TCPClientSocket(net::AddressList(), NULL, net::NetLog::Source()) { |
+ CHECK(do_nothing); |
+ do_nothing_ = do_nothing; |
+ } |
virtual int Connect(const net::CompletionCallback& callback) OVERRIDE { |
+ if (do_nothing_) { |
+ // Stall the I/O event loop. |
+ return net::ERR_IO_PENDING; |
+ } |
+ |
if (connect_data_.mode == net::ASYNC) { |
CHECK_NE(connect_data_.result, net::ERR_IO_PENDING); |
base::MessageLoop::current()->PostTask( |
@@ -112,6 +128,7 @@ class MockTCPSocket : public net::TCPClientSocket { |
private: |
net::MockConnect connect_data_; |
+ bool do_nothing_; |
}; |
class CompleteHandler { |
@@ -130,26 +147,34 @@ class TestCastSocket : public CastSocket { |
MockCastSocketDelegate* delegate) { |
return scoped_ptr<TestCastSocket>( |
new TestCastSocket(delegate, CreateIPEndPoint(), |
- CHANNEL_AUTH_TYPE_SSL)); |
+ CHANNEL_AUTH_TYPE_SSL, |
+ kDistantTimeoutMillis)); |
} |
static scoped_ptr<TestCastSocket> CreateSecure( |
MockCastSocketDelegate* delegate) { |
return scoped_ptr<TestCastSocket>( |
new TestCastSocket(delegate, CreateIPEndPoint(), |
- CHANNEL_AUTH_TYPE_SSL_VERIFIED)); |
+ CHANNEL_AUTH_TYPE_SSL_VERIFIED, |
+ kDistantTimeoutMillis)); |
} |
explicit TestCastSocket(MockCastSocketDelegate* delegate, |
const net::IPEndPoint& ip_endpoint, |
- ChannelAuthType channel_auth) : |
- CastSocket("abcdefg", ip_endpoint, channel_auth, delegate, |
- &capturing_net_log_), |
- ip_(ip_endpoint), |
- connect_index_(0), |
- extract_cert_result_(true), |
- verify_challenge_result_(true) { |
- } |
+ ChannelAuthType channel_auth, |
+ int64 timeout_ms) |
+ : CastSocket("abcdefg", |
+ ip_endpoint, |
+ channel_auth, |
+ delegate, |
+ &capturing_net_log_, |
+ base::TimeDelta::FromMilliseconds(timeout_ms)), |
+ ip_(ip_endpoint), |
+ connect_index_(0), |
+ extract_cert_result_(true), |
+ verify_challenge_result_(true), |
+ tcp_unresponsive_(false), |
+ mock_timer_(new base::MockTimer(false, false)) {} |
static net::IPEndPoint CreateIPEndPoint() { |
net::IPAddressNumber number; |
@@ -181,6 +206,9 @@ class TestCastSocket : public CastSocket { |
void SetupSsl2Connect(net::IoMode mode, int result) { |
ssl_connect_data_[1].reset(new net::MockConnect(mode, result)); |
} |
+ void SetupTcp1ConnectUnresponsive() { |
+ tcp_unresponsive_ = true; |
+ } |
void AddWriteResult(const net::MockWrite& write) { |
writes_.push_back(write); |
} |
@@ -235,11 +263,19 @@ class TestCastSocket : public CastSocket { |
verify_challenge_result_ = value; |
} |
+ void TriggerTimeout() { |
+ mock_timer_->Fire(); |
+ } |
+ |
private: |
virtual scoped_ptr<net::TCPClientSocket> CreateTcpSocket() OVERRIDE { |
- net::MockConnect* connect_data = tcp_connect_data_[connect_index_].get(); |
- connect_data->peer_addr = ip_; |
- return scoped_ptr<net::TCPClientSocket>(new MockTCPSocket(*connect_data)); |
+ if (tcp_unresponsive_) { |
+ return scoped_ptr<net::TCPClientSocket>(new MockTCPSocket(true)); |
+ } else { |
+ net::MockConnect* connect_data = tcp_connect_data_[connect_index_].get(); |
+ connect_data->peer_addr = ip_; |
+ return scoped_ptr<net::TCPClientSocket>(new MockTCPSocket(*connect_data)); |
+ } |
} |
virtual scoped_ptr<net::SSLClientSocket> CreateSslSocket( |
@@ -267,6 +303,10 @@ class TestCastSocket : public CastSocket { |
return verify_challenge_result_; |
} |
+ virtual base::Timer* GetTimer() OVERRIDE { |
+ return mock_timer_.get(); |
+ } |
+ |
net::CapturingNetLog capturing_net_log_; |
net::IPEndPoint ip_; |
// Simulated connect data |
@@ -282,6 +322,9 @@ class TestCastSocket : public CastSocket { |
bool extract_cert_result_; |
// Simulated result of verifying challenge reply. |
bool verify_challenge_result_; |
+ // If true, makes TCP connection process stall. For timeout testing. |
+ bool tcp_unresponsive_; |
+ scoped_ptr<base::MockTimer> mock_timer_; |
}; |
class CastSocketTest : public testing::Test { |
@@ -520,6 +563,25 @@ TEST_F(CastSocketTest, TestConnectTcpConnectErrorSync) { |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
} |
+// Test connection error - timeout |
+TEST_F(CastSocketTest, TestConnectTcpTimeoutError) { |
+ CreateCastSocketSecure(); |
+ socket_->SetupTcp1ConnectUnresponsive(); |
+ EXPECT_CALL(handler_, OnConnectComplete(net::ERR_TIMED_OUT)); |
+ socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
+ |
+ EXPECT_EQ(cast_channel::READY_STATE_CONNECTING, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+ socket_->TriggerTimeout(); |
+ RunPendingTasks(); |
+ |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_TIMEOUT, |
+ socket_->error_state()); |
+} |
+ |
// Test connection error - SSL connect fails (async) |
TEST_F(CastSocketTest, TestConnectSslConnectErrorAsync) { |
CreateCastSocketSecure(); |
@@ -536,7 +598,7 @@ TEST_F(CastSocketTest, TestConnectSslConnectErrorAsync) { |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
} |
-// Test connection error - SSL connect fails (async) |
+// Test connection error - SSL connect fails (sync) |
TEST_F(CastSocketTest, TestConnectSslConnectErrorSync) { |
CreateCastSocketSecure(); |