Index: net/socket/client_socket_pool_base_unittest.cc |
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc |
index ef9f15f882746433f1afac88e13491b55507a764..7bb5ae71eb5b6976e68bd39b8ddb1a365007ce90 100644 |
--- a/net/socket/client_socket_pool_base_unittest.cc |
+++ b/net/socket/client_socket_pool_base_unittest.cc |
@@ -134,11 +134,9 @@ class TestConnectJob : public ConnectJob { |
const ClientSocketPoolBase::Request& request, |
ConnectJob::Delegate* delegate, |
ClientSocketFactory* client_socket_factory) |
- : job_type_(job_type), |
- group_name_(group_name), |
- handle_(request.handle), |
+ : ConnectJob(group_name, request.handle, delegate), |
+ job_type_(job_type), |
client_socket_factory_(client_socket_factory), |
- delegate_(delegate), |
method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} |
// ConnectJob methods: |
@@ -176,22 +174,19 @@ class TestConnectJob : public ConnectJob { |
private: |
int DoConnect(bool succeed, bool was_async) { |
int result = ERR_CONNECTION_FAILED; |
- ClientSocket* socket = NULL; |
if (succeed) { |
result = OK; |
- socket = new MockClientSocket(); |
- socket->Connect(NULL); |
+ set_socket(new MockClientSocket()); |
+ socket()->Connect(NULL); |
} |
- delegate_->OnConnectJobComplete( |
- group_name_, handle_, socket, result, was_async); |
+ |
+ if (was_async) |
+ delegate()->OnConnectJobComplete(result, this); |
return result; |
} |
const JobType job_type_; |
- const std::string group_name_; |
- const ClientSocketHandle* handle_; |
ClientSocketFactory* const client_socket_factory_; |
- Delegate* const delegate_; |
ScopedRunnableMethodFactory<TestConnectJob> method_factory_; |
DISALLOW_COPY_AND_ASSIGN(TestConnectJob); |
@@ -530,20 +525,35 @@ TEST_F(ClientSocketPoolBaseTest, CancelRequest) { |
class RequestSocketCallback : public CallbackRunner< Tuple1<int> > { |
public: |
- RequestSocketCallback(ClientSocketHandle* handle) |
+ RequestSocketCallback(ClientSocketHandle* handle, |
+ TestConnectJobFactory* test_connect_job_factory, |
+ TestConnectJob::JobType next_job_type) |
: handle_(handle), |
- within_callback_(false) {} |
+ within_callback_(false), |
+ test_connect_job_factory_(test_connect_job_factory), |
+ next_job_type_(next_job_type) {} |
virtual void RunWithParams(const Tuple1<int>& params) { |
callback_.RunWithParams(params); |
ASSERT_EQ(OK, params.a); |
if (!within_callback_) { |
+ test_connect_job_factory_->set_job_type(next_job_type_); |
handle_->Reset(); |
within_callback_ = true; |
int rv = handle_->Init( |
"a", HostResolver::RequestInfo("www.google.com", 80), 0, this); |
- EXPECT_EQ(ERR_IO_PENDING, rv); |
+ switch (next_job_type_) { |
+ case TestConnectJob::kMockJob: |
+ EXPECT_EQ(OK, rv); |
+ break; |
+ case TestConnectJob::kMockPendingJob: |
+ EXPECT_EQ(ERR_IO_PENDING, rv); |
+ break; |
+ default: |
+ FAIL() << "Unexpected job type: " << next_job_type_; |
+ break; |
+ } |
} |
} |
@@ -554,19 +564,34 @@ class RequestSocketCallback : public CallbackRunner< Tuple1<int> > { |
private: |
ClientSocketHandle* const handle_; |
bool within_callback_; |
+ TestConnectJobFactory* const test_connect_job_factory_; |
+ TestConnectJob::JobType next_job_type_; |
TestCompletionCallback callback_; |
}; |
-TEST_F(ClientSocketPoolBaseTest, RequestTwice) { |
+TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { |
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
ClientSocketHandle handle(pool_.get()); |
- RequestSocketCallback callback(&handle); |
+ RequestSocketCallback callback( |
+ &handle, connect_job_factory_, TestConnectJob::kMockPendingJob); |
int rv = handle.Init( |
"a", ignored_request_info_, 0, &callback); |
ASSERT_EQ(ERR_IO_PENDING, rv); |
EXPECT_EQ(OK, callback.WaitForResult()); |
+ handle.Reset(); |
+} |
+TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { |
+ connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
+ ClientSocketHandle handle(pool_.get()); |
+ RequestSocketCallback callback( |
+ &handle, connect_job_factory_, TestConnectJob::kMockJob); |
+ int rv = handle.Init( |
+ "a", ignored_request_info_, 0, &callback); |
+ ASSERT_EQ(ERR_IO_PENDING, rv); |
+ |
+ EXPECT_EQ(OK, callback.WaitForResult()); |
handle.Reset(); |
} |
@@ -615,6 +640,45 @@ TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) { |
EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult()); |
} |
+// A pending asynchronous job completes, which will free up a socket slot. The |
+// next job finishes synchronously. The callback for the asynchronous job |
+// should be first though. |
+TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) { |
+ // First two jobs are async. |
+ connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); |
+ |
+ // Start job 1 (async error). |
+ TestSocketRequest req1(pool_.get(), &request_order_); |
+ int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1); |
+ EXPECT_EQ(ERR_IO_PENDING, rv); |
+ |
+ // Start job 2 (async error). |
+ TestSocketRequest req2(pool_.get(), &request_order_); |
+ rv = req2.handle.Init("a", ignored_request_info_, 5, &req2); |
+ EXPECT_EQ(ERR_IO_PENDING, rv); |
+ |
+ // The pending job is sync. |
+ connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
+ |
+ // Request 3 does not have a ConnectJob yet. It's just pending. |
+ TestSocketRequest req3(pool_.get(), &request_order_); |
+ rv = req3.handle.Init("a", ignored_request_info_, 5, &req3); |
+ EXPECT_EQ(ERR_IO_PENDING, rv); |
+ |
+ EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult()); |
+ EXPECT_EQ(ERR_CONNECTION_FAILED, req2.WaitForResult()); |
+ EXPECT_EQ(OK, req3.WaitForResult()); |
+ |
+ ASSERT_EQ(3U, request_order_.size()); |
+ |
+ // After job 1 finishes unsuccessfully, it will try to process the pending |
+ // requests queue, so it starts up job 3 for request 3. This job |
+ // synchronously succeeds, so the request order is 1, 3, 2. |
+ EXPECT_EQ(&req1, request_order_[0]); |
+ EXPECT_EQ(&req2, request_order_[2]); |
+ EXPECT_EQ(&req3, request_order_[1]); |
+} |
+ |
} // namespace |
} // namespace net |