Index: net/socket/socks_client_socket_unittest.cc |
=================================================================== |
--- net/socket/socks_client_socket_unittest.cc (revision 35690) |
+++ net/socket/socks_client_socket_unittest.cc (working copy) |
@@ -30,6 +30,7 @@ |
SOCKSClientSocketTest(); |
// Create a SOCKSClientSocket on top of a MockSocket. |
SOCKSClientSocket* BuildMockSocket(MockRead reads[], MockWrite writes[], |
+ HostResolver* host_resolver, |
const std::string& hostname, int port); |
virtual void SetUp(); |
@@ -57,6 +58,7 @@ |
SOCKSClientSocket* SOCKSClientSocketTest::BuildMockSocket( |
MockRead reads[], |
MockWrite writes[], |
+ HostResolver* host_resolver, |
const std::string& hostname, |
int port) { |
@@ -72,9 +74,48 @@ |
return new SOCKSClientSocket(tcp_sock_, |
HostResolver::RequestInfo(hostname, port), |
- host_resolver_); |
+ host_resolver); |
} |
+// Implementation of HostResolver that never completes its resolve request. |
+// We use this in the test "DisconnectWhileHostResolveInProgress" to make |
+// sure that the outstanding resolve request gets cancelled. |
+class HangingHostResolver : public HostResolver { |
+ public: |
+ HangingHostResolver() : outstanding_request_(NULL) {} |
+ |
+ virtual int Resolve(const RequestInfo& info, |
+ AddressList* addresses, |
+ CompletionCallback* callback, |
+ RequestHandle* out_req, |
+ LoadLog* load_log) { |
+ EXPECT_FALSE(HasOutstandingRequest()); |
+ outstanding_request_ = reinterpret_cast<RequestHandle>(1); |
+ *out_req = outstanding_request_; |
+ return ERR_IO_PENDING; |
+ } |
+ |
+ virtual void CancelRequest(RequestHandle req) { |
+ EXPECT_TRUE(HasOutstandingRequest()); |
+ EXPECT_EQ(outstanding_request_, req); |
+ outstanding_request_ = NULL; |
+ } |
+ |
+ virtual void AddObserver(Observer* observer) {} |
+ virtual void RemoveObserver(Observer* observer) {} |
+ virtual HostCache* GetHostCache() { return NULL; } |
+ virtual void Shutdown() {} |
+ |
+ bool HasOutstandingRequest() { |
+ return outstanding_request_ != NULL; |
+ } |
+ |
+ private: |
+ RequestHandle outstanding_request_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(HangingHostResolver); |
+}; |
+ |
// Tests a complete handshake and the disconnection. |
TEST_F(SOCKSClientSocketTest, CompleteHandshake) { |
const std::string payload_write = "random data"; |
@@ -87,7 +128,8 @@ |
MockRead(true, kSOCKSOkReply, arraysize(kSOCKSOkReply)), |
MockRead(true, payload_read.data(), payload_read.size()) }; |
- user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80)); |
+ user_sock_.reset(BuildMockSocket(data_reads, data_writes, host_resolver_, |
+ "localhost", 80)); |
// At this state the TCP connection is completed but not the SOCKS handshake. |
EXPECT_TRUE(tcp_sock_->IsConnected()); |
@@ -153,7 +195,8 @@ |
MockRead data_reads[] = { |
MockRead(false, tests[i].fail_reply, arraysize(tests[i].fail_reply)) }; |
- user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80)); |
+ user_sock_.reset(BuildMockSocket(data_reads, data_writes, host_resolver_, |
+ "localhost", 80)); |
scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); |
int rv = user_sock_->Connect(&callback_, log); |
@@ -181,7 +224,8 @@ |
MockRead(true, kSOCKSPartialReply1, arraysize(kSOCKSPartialReply1)), |
MockRead(true, kSOCKSPartialReply2, arraysize(kSOCKSPartialReply2)) }; |
- user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80)); |
+ user_sock_.reset(BuildMockSocket(data_reads, data_writes, host_resolver_, |
+ "localhost", 80)); |
scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); |
int rv = user_sock_->Connect(&callback_, log); |
@@ -211,7 +255,8 @@ |
MockRead data_reads[] = { |
MockRead(true, kSOCKSOkReply, arraysize(kSOCKSOkReply)) }; |
- user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80)); |
+ user_sock_.reset(BuildMockSocket(data_reads, data_writes, host_resolver_, |
+ "localhost", 80)); |
scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); |
int rv = user_sock_->Connect(&callback_, log); |
@@ -235,7 +280,8 @@ |
// close connection unexpectedly |
MockRead(false, 0) }; |
- user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80)); |
+ user_sock_.reset(BuildMockSocket(data_reads, data_writes, host_resolver_, |
+ "localhost", 80)); |
scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); |
int rv = user_sock_->Connect(&callback_, log); |
@@ -264,7 +310,8 @@ |
MockRead data_reads[] = { |
MockRead(false, kSOCKSOkReply, arraysize(kSOCKSOkReply)) }; |
- user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80)); |
+ user_sock_.reset(BuildMockSocket(data_reads, data_writes, host_resolver_, |
+ hostname, 80)); |
scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); |
int rv = user_sock_->Connect(&callback_, log); |
@@ -295,7 +342,8 @@ |
MockRead data_reads[] = { |
MockRead(false, kSOCKSOkReply, arraysize(kSOCKSOkReply)) }; |
- user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80)); |
+ user_sock_.reset(BuildMockSocket(data_reads, data_writes, host_resolver_, |
+ hostname, 80)); |
scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); |
int rv = user_sock_->Connect(&callback_, log); |
@@ -310,4 +358,36 @@ |
*log, -1, LoadLog::TYPE_SOCKS_CONNECT, LoadLog::PHASE_END)); |
} |
+// Calls Disconnect() while a host resolve is in progress. The outstanding host |
+// resolve should be cancelled. |
+TEST_F(SOCKSClientSocketTest, DisconnectWhileHostResolveInProgress) { |
+ scoped_refptr<HangingHostResolver> hanging_resolver = |
+ new HangingHostResolver(); |
+ |
+ // Doesn't matter what the socket data is, we will never use it -- garbage. |
+ MockWrite data_writes[] = { MockWrite(false, "", 0) }; |
+ MockRead data_reads[] = { MockRead(false, "", 0) }; |
+ |
+ user_sock_.reset(BuildMockSocket(data_reads, data_writes, hanging_resolver, |
+ "foo", 80)); |
+ |
+ // Start connecting (will get stuck waiting for the host to resolve). |
+ int rv = user_sock_->Connect(&callback_, NULL); |
+ EXPECT_EQ(ERR_IO_PENDING, rv); |
+ |
+ EXPECT_FALSE(user_sock_->IsConnected()); |
+ EXPECT_FALSE(user_sock_->IsConnectedAndIdle()); |
+ |
+ // The host resolver should have received the resolve request. |
+ EXPECT_TRUE(hanging_resolver->HasOutstandingRequest()); |
+ |
+ // Disconnect the SOCKS socket -- this should cancel the outstanding resolve. |
+ user_sock_->Disconnect(); |
+ |
+ EXPECT_FALSE(hanging_resolver->HasOutstandingRequest()); |
+ |
+ EXPECT_FALSE(user_sock_->IsConnected()); |
+ EXPECT_FALSE(user_sock_->IsConnectedAndIdle()); |
+} |
+ |
} // namespace net |