Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(377)

Unified Diff: net/socket/client_socket_pool_base_unittest.cc

Issue 19278016: Add load states for stalled requests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Fix comment Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/client_socket_pool_base.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/client_socket_pool_base_unittest.cc
===================================================================
--- net/socket/client_socket_pool_base_unittest.cc (revision 211022)
+++ net/socket/client_socket_pool_base_unittest.cc (working copy)
@@ -220,8 +220,13 @@
}
void WaitForSignal(TestConnectJob* job) { waiting_jobs_.push_back(job); }
+
void SignalJobs();
+ void SignalJob(size_t job);
+
+ void SetJobLoadState(size_t job, LoadState load_state);
+
int allocation_count() const { return allocation_count_; }
private:
@@ -237,7 +242,6 @@
kMockPendingJob,
kMockPendingFailingJob,
kMockWaitingJob,
- kMockAdvancingLoadStateJob,
kMockRecoverableJob,
kMockPendingRecoverableJob,
kMockAdditionalErrorStateJob,
@@ -267,6 +271,10 @@
DoConnect(waiting_success_, true /* async */, false /* recoverable */);
}
+ void set_load_state(LoadState load_state) { load_state_ = load_state; }
+
+ // From ConnectJob:
+
virtual LoadState GetLoadState() const OVERRIDE { return load_state_; }
virtual void GetAdditionalErrorState(ClientSocketHandle* handle) OVERRIDE {
@@ -280,7 +288,7 @@
}
private:
- // ConnectJob implementation.
+ // From ConnectJob:
virtual int ConnectInternal() OVERRIDE {
AddressList ignored;
@@ -329,14 +337,10 @@
base::TimeDelta::FromMilliseconds(2));
return ERR_IO_PENDING;
case kMockWaitingJob:
+ set_load_state(LOAD_STATE_CONNECTING);
client_socket_factory_->WaitForSignal(this);
waiting_success_ = true;
return ERR_IO_PENDING;
- case kMockAdvancingLoadStateJob:
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&TestConnectJob::AdvanceLoadState,
- weak_factory_.GetWeakPtr(), load_state_));
- return ERR_IO_PENDING;
case kMockRecoverableJob:
return DoConnect(false /* error */, false /* sync */,
true /* recoverable */);
@@ -374,8 +378,6 @@
}
}
- void set_load_state(LoadState load_state) { load_state_ = load_state; }
-
int DoConnect(bool succeed, bool was_async, bool recoverable) {
int result = OK;
if (succeed) {
@@ -392,22 +394,6 @@
return result;
}
- // This function helps simulate the progress of load states on a ConnectJob.
- // Each time it is called it advances the load state and posts a task to be
- // called again. It stops at the last connecting load state (the one
- // before LOAD_STATE_SENDING_REQUEST).
- void AdvanceLoadState(LoadState state) {
- int tmp = state;
- tmp++;
- if (tmp < LOAD_STATE_SENDING_REQUEST) {
- state = static_cast<LoadState>(tmp);
- set_load_state(state);
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&TestConnectJob::AdvanceLoadState,
- weak_factory_.GetWeakPtr(), state));
- }
- }
-
bool waiting_success_;
const JobType job_type_;
MockClientSocketFactory* const client_socket_factory_;
@@ -624,6 +610,18 @@
waiting_jobs_.clear();
}
+void MockClientSocketFactory::SignalJob(size_t job) {
+ ASSERT_LT(job, waiting_jobs_.size());
+ waiting_jobs_[job]->Signal();
+ waiting_jobs_.erase(waiting_jobs_.begin() + job);
+}
+
+void MockClientSocketFactory::SetJobLoadState(size_t job,
+ LoadState load_state) {
+ ASSERT_LT(job, waiting_jobs_.size());
+ waiting_jobs_[job]->set_load_state(load_state);
+}
+
class TestConnectJobDelegate : public ConnectJob::Delegate {
public:
TestConnectJobDelegate()
@@ -1924,10 +1922,10 @@
EXPECT_EQ(&req3, request_order[2]);
}
-TEST_F(ClientSocketPoolBaseTest, LoadState) {
+// Test GetLoadState in the case there's only one socket request.
+TEST_F(ClientSocketPoolBaseTest, LoadStateOneRequest) {
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
- connect_job_factory_->set_job_type(
- TestConnectJob::kMockAdvancingLoadStateJob);
+ connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -1938,19 +1936,167 @@
pool_.get(),
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
- EXPECT_EQ(LOAD_STATE_IDLE, handle.GetLoadState());
+ EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState());
- base::MessageLoop::current()->RunUntilIdle();
+ client_socket_factory_.SetJobLoadState(0, LOAD_STATE_SSL_HANDSHAKE);
+ EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, handle.GetLoadState());
+ // No point in completing the connection, since ClientSocketHandles only
+ // expect the LoadState to be checked while connecting.
+}
+
+// Test GetLoadState in the case there are two socket requests.
+TEST_F(ClientSocketPoolBaseTest, LoadStateTwoRequests) {
+ CreatePool(2, 2);
+ connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
+
+ ClientSocketHandle handle;
+ TestCompletionCallback callback;
+ int rv = handle.Init("a",
+ params_,
+ kDefaultPriority,
+ callback.callback(),
+ pool_.get(),
+ BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
ClientSocketHandle handle2;
TestCompletionCallback callback2;
- rv = handle2.Init("a", params_, kDefaultPriority, callback2.callback(),
- pool_.get(), BoundNetLog());
+ rv = handle2.Init("a",
+ params_,
+ kDefaultPriority,
+ callback2.callback(),
+ pool_.get(),
+ BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
- EXPECT_NE(LOAD_STATE_IDLE, handle.GetLoadState());
- EXPECT_NE(LOAD_STATE_IDLE, handle2.GetLoadState());
+
+ // If the first Job is in an earlier state than the second, the state of
+ // the second job should be used for both handles.
+ client_socket_factory_.SetJobLoadState(0, LOAD_STATE_RESOLVING_HOST);
+ EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState());
+ EXPECT_EQ(LOAD_STATE_CONNECTING, handle2.GetLoadState());
+
+ // If the second Job is in an earlier state than the second, the state of
+ // the first job should be used for both handles.
+ client_socket_factory_.SetJobLoadState(0, LOAD_STATE_SSL_HANDSHAKE);
+ // One request is farther
+ EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, handle.GetLoadState());
+ EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, handle2.GetLoadState());
+
+ // Farthest along job connects and the first request gets the socket. The
+ // second handle switches to the state of the remaining ConnectJob.
+ client_socket_factory_.SignalJob(0);
+ EXPECT_EQ(OK, callback.WaitForResult());
+ EXPECT_EQ(LOAD_STATE_CONNECTING, handle2.GetLoadState());
}
+// Test GetLoadState in the case the per-group limit is reached.
+TEST_F(ClientSocketPoolBaseTest, LoadStateGroupLimit) {
+ CreatePool(2, 1);
+ connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
+
+ ClientSocketHandle handle;
+ TestCompletionCallback callback;
+ int rv = handle.Init("a",
+ params_,
+ MEDIUM,
+ callback.callback(),
+ pool_.get(),
+ BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState());
+
+ // Request another socket from the same pool, buth with a higher priority.
+ // The first request should now be stalled at the socket group limit.
+ ClientSocketHandle handle2;
+ TestCompletionCallback callback2;
+ rv = handle2.Init("a",
+ params_,
+ HIGHEST,
+ callback2.callback(),
+ pool_.get(),
+ BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET, handle.GetLoadState());
+ EXPECT_EQ(LOAD_STATE_CONNECTING, handle2.GetLoadState());
+
+ // The first handle should remain stalled as the other socket goes through
+ // the connect process.
+
+ client_socket_factory_.SetJobLoadState(0, LOAD_STATE_SSL_HANDSHAKE);
+ EXPECT_EQ(LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET, handle.GetLoadState());
+ EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, handle2.GetLoadState());
+
+ client_socket_factory_.SignalJob(0);
+ EXPECT_EQ(OK, callback2.WaitForResult());
+ EXPECT_EQ(LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET, handle.GetLoadState());
+
+ // Closing the second socket should cause the stalled handle to finally get a
+ // ConnectJob.
+ handle2.socket()->Disconnect();
+ handle2.Reset();
+ EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState());
+}
+
+// Test GetLoadState in the case the per-pool limit is reached.
+TEST_F(ClientSocketPoolBaseTest, LoadStatePoolLimit) {
+ CreatePool(2, 2);
+ connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
+
+ ClientSocketHandle handle;
+ TestCompletionCallback callback;
+ int rv = handle.Init("a",
+ params_,
+ kDefaultPriority,
+ callback.callback(),
+ pool_.get(),
+ BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Request for socket from another pool.
+ ClientSocketHandle handle2;
+ TestCompletionCallback callback2;
+ rv = handle2.Init("b",
+ params_,
+ kDefaultPriority,
+ callback2.callback(),
+ pool_.get(),
+ BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Request another socket from the first pool. Request should stall at the
+ // socket pool limit.
+ ClientSocketHandle handle3;
+ TestCompletionCallback callback3;
+ rv = handle3.Init("a",
+ params_,
+ kDefaultPriority,
+ callback2.callback(),
+ pool_.get(),
+ BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // The third handle should remain stalled as the other sockets in its group
+ // goes through the connect process.
+
+ EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState());
+ EXPECT_EQ(LOAD_STATE_WAITING_FOR_STALLED_SOCKET_POOL, handle3.GetLoadState());
+
+ client_socket_factory_.SetJobLoadState(0, LOAD_STATE_SSL_HANDSHAKE);
+ EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, handle.GetLoadState());
+ EXPECT_EQ(LOAD_STATE_WAITING_FOR_STALLED_SOCKET_POOL, handle3.GetLoadState());
+
+ client_socket_factory_.SignalJob(0);
+ EXPECT_EQ(OK, callback.WaitForResult());
+ EXPECT_EQ(LOAD_STATE_WAITING_FOR_STALLED_SOCKET_POOL, handle3.GetLoadState());
+
+ // Closing a socket should allow the stalled handle to finally get a new
+ // ConnectJob.
+ handle.socket()->Disconnect();
+ handle.Reset();
+ EXPECT_EQ(LOAD_STATE_CONNECTING, handle3.GetLoadState());
+}
+
TEST_F(ClientSocketPoolBaseTest, Recoverable) {
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
connect_job_factory_->set_job_type(TestConnectJob::kMockRecoverableJob);
« no previous file with comments | « net/socket/client_socket_pool_base.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698