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..88fbdf6049e191db711265dc6ef7e42696a9045a 100644 |
--- a/chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc |
+++ b/chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc |
@@ -21,6 +21,9 @@ |
#include "testing/gmock/include/gmock/gmock.h" |
#include "testing/gtest/include/gtest/gtest.h" |
+const int64 kDistantTimeoutMillis = 100000; // 100 seconds (never hit). |
+const int64 kImmediateTimeoutMillis = 100; // 0.001 seconds. |
+ |
using ::testing::_; |
using ::testing::A; |
using ::testing::DoAll; |
@@ -79,7 +82,17 @@ class MockTCPSocket : public net::TCPClientSocket { |
TCPClientSocket(net::AddressList(), NULL, net::NetLog::Source()), |
connect_data_(connect_data) { } |
+ explicit MockTCPSocket(bool do_nothing) : |
+ TCPClientSocket(net::AddressList(), NULL, net::NetLog::Source()) { |
+ CHECK(do_nothing); |
+ do_nothing_ = true; |
+ } |
+ |
virtual int Connect(const net::CompletionCallback& callback) OVERRIDE { |
+ if (do_nothing_) { |
+ 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 +125,7 @@ class MockTCPSocket : public net::TCPClientSocket { |
private: |
net::MockConnect connect_data_; |
+ bool do_nothing_; |
}; |
class CompleteHandler { |
@@ -130,26 +144,37 @@ 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)); |
+ } |
+ |
+ static scoped_ptr<TestCastSocket> CreateDoomedToTimeout( |
mark a. foltz
2014/07/15 22:18:16
Instead of fudging timeouts the cleaner way to tes
Kevin M
2014/07/16 22:59:42
Done. New approach uses Timer.
|
+ MockCastSocketDelegate* delegate) { |
+ return scoped_ptr<TestCastSocket>( |
+ new TestCastSocket(delegate, CreateIPEndPoint(), |
+ CHANNEL_AUTH_TYPE_SSL_VERIFIED, |
+ kImmediateTimeoutMillis)); |
} |
explicit TestCastSocket(MockCastSocketDelegate* delegate, |
const net::IPEndPoint& ip_endpoint, |
- ChannelAuthType channel_auth) : |
+ ChannelAuthType channel_auth, |
+ int64 timeout_ms) : |
CastSocket("abcdefg", ip_endpoint, channel_auth, delegate, |
- &capturing_net_log_), |
+ &capturing_net_log_, timeout_ms), |
ip_(ip_endpoint), |
connect_index_(0), |
extract_cert_result_(true), |
- verify_challenge_result_(true) { |
- } |
+ verify_challenge_result_(true), |
+ tcp_unresponsive_(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); |
} |
@@ -237,9 +265,13 @@ class TestCastSocket : public CastSocket { |
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( |
@@ -282,6 +314,8 @@ 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_; |
}; |
class CastSocketTest : public testing::Test { |
@@ -330,6 +364,10 @@ class CastSocketTest : public testing::Test { |
socket_ = TestCastSocket::CreateSecure(&mock_delegate_); |
} |
+ void CreateCastSocketUnresponsive() { |
+ socket_ = TestCastSocket::CreateDoomedToTimeout(&mock_delegate_); |
+ } |
+ |
// Sets up CastSocket::Connect to succeed. |
// Connecting the socket also starts the read loop; so we add a mock |
// read result that returns IO_PENDING and callback is never fired. |
@@ -520,6 +558,31 @@ TEST_F(CastSocketTest, TestConnectTcpConnectErrorSync) { |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
} |
+// Test connection error - timeout |
+TEST_F(CastSocketTest, TestConnectTcpTimeoutError) { |
+ CreateCastSocketUnresponsive(); |
+ |
+ socket_->SetupTcp1ConnectUnresponsive(); |
+ EXPECT_CALL(handler_, OnConnectComplete(net::ERR_TIMED_OUT)); |
+ EXPECT_CALL(mock_delegate_, |
+ OnError(socket_.get(), |
+ cast_channel::CHANNEL_ERROR_CONNECT_ERROR)); |
+ 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()); |
+ |
+ // Allow for the timeout to fire by sleeping (plus some padding to protect |
+ // against timing-related flakiness). |
mark a. foltz
2014/07/15 22:18:16
A mock clock would definitely be better here.
Kevin M
2014/07/16 22:59:42
Done.
|
+ base::PlatformThread::Sleep( |
+ base::TimeDelta::FromMilliseconds(kImmediateTimeoutMillis + 200)); |
+ RunPendingTasks(); |
+ |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
+} |
+ |
// Test connection error - SSL connect fails (async) |
TEST_F(CastSocketTest, TestConnectSslConnectErrorAsync) { |
CreateCastSocketSecure(); |
@@ -536,7 +599,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(); |