Index: net/base/client_socket_pool_unittest.cc |
diff --git a/net/base/client_socket_pool_unittest.cc b/net/base/client_socket_pool_unittest.cc |
index 73fc0e344dc93508e5c4e7cace238520f8166869..a889d9a7fa156a65e560b6d7fe2e908354a64351 100644 |
--- a/net/base/client_socket_pool_unittest.cc |
+++ b/net/base/client_socket_pool_unittest.cc |
@@ -4,16 +4,11 @@ |
#include "base/message_loop.h" |
#include "net/base/client_socket.h" |
-#include "net/base/client_socket_factory.h" |
#include "net/base/client_socket_handle.h" |
#include "net/base/client_socket_pool.h" |
-#include "net/base/host_resolver_unittest.h" |
#include "net/base/net_errors.h" |
-#include "net/base/test_completion_callback.h" |
#include "testing/gtest/include/gtest/gtest.h" |
-namespace net { |
- |
namespace { |
const int kMaxSocketsPerGroup = 6; |
@@ -26,16 +21,16 @@ const int kPriorities[10] = { 1, 7, 9, 5, 6, 2, 8, 3, 4, 1 }; |
// available sockets in the socket group. |
const int kNumPendingRequests = arraysize(kPriorities); |
-const int kNumRequests = kMaxSocketsPerGroup + kNumPendingRequests; |
- |
-class MockClientSocket : public ClientSocket { |
+class MockClientSocket : public net::ClientSocket { |
public: |
- MockClientSocket() : connected_(false) {} |
+ MockClientSocket() : connected_(false) { |
+ allocation_count++; |
+ } |
// ClientSocket methods: |
- virtual int Connect(CompletionCallback* callback) { |
+ virtual int Connect(net::CompletionCallback* callback) { |
connected_ = true; |
- return OK; |
+ return net::OK; |
} |
virtual void Disconnect() { |
connected_ = false; |
@@ -48,115 +43,51 @@ class MockClientSocket : public ClientSocket { |
} |
// Socket methods: |
- virtual int Read(IOBuffer* buf, int buf_len, |
- CompletionCallback* callback) { |
- return ERR_FAILED; |
+ virtual int Read(net::IOBuffer* buf, int buf_len, |
+ net::CompletionCallback* callback) { |
+ return net::ERR_FAILED; |
} |
- virtual int Write(IOBuffer* buf, int buf_len, |
- CompletionCallback* callback) { |
- return ERR_FAILED; |
+ virtual int Write(net::IOBuffer* buf, int buf_len, |
+ net::CompletionCallback* callback) { |
+ return net::ERR_FAILED; |
} |
+ static int allocation_count; |
+ |
private: |
bool connected_; |
}; |
-class MockFailingClientSocket : public ClientSocket { |
- public: |
- MockFailingClientSocket() {} |
- |
- // ClientSocket methods: |
- virtual int Connect(CompletionCallback* callback) { |
- return ERR_CONNECTION_FAILED; |
- } |
- |
- virtual void Disconnect() {} |
- |
- virtual bool IsConnected() const { |
- return false; |
- } |
- virtual bool IsConnectedAndIdle() const { |
- return false; |
- } |
- |
- // Socket methods: |
- virtual int Read(IOBuffer* buf, int buf_len, |
- CompletionCallback* callback) { |
- return ERR_FAILED; |
- } |
- |
- virtual int Write(IOBuffer* buf, int buf_len, |
- CompletionCallback* callback) { |
- return ERR_FAILED; |
- } |
-}; |
- |
-class MockClientSocketFactory : public ClientSocketFactory { |
- public: |
- enum ClientSocketType { |
- MOCK_CLIENT_SOCKET, |
- MOCK_FAILING_CLIENT_SOCKET, |
- }; |
- |
- MockClientSocketFactory() |
- : allocation_count_(0), client_socket_type_(MOCK_CLIENT_SOCKET) {} |
- |
- virtual ClientSocket* CreateTCPClientSocket(const AddressList& addresses) { |
- allocation_count_++; |
- switch (client_socket_type_) { |
- case MOCK_CLIENT_SOCKET: |
- return new MockClientSocket(); |
- case MOCK_FAILING_CLIENT_SOCKET: |
- return new MockFailingClientSocket(); |
- default: |
- NOTREACHED(); |
- return new MockClientSocket(); |
- } |
- } |
- |
- virtual SSLClientSocket* CreateSSLClientSocket( |
- ClientSocket* transport_socket, |
- const std::string& hostname, |
- const SSLConfig& ssl_config) { |
- NOTIMPLEMENTED(); |
- return NULL; |
- } |
- |
- int allocation_count() const { return allocation_count_; } |
- |
- void set_client_socket_type(ClientSocketType type) { |
- client_socket_type_ = type; |
- } |
- |
- private: |
- int allocation_count_; |
- ClientSocketType client_socket_type_; |
-}; |
+int MockClientSocket::allocation_count = 0; |
class TestSocketRequest : public CallbackRunner< Tuple1<int> > { |
public: |
TestSocketRequest( |
- ClientSocketPool* pool, |
+ net::ClientSocketPool* pool, |
std::vector<TestSocketRequest*>* request_order) |
: handle(pool), request_order_(request_order) {} |
- ClientSocketHandle handle; |
+ net::ClientSocketHandle handle; |
- int WaitForResult() { |
- return callback_.WaitForResult(); |
+ void EnsureSocket() { |
+ DCHECK(handle.is_initialized()); |
+ request_order_->push_back(this); |
+ if (!handle.socket()) { |
+ handle.set_socket(new MockClientSocket()); |
+ handle.socket()->Connect(NULL); |
+ } |
} |
virtual void RunWithParams(const Tuple1<int>& params) { |
- callback_.RunWithParams(params); |
+ DCHECK(params.a == net::OK); |
completion_count++; |
- request_order_->push_back(this); |
+ EnsureSocket(); |
} |
static int completion_count; |
private: |
std::vector<TestSocketRequest*>* request_order_; |
- TestCompletionCallback callback_; |
}; |
int TestSocketRequest::completion_count = 0; |
@@ -164,76 +95,68 @@ int TestSocketRequest::completion_count = 0; |
class ClientSocketPoolTest : public testing::Test { |
protected: |
ClientSocketPoolTest() |
- : pool_(new ClientSocketPool(kMaxSocketsPerGroup, |
- &client_socket_factory_)) {} |
+ : pool_(new net::ClientSocketPool(kMaxSocketsPerGroup)) {} |
virtual void SetUp() { |
+ MockClientSocket::allocation_count = 0; |
TestSocketRequest::completion_count = 0; |
} |
- MockClientSocketFactory client_socket_factory_; |
- scoped_refptr<ClientSocketPool> pool_; |
+ scoped_refptr<net::ClientSocketPool> pool_; |
std::vector<TestSocketRequest*> request_order_; |
}; |
TEST_F(ClientSocketPoolTest, Basic) { |
- TestCompletionCallback callback; |
- ClientSocketHandle handle(pool_.get()); |
- int rv = handle.Init("a", "www.google.com", 80, 0, &callback); |
- EXPECT_EQ(ERR_IO_PENDING, rv); |
- EXPECT_FALSE(handle.is_initialized()); |
- EXPECT_FALSE(handle.socket()); |
+ TestSocketRequest r(pool_.get(), &request_order_); |
+ int rv; |
- EXPECT_EQ(OK, callback.WaitForResult()); |
- EXPECT_TRUE(handle.is_initialized()); |
- EXPECT_TRUE(handle.socket()); |
+ rv = r.handle.Init("a", 0, &r); |
+ EXPECT_EQ(net::OK, rv); |
+ EXPECT_TRUE(r.handle.is_initialized()); |
- handle.Reset(); |
+ r.handle.Reset(); |
// The handle's Reset method may have posted a task. |
MessageLoop::current()->RunAllPending(); |
} |
-TEST_F(ClientSocketPoolTest, InitHostResolutionFailure) { |
- RuleBasedHostMapper* host_mapper = new RuleBasedHostMapper; |
- host_mapper->AddSimulatedFailure("unresolvable.host.name"); |
- ScopedHostMapper scoped_host_mapper(host_mapper); |
- TestSocketRequest req(pool_.get(), &request_order_); |
- EXPECT_EQ(ERR_IO_PENDING, |
- req.handle.Init("a", "unresolvable.host.name", 80, 5, &req)); |
- EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req.WaitForResult()); |
-} |
+TEST_F(ClientSocketPoolTest, WithIdleConnection) { |
+ TestSocketRequest r(pool_.get(), &request_order_); |
+ int rv; |
+ |
+ rv = r.handle.Init("a", 0, &r); |
+ EXPECT_EQ(net::OK, rv); |
+ EXPECT_TRUE(r.handle.is_initialized()); |
-TEST_F(ClientSocketPoolTest, InitConnectionFailure) { |
- client_socket_factory_.set_client_socket_type( |
- MockClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET); |
- TestSocketRequest req(pool_.get(), &request_order_); |
- EXPECT_EQ(ERR_IO_PENDING, |
- req.handle.Init("a", "unresolvable.host.name", 80, 5, &req)); |
- EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult()); |
+ // Create a socket. |
+ r.EnsureSocket(); |
+ |
+ // Release the socket. It should find its way into the idle list. We're |
+ // testing that this does not trigger a crash. |
+ r.handle.Reset(); |
+ |
+ // The handle's Reset method may have posted a task. |
+ MessageLoop::current()->RunAllPending(); |
} |
TEST_F(ClientSocketPoolTest, PendingRequests) { |
int rv; |
- scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
+ scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + kNumPendingRequests]; |
for (size_t i = 0; i < arraysize(reqs); ++i) |
reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); |
// Create connections or queue up requests. |
for (int i = 0; i < kMaxSocketsPerGroup; ++i) { |
- EXPECT_EQ( |
- ERR_IO_PENDING, |
- reqs[i]->handle.Init("a", "www.google.com", 80, 5, reqs[i].get())); |
- EXPECT_EQ(OK, reqs[i]->WaitForResult()); |
+ rv = reqs[i]->handle.Init("a", 5, reqs[i].get()); |
+ EXPECT_EQ(net::OK, rv); |
+ reqs[i]->EnsureSocket(); |
} |
- |
for (int i = 0; i < kNumPendingRequests; ++i) { |
rv = reqs[kMaxSocketsPerGroup + i]->handle.Init( |
- "a", "www.google.com", 80, kPriorities[i], |
- reqs[kMaxSocketsPerGroup + i].get()); |
- EXPECT_EQ(ERR_IO_PENDING, rv); |
+ "a", kPriorities[i], reqs[kMaxSocketsPerGroup + i].get()); |
+ EXPECT_EQ(net::ERR_IO_PENDING, rv); |
} |
// Release any connections until we have no connections. |
@@ -249,8 +172,8 @@ TEST_F(ClientSocketPoolTest, PendingRequests) { |
} |
} while (released_one); |
- EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); |
- EXPECT_EQ(kNumRequests, TestSocketRequest::completion_count); |
+ EXPECT_EQ(kMaxSocketsPerGroup, MockClientSocket::allocation_count); |
+ EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); |
for (int i = 0; i < kMaxSocketsPerGroup; ++i) { |
EXPECT_EQ(request_order_[i], reqs[i].get()) << |
@@ -271,77 +194,58 @@ TEST_F(ClientSocketPoolTest, PendingRequests) { |
} |
TEST_F(ClientSocketPoolTest, PendingRequests_NoKeepAlive) { |
- scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
+ int rv; |
+ |
+ scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + kNumPendingRequests]; |
for (size_t i = 0; i < arraysize(reqs); ++i) |
reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); |
// Create connections or queue up requests. |
- for (int i = 0; i < kMaxSocketsPerGroup; ++i) { |
- EXPECT_EQ( |
- ERR_IO_PENDING, |
- reqs[i]->handle.Init("a", "www.google.com", 80, 0, reqs[i].get())); |
- EXPECT_EQ(OK, reqs[i]->WaitForResult()); |
- } |
- |
- for (int i = 0; i < kNumPendingRequests; ++i) { |
- EXPECT_EQ(ERR_IO_PENDING, reqs[kMaxSocketsPerGroup + i]->handle.Init( |
- "a", "www.google.com", 80, 0, reqs[kMaxSocketsPerGroup + i].get())); |
+ for (size_t i = 0; i < arraysize(reqs); ++i) { |
+ rv = reqs[i]->handle.Init("a", 0, reqs[i].get()); |
+ if (rv != net::ERR_IO_PENDING) { |
+ EXPECT_EQ(net::OK, rv); |
+ reqs[i]->EnsureSocket(); |
+ } |
} |
// Release any connections until we have no connections. |
- |
- while (TestSocketRequest::completion_count < kNumRequests) { |
- int num_released = 0; |
+ bool released_one; |
+ do { |
+ released_one = false; |
for (size_t i = 0; i < arraysize(reqs); ++i) { |
if (reqs[i]->handle.is_initialized()) { |
reqs[i]->handle.socket()->Disconnect(); |
reqs[i]->handle.Reset(); |
- num_released++; |
+ MessageLoop::current()->RunAllPending(); |
+ released_one = true; |
} |
} |
- int curr_num_completed = TestSocketRequest::completion_count; |
- for (int i = 0; |
- (i < num_released) && (i + curr_num_completed < kNumRequests); ++i) { |
- EXPECT_EQ(OK, reqs[i + curr_num_completed]->WaitForResult()); |
- } |
- } |
- |
- EXPECT_EQ(kNumRequests, client_socket_factory_.allocation_count()); |
- EXPECT_EQ(kNumRequests, TestSocketRequest::completion_count); |
-} |
+ } while (released_one); |
-// This test will start up a RequestSocket() and then immediately Cancel() it. |
-// The pending host resolution will eventually complete, and destroy the |
-// ClientSocketPool which will crash if the group was not cleared properly. |
-TEST_F(ClientSocketPoolTest, CancelRequestClearGroup) { |
- TestSocketRequest req(pool_.get(), &request_order_); |
- EXPECT_EQ(ERR_IO_PENDING, |
- req.handle.Init("a", "www.google.com", 80, 5, &req)); |
- req.handle.Reset(); |
- // There is a race condition here. If the worker pool doesn't post the task |
- // before we get here, then this might not run ConnectingSocket::IOComplete |
- // and therefore leak the canceled ConnectingSocket. |
- MessageLoop::current()->RunAllPending(); |
+ EXPECT_EQ(kMaxSocketsPerGroup + kNumPendingRequests, |
+ MockClientSocket::allocation_count); |
+ EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); |
} |
TEST_F(ClientSocketPoolTest, CancelRequest) { |
- scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
+ int rv; |
+ |
+ scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + kNumPendingRequests]; |
for (size_t i = 0; i < arraysize(reqs); ++i) |
reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); |
// Create connections or queue up requests. |
for (int i = 0; i < kMaxSocketsPerGroup; ++i) { |
- EXPECT_EQ( |
- ERR_IO_PENDING, |
- reqs[i]->handle.Init("a", "www.google.com", 80, 5, reqs[i].get())); |
- EXPECT_EQ(OK, reqs[i]->WaitForResult()); |
+ rv = reqs[i]->handle.Init("a", 5, reqs[i].get()); |
+ EXPECT_EQ(net::OK, rv); |
+ reqs[i]->EnsureSocket(); |
} |
- |
for (int i = 0; i < kNumPendingRequests; ++i) { |
- EXPECT_EQ(ERR_IO_PENDING, reqs[kMaxSocketsPerGroup + i]->handle.Init( |
- "a", "www.google.com", 80, kPriorities[i], |
- reqs[kMaxSocketsPerGroup + i].get())); |
+ rv = reqs[kMaxSocketsPerGroup + i]->handle.Init( |
+ "a", kPriorities[i], reqs[kMaxSocketsPerGroup + i].get()); |
+ EXPECT_EQ(net::ERR_IO_PENDING, rv); |
} |
// Cancel a request. |
@@ -362,8 +266,8 @@ TEST_F(ClientSocketPoolTest, CancelRequest) { |
} |
} while (released_one); |
- EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); |
- EXPECT_EQ(kNumRequests - 1, TestSocketRequest::completion_count); |
+ EXPECT_EQ(kMaxSocketsPerGroup, MockClientSocket::allocation_count); |
+ EXPECT_EQ(kNumPendingRequests - 1, TestSocketRequest::completion_count); |
for (int i = 0; i < kMaxSocketsPerGroup; ++i) { |
EXPECT_EQ(request_order_[i], reqs[i].get()) << |
"Request " << i << " was not in order."; |
@@ -386,5 +290,3 @@ TEST_F(ClientSocketPoolTest, CancelRequest) { |
} |
} // namespace |
- |
-} // namespace net |