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 087db231d7fea52127690994a945d2fe5847dae4..b35ed2420faa14d1121fa2de3bf3bca938101fc3 100644 |
--- a/net/socket/client_socket_pool_base_unittest.cc |
+++ b/net/socket/client_socket_pool_base_unittest.cc |
@@ -9,6 +9,7 @@ |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
#include "base/callback.h" |
+#include "base/logging.h" |
#include "base/memory/ref_counted.h" |
#include "base/memory/scoped_vector.h" |
#include "base/memory/weak_ptr.h" |
@@ -1427,125 +1428,77 @@ TEST_F(ClientSocketPoolBaseTest, CancelRequest) { |
EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(8)); |
} |
-class RequestSocketCallback : public TestCompletionCallbackBase { |
- public: |
- RequestSocketCallback(ClientSocketHandle* handle, |
- TestClientSocketPool* pool, |
- TestConnectJobFactory* test_connect_job_factory, |
- TestConnectJob::JobType next_job_type) |
- : handle_(handle), |
- pool_(pool), |
- within_callback_(false), |
- test_connect_job_factory_(test_connect_job_factory), |
- next_job_type_(next_job_type), |
- callback_(base::Bind(&RequestSocketCallback::OnComplete, |
- base::Unretained(this))) { |
- } |
- |
- ~RequestSocketCallback() override {} |
- |
- const CompletionCallback& callback() const { return callback_; } |
- |
- private: |
- void OnComplete(int result) { |
- SetResult(result); |
- ASSERT_EQ(OK, result); |
- |
- if (!within_callback_) { |
- test_connect_job_factory_->set_job_type(next_job_type_); |
- |
- // Don't allow reuse of the socket. Disconnect it and then release it and |
- // run through the MessageLoop once to get it completely released. |
- handle_->socket()->Disconnect(); |
- handle_->Reset(); |
- { |
- // TODO: Resolve conflicting intentions of stopping recursion with the |
- // |!within_callback_| test (above) and the call to |RunUntilIdle()| |
- // below. http://crbug.com/114130. |
- base::MessageLoop::ScopedNestableTaskAllower allow( |
- base::MessageLoop::current()); |
- base::MessageLoop::current()->RunUntilIdle(); |
- } |
- within_callback_ = true; |
- TestCompletionCallback next_job_callback; |
- scoped_refptr<TestSocketParams> params( |
- new TestSocketParams(false /* ignore_limits */)); |
- int rv = handle_->Init("a", |
- params, |
- DEFAULT_PRIORITY, |
- next_job_callback.callback(), |
- pool_, |
- BoundNetLog()); |
- switch (next_job_type_) { |
- case TestConnectJob::kMockJob: |
- EXPECT_EQ(OK, rv); |
- break; |
- case TestConnectJob::kMockPendingJob: |
- EXPECT_EQ(ERR_IO_PENDING, rv); |
- |
- // For pending jobs, wait for new socket to be created. This makes |
- // sure there are no more pending operations nor any unclosed sockets |
- // when the test finishes. |
- // We need to give it a little bit of time to run, so that all the |
- // operations that happen on timers (e.g. cleanup of idle |
- // connections) can execute. |
- { |
- base::MessageLoop::ScopedNestableTaskAllower allow( |
- base::MessageLoop::current()); |
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); |
- EXPECT_EQ(OK, next_job_callback.WaitForResult()); |
- } |
- break; |
- default: |
- FAIL() << "Unexpected job type: " << next_job_type_; |
- break; |
- } |
- } |
+// Function to be used as a callback on socket request completion. It first |
+// disconnects the successfully connected socket from the first request, and |
+// then reuses the ClientSocketHandle to request another socket. |
+// |
+// |nested_callback| is called with the result of the second socket request. |
+void RequestSocketOnComplete(ClientSocketHandle* handle, |
+ TestClientSocketPool* pool, |
+ TestConnectJobFactory* test_connect_job_factory, |
+ TestConnectJob::JobType next_job_type, |
+ const CompletionCallback& nested_callback, |
+ int first_request_result) { |
+ EXPECT_EQ(OK, first_request_result); |
+ |
+ test_connect_job_factory->set_job_type(next_job_type); |
+ |
+ // Don't allow reuse of the socket. Disconnect it and then release it. |
+ if (handle->socket()) |
+ handle->socket()->Disconnect(); |
+ handle->Reset(); |
+ |
+ scoped_refptr<TestSocketParams> params( |
+ new TestSocketParams(false /* ignore_limits */)); |
+ TestCompletionCallback callback; |
+ int rv = |
+ handle->Init("a", params, LOWEST, nested_callback, pool, BoundNetLog()); |
+ if (rv != ERR_IO_PENDING) { |
+ DCHECK_EQ(TestConnectJob::kMockJob, next_job_type); |
+ nested_callback.Run(rv); |
+ } else { |
+ DCHECK_EQ(TestConnectJob::kMockPendingJob, next_job_type); |
} |
+} |
- ClientSocketHandle* const handle_; |
- TestClientSocketPool* const pool_; |
- bool within_callback_; |
- TestConnectJobFactory* const test_connect_job_factory_; |
- TestConnectJob::JobType next_job_type_; |
- CompletionCallback callback_; |
-}; |
- |
+// Tests the case where a second socket is requested in a completion callback, |
+// and the second socket connects asynchronously. Reuses the same |
+// ClientSocketHandle for the second socket, after disconnecting the first. |
TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { |
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
ClientSocketHandle handle; |
- RequestSocketCallback callback( |
- &handle, pool_.get(), connect_job_factory_, |
- TestConnectJob::kMockPendingJob); |
- int rv = handle.Init("a", |
- params_, |
- DEFAULT_PRIORITY, |
- callback.callback(), |
- pool_.get(), |
- BoundNetLog()); |
+ TestCompletionCallback second_result_callback; |
+ int rv = handle.Init( |
+ "a", params_, DEFAULT_PRIORITY, |
+ base::Bind(&RequestSocketOnComplete, &handle, pool_.get(), |
+ connect_job_factory_, TestConnectJob::kMockPendingJob, |
+ second_result_callback.callback()), |
+ pool_.get(), BoundNetLog()); |
ASSERT_EQ(ERR_IO_PENDING, rv); |
- EXPECT_EQ(OK, callback.WaitForResult()); |
+ EXPECT_EQ(OK, second_result_callback.WaitForResult()); |
} |
+// Tests the case where a second socket is requested in a completion callback, |
+// and the second socket connects synchronously. Reuses the same |
+// ClientSocketHandle for the second socket, after disconnecting the first. |
TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { |
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
ClientSocketHandle handle; |
- RequestSocketCallback callback( |
- &handle, pool_.get(), connect_job_factory_, TestConnectJob::kMockJob); |
- int rv = handle.Init("a", |
- params_, |
- DEFAULT_PRIORITY, |
- callback.callback(), |
- pool_.get(), |
- BoundNetLog()); |
+ TestCompletionCallback second_result_callback; |
+ int rv = handle.Init( |
+ "a", params_, DEFAULT_PRIORITY, |
+ base::Bind(&RequestSocketOnComplete, &handle, pool_.get(), |
+ connect_job_factory_, TestConnectJob::kMockPendingJob, |
+ second_result_callback.callback()), |
+ pool_.get(), BoundNetLog()); |
ASSERT_EQ(ERR_IO_PENDING, rv); |
- EXPECT_EQ(OK, callback.WaitForResult()); |
+ EXPECT_EQ(OK, second_result_callback.WaitForResult()); |
} |
// Make sure that pending requests get serviced after active requests get |