summaryrefslogtreecommitdiffstats
path: root/net/base/client_socket_pool_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/base/client_socket_pool_unittest.cc')
-rw-r--r--net/base/client_socket_pool_unittest.cc274
1 files changed, 88 insertions, 186 deletions
diff --git a/net/base/client_socket_pool_unittest.cc b/net/base/client_socket_pool_unittest.cc
index 73fc0e3..a889d9a 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