blob: 8c0e6ea379a8179fe54d319fdecf390e252cb5ec [file] [log] [blame]
[email protected]7fc5b09a2010-02-27 00:07:381// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]f6d1d6eb2009-06-24 20:16:092// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]ab838892009-06-30 18:49:055#include "net/socket/client_socket_pool_base.h"
[email protected]f6d1d6eb2009-06-24 20:16:096
[email protected]2041cf342010-02-19 03:15:597#include "base/callback.h"
[email protected]f6d1d6eb2009-06-24 20:16:098#include "base/compiler_specific.h"
9#include "base/message_loop.h"
[email protected]974ebd62009-08-03 23:14:3410#include "base/platform_thread.h"
[email protected]c9d6a1d2009-07-14 16:15:2011#include "base/scoped_vector.h"
[email protected]89628072010-06-08 05:50:5812#include "base/string_util.h"
[email protected]9e743cd2010-03-16 07:03:5313#include "net/base/net_log.h"
14#include "net/base/net_log_unittest.h"
[email protected]f6d1d6eb2009-06-24 20:16:0915#include "net/base/net_errors.h"
[email protected]ac790b42009-12-02 04:31:3116#include "net/base/request_priority.h"
[email protected]f6d1d6eb2009-06-24 20:16:0917#include "net/base/test_completion_callback.h"
18#include "net/socket/client_socket.h"
19#include "net/socket/client_socket_factory.h"
20#include "net/socket/client_socket_handle.h"
[email protected]b89f7e42010-05-20 20:37:0021#include "net/socket/client_socket_pool_histograms.h"
[email protected]75439d3b2009-07-23 22:11:1722#include "net/socket/socket_test_util.h"
[email protected]f6d1d6eb2009-06-24 20:16:0923#include "testing/gtest/include/gtest/gtest.h"
24
25namespace net {
26
27namespace {
28
[email protected]211d21722009-07-22 15:48:5329const int kDefaultMaxSockets = 4;
[email protected]c9d6a1d2009-07-14 16:15:2030const int kDefaultMaxSocketsPerGroup = 2;
[email protected]a554a8262010-05-20 00:13:5231const net::RequestPriority kDefaultPriority = MEDIUM;
[email protected]0b7648c2009-07-06 20:14:0132
[email protected]7fc5b09a2010-02-27 00:07:3833typedef const void* TestSocketParams;
34typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase;
[email protected]d80a4322009-08-14 07:07:4935
[email protected]f6d1d6eb2009-06-24 20:16:0936class MockClientSocket : public ClientSocket {
37 public:
38 MockClientSocket() : connected_(false) {}
39
[email protected]ab838892009-06-30 18:49:0540 // Socket methods:
41 virtual int Read(
42 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) {
43 return ERR_UNEXPECTED;
44 }
45
46 virtual int Write(
47 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) {
48 return ERR_UNEXPECTED;
49 }
[email protected]06650c52010-06-03 00:49:1750 virtual bool SetReceiveBufferSize(int32 size) { return true; }
51 virtual bool SetSendBufferSize(int32 size) { return true; }
[email protected]ab838892009-06-30 18:49:0552
[email protected]f6d1d6eb2009-06-24 20:16:0953 // ClientSocket methods:
[email protected]ab838892009-06-30 18:49:0554
[email protected]a2006ece2010-04-23 16:44:0255 virtual int Connect(CompletionCallback* callback) {
[email protected]f6d1d6eb2009-06-24 20:16:0956 connected_ = true;
57 return OK;
58 }
[email protected]f6d1d6eb2009-06-24 20:16:0959
[email protected]ab838892009-06-30 18:49:0560 virtual void Disconnect() { connected_ = false; }
61 virtual bool IsConnected() const { return connected_; }
62 virtual bool IsConnectedAndIdle() const { return connected_; }
[email protected]0b7648c2009-07-06 20:14:0163
[email protected]ac9eec62010-02-20 18:50:3864 virtual int GetPeerAddress(AddressList* /* address */) const {
[email protected]9f864b32010-01-20 15:01:1665 return ERR_UNEXPECTED;
[email protected]f6d1d6eb2009-06-24 20:16:0966 }
[email protected]f6d1d6eb2009-06-24 20:16:0967
[email protected]a2006ece2010-04-23 16:44:0268 virtual const BoundNetLog& NetLog() const {
69 return net_log_;
70 }
71
[email protected]f6d1d6eb2009-06-24 20:16:0972 private:
73 bool connected_;
[email protected]a2006ece2010-04-23 16:44:0274 BoundNetLog net_log_;
[email protected]f6d1d6eb2009-06-24 20:16:0975
[email protected]ab838892009-06-30 18:49:0576 DISALLOW_COPY_AND_ASSIGN(MockClientSocket);
[email protected]f6d1d6eb2009-06-24 20:16:0977};
78
[email protected]5fc08e32009-07-15 17:09:5779class TestConnectJob;
80
[email protected]f6d1d6eb2009-06-24 20:16:0981class MockClientSocketFactory : public ClientSocketFactory {
82 public:
[email protected]ab838892009-06-30 18:49:0583 MockClientSocketFactory() : allocation_count_(0) {}
[email protected]f6d1d6eb2009-06-24 20:16:0984
[email protected]a2006ece2010-04-23 16:44:0285 virtual ClientSocket* CreateTCPClientSocket(const AddressList& addresses,
86 NetLog* /* net_log */) {
[email protected]f6d1d6eb2009-06-24 20:16:0987 allocation_count_++;
[email protected]ab838892009-06-30 18:49:0588 return NULL;
[email protected]f6d1d6eb2009-06-24 20:16:0989 }
90
91 virtual SSLClientSocket* CreateSSLClientSocket(
92 ClientSocket* transport_socket,
93 const std::string& hostname,
94 const SSLConfig& ssl_config) {
95 NOTIMPLEMENTED();
96 return NULL;
97 }
98
[email protected]5fc08e32009-07-15 17:09:5799 void WaitForSignal(TestConnectJob* job) { waiting_jobs_.push_back(job); }
100 void SignalJobs();
101
[email protected]f6d1d6eb2009-06-24 20:16:09102 int allocation_count() const { return allocation_count_; }
103
[email protected]f6d1d6eb2009-06-24 20:16:09104 private:
105 int allocation_count_;
[email protected]5fc08e32009-07-15 17:09:57106 std::vector<TestConnectJob*> waiting_jobs_;
[email protected]f6d1d6eb2009-06-24 20:16:09107};
108
[email protected]ab838892009-06-30 18:49:05109class TestConnectJob : public ConnectJob {
110 public:
111 enum JobType {
112 kMockJob,
113 kMockFailingJob,
114 kMockPendingJob,
115 kMockPendingFailingJob,
[email protected]5fc08e32009-07-15 17:09:57116 kMockWaitingJob,
117 kMockAdvancingLoadStateJob,
[email protected]ab838892009-06-30 18:49:05118 };
119
120 TestConnectJob(JobType job_type,
121 const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49122 const TestClientSocketPoolBase::Request& request,
[email protected]974ebd62009-08-03 23:14:34123 base::TimeDelta timeout_duration,
[email protected]ab838892009-06-30 18:49:05124 ConnectJob::Delegate* delegate,
[email protected]fd7b7c92009-08-20 19:38:30125 MockClientSocketFactory* client_socket_factory,
[email protected]06650c52010-06-03 00:49:17126 NetLog* net_log)
127 : ConnectJob(group_name, timeout_duration, delegate,
128 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
[email protected]2ab05b52009-07-01 23:57:58129 job_type_(job_type),
[email protected]ab838892009-06-30 18:49:05130 client_socket_factory_(client_socket_factory),
[email protected]46451352009-09-01 14:54:21131 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
132 load_state_(LOAD_STATE_IDLE) {}
[email protected]ab838892009-06-30 18:49:05133
[email protected]974ebd62009-08-03 23:14:34134 void Signal() {
135 DoConnect(waiting_success_, true /* async */);
136 }
137
[email protected]46451352009-09-01 14:54:21138 virtual LoadState GetLoadState() const { return load_state_; }
139
[email protected]974ebd62009-08-03 23:14:34140 private:
[email protected]ab838892009-06-30 18:49:05141 // ConnectJob methods:
142
[email protected]974ebd62009-08-03 23:14:34143 virtual int ConnectInternal() {
[email protected]ab838892009-06-30 18:49:05144 AddressList ignored;
[email protected]a2006ece2010-04-23 16:44:02145 client_socket_factory_->CreateTCPClientSocket(ignored, NULL);
[email protected]6e713f02009-08-06 02:56:40146 set_socket(new MockClientSocket());
[email protected]ab838892009-06-30 18:49:05147 switch (job_type_) {
148 case kMockJob:
149 return DoConnect(true /* successful */, false /* sync */);
150 case kMockFailingJob:
151 return DoConnect(false /* error */, false /* sync */);
152 case kMockPendingJob:
[email protected]5fc08e32009-07-15 17:09:57153 set_load_state(LOAD_STATE_CONNECTING);
[email protected]6b175382009-10-13 06:47:47154
155 // Depending on execution timings, posting a delayed task can result
156 // in the task getting executed the at the earliest possible
157 // opportunity or only after returning once from the message loop and
158 // then a second call into the message loop. In order to make behavior
159 // more deterministic, we change the default delay to 2ms. This should
160 // always require us to wait for the second call into the message loop.
161 //
162 // N.B. The correct fix for this and similar timing problems is to
163 // abstract time for the purpose of unittests. Unfortunately, we have
164 // a lot of third-party components that directly call the various
165 // time functions, so this change would be rather invasive.
166 MessageLoop::current()->PostDelayedTask(
[email protected]ab838892009-06-30 18:49:05167 FROM_HERE,
168 method_factory_.NewRunnableMethod(
[email protected]6b175382009-10-13 06:47:47169 &TestConnectJob::DoConnect,
170 true /* successful */,
171 true /* async */),
172 2);
[email protected]ab838892009-06-30 18:49:05173 return ERR_IO_PENDING;
174 case kMockPendingFailingJob:
[email protected]5fc08e32009-07-15 17:09:57175 set_load_state(LOAD_STATE_CONNECTING);
[email protected]6b175382009-10-13 06:47:47176 MessageLoop::current()->PostDelayedTask(
[email protected]ab838892009-06-30 18:49:05177 FROM_HERE,
178 method_factory_.NewRunnableMethod(
[email protected]6b175382009-10-13 06:47:47179 &TestConnectJob::DoConnect,
180 false /* error */,
181 true /* async */),
182 2);
[email protected]ab838892009-06-30 18:49:05183 return ERR_IO_PENDING;
[email protected]5fc08e32009-07-15 17:09:57184 case kMockWaitingJob:
185 client_socket_factory_->WaitForSignal(this);
186 waiting_success_ = true;
187 return ERR_IO_PENDING;
188 case kMockAdvancingLoadStateJob:
[email protected]6b175382009-10-13 06:47:47189 MessageLoop::current()->PostDelayedTask(
[email protected]5fc08e32009-07-15 17:09:57190 FROM_HERE,
191 method_factory_.NewRunnableMethod(
[email protected]6b175382009-10-13 06:47:47192 &TestConnectJob::AdvanceLoadState, load_state_),
193 2);
[email protected]5fc08e32009-07-15 17:09:57194 return ERR_IO_PENDING;
[email protected]ab838892009-06-30 18:49:05195 default:
196 NOTREACHED();
[email protected]6e713f02009-08-06 02:56:40197 set_socket(NULL);
[email protected]ab838892009-06-30 18:49:05198 return ERR_FAILED;
199 }
200 }
201
[email protected]46451352009-09-01 14:54:21202 void set_load_state(LoadState load_state) { load_state_ = load_state; }
203
[email protected]ab838892009-06-30 18:49:05204 int DoConnect(bool succeed, bool was_async) {
205 int result = ERR_CONNECTION_FAILED;
[email protected]ab838892009-06-30 18:49:05206 if (succeed) {
207 result = OK;
[email protected]a2006ece2010-04-23 16:44:02208 socket()->Connect(NULL);
[email protected]6e713f02009-08-06 02:56:40209 } else {
210 set_socket(NULL);
[email protected]ab838892009-06-30 18:49:05211 }
[email protected]2ab05b52009-07-01 23:57:58212
213 if (was_async)
[email protected]fd7b7c92009-08-20 19:38:30214 NotifyDelegateOfCompletion(result);
[email protected]ab838892009-06-30 18:49:05215 return result;
216 }
217
[email protected]5fc08e32009-07-15 17:09:57218 void AdvanceLoadState(LoadState state) {
219 int tmp = state;
220 tmp++;
221 state = static_cast<LoadState>(tmp);
222 set_load_state(state);
223 // Post a delayed task so RunAllPending() won't run it.
224 MessageLoop::current()->PostDelayedTask(
225 FROM_HERE,
226 method_factory_.NewRunnableMethod(&TestConnectJob::AdvanceLoadState,
227 state),
228 1 /* 1ms delay */);
229 }
230
231 bool waiting_success_;
[email protected]ab838892009-06-30 18:49:05232 const JobType job_type_;
[email protected]5fc08e32009-07-15 17:09:57233 MockClientSocketFactory* const client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05234 ScopedRunnableMethodFactory<TestConnectJob> method_factory_;
[email protected]46451352009-09-01 14:54:21235 LoadState load_state_;
[email protected]ab838892009-06-30 18:49:05236
237 DISALLOW_COPY_AND_ASSIGN(TestConnectJob);
238};
239
[email protected]d80a4322009-08-14 07:07:49240class TestConnectJobFactory
241 : public TestClientSocketPoolBase::ConnectJobFactory {
[email protected]ab838892009-06-30 18:49:05242 public:
[email protected]5fc08e32009-07-15 17:09:57243 explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory)
[email protected]ab838892009-06-30 18:49:05244 : job_type_(TestConnectJob::kMockJob),
245 client_socket_factory_(client_socket_factory) {}
246
247 virtual ~TestConnectJobFactory() {}
248
249 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; }
250
[email protected]974ebd62009-08-03 23:14:34251 void set_timeout_duration(base::TimeDelta timeout_duration) {
252 timeout_duration_ = timeout_duration;
253 }
254
[email protected]ab838892009-06-30 18:49:05255 // ConnectJobFactory methods:
256
257 virtual ConnectJob* NewConnectJob(
258 const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49259 const TestClientSocketPoolBase::Request& request,
[email protected]06650c52010-06-03 00:49:17260 ConnectJob::Delegate* delegate) const {
[email protected]ab838892009-06-30 18:49:05261 return new TestConnectJob(job_type_,
262 group_name,
263 request,
[email protected]974ebd62009-08-03 23:14:34264 timeout_duration_,
[email protected]ab838892009-06-30 18:49:05265 delegate,
[email protected]fd7b7c92009-08-20 19:38:30266 client_socket_factory_,
[email protected]06650c52010-06-03 00:49:17267 NULL);
[email protected]ab838892009-06-30 18:49:05268 }
269
[email protected]a796bcec2010-03-22 17:17:26270 virtual base::TimeDelta ConnectionTimeout() const {
271 return timeout_duration_;
272 }
273
[email protected]ab838892009-06-30 18:49:05274 private:
275 TestConnectJob::JobType job_type_;
[email protected]974ebd62009-08-03 23:14:34276 base::TimeDelta timeout_duration_;
[email protected]5fc08e32009-07-15 17:09:57277 MockClientSocketFactory* const client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05278
279 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory);
280};
281
282class TestClientSocketPool : public ClientSocketPool {
283 public:
284 TestClientSocketPool(
[email protected]211d21722009-07-22 15:48:53285 int max_sockets,
[email protected]ab838892009-06-30 18:49:05286 int max_sockets_per_group,
[email protected]b89f7e42010-05-20 20:37:00287 const scoped_refptr<ClientSocketPoolHistograms>& histograms,
[email protected]9bf28db2009-08-29 01:35:16288 base::TimeDelta unused_idle_socket_timeout,
289 base::TimeDelta used_idle_socket_timeout,
[email protected]d80a4322009-08-14 07:07:49290 TestClientSocketPoolBase::ConnectJobFactory* connect_job_factory)
[email protected]b89f7e42010-05-20 20:37:00291 : base_(max_sockets, max_sockets_per_group, histograms,
[email protected]9bf28db2009-08-29 01:35:16292 unused_idle_socket_timeout, used_idle_socket_timeout,
[email protected]a554a8262010-05-20 00:13:52293 connect_job_factory, NULL) {}
[email protected]ab838892009-06-30 18:49:05294
295 virtual int RequestSocket(
296 const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49297 const void* params,
[email protected]ac790b42009-12-02 04:31:31298 net::RequestPriority priority,
[email protected]ab838892009-06-30 18:49:05299 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46300 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53301 const BoundNetLog& net_log) {
[email protected]d80a4322009-08-14 07:07:49302 return base_.RequestSocket(
[email protected]9e743cd2010-03-16 07:03:53303 group_name, params, priority, handle, callback, net_log);
[email protected]ab838892009-06-30 18:49:05304 }
305
306 virtual void CancelRequest(
307 const std::string& group_name,
308 const ClientSocketHandle* handle) {
[email protected]d80a4322009-08-14 07:07:49309 base_.CancelRequest(group_name, handle);
[email protected]ab838892009-06-30 18:49:05310 }
311
312 virtual void ReleaseSocket(
313 const std::string& group_name,
[email protected]a7e38572010-06-07 18:22:24314 ClientSocket* socket,
315 int id) {
316 base_.ReleaseSocket(group_name, socket, id);
317 }
318
319 virtual void Flush() {
320 base_.Flush();
[email protected]ab838892009-06-30 18:49:05321 }
322
323 virtual void CloseIdleSockets() {
[email protected]d80a4322009-08-14 07:07:49324 base_.CloseIdleSockets();
[email protected]ab838892009-06-30 18:49:05325 }
326
[email protected]d80a4322009-08-14 07:07:49327 virtual int IdleSocketCount() const { return base_.idle_socket_count(); }
[email protected]ab838892009-06-30 18:49:05328
329 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
[email protected]d80a4322009-08-14 07:07:49330 return base_.IdleSocketCountInGroup(group_name);
[email protected]ab838892009-06-30 18:49:05331 }
332
333 virtual LoadState GetLoadState(const std::string& group_name,
334 const ClientSocketHandle* handle) const {
[email protected]d80a4322009-08-14 07:07:49335 return base_.GetLoadState(group_name, handle);
[email protected]ab838892009-06-30 18:49:05336 }
337
[email protected]a796bcec2010-03-22 17:17:26338 virtual base::TimeDelta ConnectionTimeout() const {
339 return base_.ConnectionTimeout();
340 }
341
[email protected]b89f7e42010-05-20 20:37:00342 virtual scoped_refptr<ClientSocketPoolHistograms> histograms() const {
343 return base_.histograms();
344 }
[email protected]a796bcec2010-03-22 17:17:26345
[email protected]d80a4322009-08-14 07:07:49346 const TestClientSocketPoolBase* base() const { return &base_; }
[email protected]c9d6a1d2009-07-14 16:15:20347
[email protected]974ebd62009-08-03 23:14:34348 int NumConnectJobsInGroup(const std::string& group_name) const {
[email protected]d80a4322009-08-14 07:07:49349 return base_.NumConnectJobsInGroup(group_name);
[email protected]974ebd62009-08-03 23:14:34350 }
351
[email protected]9bf28db2009-08-29 01:35:16352 void CleanupTimedOutIdleSockets() { base_.CleanupIdleSockets(false); }
353
[email protected]89628072010-06-08 05:50:58354 void EnableBackupJobs() { base_.EnableBackupJobs(); }
355
[email protected]ab838892009-06-30 18:49:05356 private:
[email protected]5389bc72009-11-05 23:34:24357 ~TestClientSocketPool() {}
358
[email protected]d80a4322009-08-14 07:07:49359 TestClientSocketPoolBase base_;
[email protected]ab838892009-06-30 18:49:05360
361 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool);
362};
363
[email protected]a937a06d2009-08-19 21:19:24364} // namespace
365
[email protected]7fc5b09a2010-02-27 00:07:38366REGISTER_SOCKET_PARAMS_FOR_POOL(TestClientSocketPool, TestSocketParams);
[email protected]a937a06d2009-08-19 21:19:24367
368namespace {
369
[email protected]5fc08e32009-07-15 17:09:57370void MockClientSocketFactory::SignalJobs() {
371 for (std::vector<TestConnectJob*>::iterator it = waiting_jobs_.begin();
372 it != waiting_jobs_.end(); ++it) {
373 (*it)->Signal();
374 }
375 waiting_jobs_.clear();
376}
377
[email protected]974ebd62009-08-03 23:14:34378class TestConnectJobDelegate : public ConnectJob::Delegate {
379 public:
380 TestConnectJobDelegate()
381 : have_result_(false), waiting_for_result_(false), result_(OK) {}
382 virtual ~TestConnectJobDelegate() {}
383
384 virtual void OnConnectJobComplete(int result, ConnectJob* job) {
385 result_ = result;
[email protected]6e713f02009-08-06 02:56:40386 scoped_ptr<ClientSocket> socket(job->ReleaseSocket());
[email protected]9b6fee12009-09-29 18:13:07387 // socket.get() should be NULL iff result != OK
388 EXPECT_EQ(socket.get() == NULL, result != OK);
[email protected]974ebd62009-08-03 23:14:34389 delete job;
390 have_result_ = true;
391 if (waiting_for_result_)
392 MessageLoop::current()->Quit();
393 }
394
395 int WaitForResult() {
396 DCHECK(!waiting_for_result_);
397 while (!have_result_) {
398 waiting_for_result_ = true;
399 MessageLoop::current()->Run();
400 waiting_for_result_ = false;
401 }
402 have_result_ = false; // auto-reset for next callback
403 return result_;
404 }
405
406 private:
407 bool have_result_;
408 bool waiting_for_result_;
409 int result_;
410};
411
[email protected]75439d3b2009-07-23 22:11:17412class ClientSocketPoolBaseTest : public ClientSocketPoolTest {
[email protected]f6d1d6eb2009-06-24 20:16:09413 protected:
[email protected]b89f7e42010-05-20 20:37:00414 ClientSocketPoolBaseTest()
415 : histograms_(new ClientSocketPoolHistograms("ClientSocketPoolTest")) {}
[email protected]c9d6a1d2009-07-14 16:15:20416
[email protected]211d21722009-07-22 15:48:53417 void CreatePool(int max_sockets, int max_sockets_per_group) {
[email protected]9bf28db2009-08-29 01:35:16418 CreatePoolWithIdleTimeouts(
419 max_sockets,
420 max_sockets_per_group,
421 base::TimeDelta::FromSeconds(kUnusedIdleSocketTimeout),
422 base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout));
423 }
424
425 void CreatePoolWithIdleTimeouts(
426 int max_sockets, int max_sockets_per_group,
427 base::TimeDelta unused_idle_socket_timeout,
428 base::TimeDelta used_idle_socket_timeout) {
[email protected]c9d6a1d2009-07-14 16:15:20429 DCHECK(!pool_.get());
[email protected]17a0c6c2009-08-04 00:07:04430 connect_job_factory_ = new TestConnectJobFactory(&client_socket_factory_);
[email protected]211d21722009-07-22 15:48:53431 pool_ = new TestClientSocketPool(max_sockets,
432 max_sockets_per_group,
[email protected]b89f7e42010-05-20 20:37:00433 histograms_,
[email protected]9bf28db2009-08-29 01:35:16434 unused_idle_socket_timeout,
435 used_idle_socket_timeout,
[email protected]c9d6a1d2009-07-14 16:15:20436 connect_job_factory_);
437 }
[email protected]f6d1d6eb2009-06-24 20:16:09438
[email protected]ac790b42009-12-02 04:31:31439 int StartRequest(const std::string& group_name,
440 net::RequestPriority priority) {
[email protected]7fc5b09a2010-02-27 00:07:38441 return StartRequestUsingPool<TestClientSocketPool, TestSocketParams>(
[email protected]a796bcec2010-03-22 17:17:26442 pool_, group_name, priority, NULL);
[email protected]f6d1d6eb2009-06-24 20:16:09443 }
444
445 virtual void TearDown() {
[email protected]6b175382009-10-13 06:47:47446 // We post all of our delayed tasks with a 2ms delay. I.e. they don't
447 // actually become pending until 2ms after they have been created. In order
448 // to flush all tasks, we need to wait so that we know there are no
449 // soon-to-be-pending tasks waiting.
450 PlatformThread::Sleep(10);
451 MessageLoop::current()->RunAllPending();
452
[email protected]211d21722009-07-22 15:48:53453 // Need to delete |pool_| before we turn late binding back off. We also need
454 // to delete |requests_| because the pool is reference counted and requests
455 // keep reference to it.
456 // TODO(willchan): Remove this part when late binding becomes the default.
[email protected]5fc08e32009-07-15 17:09:57457 pool_ = NULL;
[email protected]211d21722009-07-22 15:48:53458 requests_.reset();
459
[email protected]75439d3b2009-07-23 22:11:17460 ClientSocketPoolTest::TearDown();
[email protected]f6d1d6eb2009-06-24 20:16:09461 }
462
[email protected]f6d1d6eb2009-06-24 20:16:09463 MockClientSocketFactory client_socket_factory_;
[email protected]17a0c6c2009-08-04 00:07:04464 TestConnectJobFactory* connect_job_factory_;
[email protected]c9d6a1d2009-07-14 16:15:20465 scoped_refptr<TestClientSocketPool> pool_;
[email protected]b89f7e42010-05-20 20:37:00466 scoped_refptr<ClientSocketPoolHistograms> histograms_;
[email protected]f6d1d6eb2009-06-24 20:16:09467};
468
[email protected]a937a06d2009-08-19 21:19:24469// Helper function which explicitly specifies the template parameters, since
470// the compiler will infer (in this case, incorrectly) that NULL is of type int.
471int InitHandle(ClientSocketHandle* handle,
472 const std::string& group_name,
[email protected]ac790b42009-12-02 04:31:31473 net::RequestPriority priority,
[email protected]a937a06d2009-08-19 21:19:24474 CompletionCallback* callback,
[email protected]a796bcec2010-03-22 17:17:26475 const scoped_refptr<TestClientSocketPool>& pool,
[email protected]9e743cd2010-03-16 07:03:53476 const BoundNetLog& net_log) {
[email protected]7fc5b09a2010-02-27 00:07:38477 return handle->Init<TestSocketParams, TestClientSocketPool>(
[email protected]9e743cd2010-03-16 07:03:53478 group_name, NULL, priority, callback, pool, net_log);
[email protected]a937a06d2009-08-19 21:19:24479}
480
[email protected]974ebd62009-08-03 23:14:34481// Even though a timeout is specified, it doesn't time out on a synchronous
482// completion.
483TEST_F(ClientSocketPoolBaseTest, ConnectJob_NoTimeoutOnSynchronousCompletion) {
484 TestConnectJobDelegate delegate;
[email protected]a512f5982009-08-18 16:01:06485 ClientSocketHandle ignored;
[email protected]d80a4322009-08-14 07:07:49486 TestClientSocketPoolBase::Request request(
[email protected]5a1d7ca2010-04-28 20:12:27487 &ignored, NULL, kDefaultPriority, NULL, BoundNetLog());
[email protected]974ebd62009-08-03 23:14:34488 scoped_ptr<TestConnectJob> job(
489 new TestConnectJob(TestConnectJob::kMockJob,
[email protected]ec08bb22009-08-12 00:25:12490 "a",
[email protected]974ebd62009-08-03 23:14:34491 request,
492 base::TimeDelta::FromMicroseconds(1),
493 &delegate,
[email protected]fd7b7c92009-08-20 19:38:30494 &client_socket_factory_,
[email protected]06650c52010-06-03 00:49:17495 NULL));
[email protected]974ebd62009-08-03 23:14:34496 EXPECT_EQ(OK, job->Connect());
497}
498
499TEST_F(ClientSocketPoolBaseTest, ConnectJob_TimedOut) {
500 TestConnectJobDelegate delegate;
[email protected]a512f5982009-08-18 16:01:06501 ClientSocketHandle ignored;
[email protected]06650c52010-06-03 00:49:17502 CapturingNetLog log(CapturingNetLog::kUnbounded);
[email protected]9e743cd2010-03-16 07:03:53503
[email protected]d80a4322009-08-14 07:07:49504 TestClientSocketPoolBase::Request request(
[email protected]5a1d7ca2010-04-28 20:12:27505 &ignored, NULL, kDefaultPriority, NULL, BoundNetLog());
[email protected]974ebd62009-08-03 23:14:34506 // Deleted by TestConnectJobDelegate.
507 TestConnectJob* job =
508 new TestConnectJob(TestConnectJob::kMockPendingJob,
[email protected]ec08bb22009-08-12 00:25:12509 "a",
[email protected]974ebd62009-08-03 23:14:34510 request,
511 base::TimeDelta::FromMicroseconds(1),
512 &delegate,
[email protected]fd7b7c92009-08-20 19:38:30513 &client_socket_factory_,
[email protected]06650c52010-06-03 00:49:17514 &log);
[email protected]974ebd62009-08-03 23:14:34515 ASSERT_EQ(ERR_IO_PENDING, job->Connect());
516 PlatformThread::Sleep(1);
517 EXPECT_EQ(ERR_TIMED_OUT, delegate.WaitForResult());
[email protected]fd7b7c92009-08-20 19:38:30518
[email protected]06650c52010-06-03 00:49:17519 EXPECT_EQ(6u, log.entries().size());
[email protected]e9002a92010-01-29 07:10:46520 EXPECT_TRUE(LogContainsBeginEvent(
[email protected]9e743cd2010-03-16 07:03:53521 log.entries(), 0, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB));
[email protected]06650c52010-06-03 00:49:17522 EXPECT_TRUE(LogContainsBeginEvent(
523 log.entries(), 1, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT));
[email protected]e9002a92010-01-29 07:10:46524 EXPECT_TRUE(LogContainsEvent(
[email protected]06650c52010-06-03 00:49:17525 log.entries(), 2, NetLog::TYPE_CONNECT_JOB_SET_SOCKET,
526 NetLog::PHASE_NONE));
527 EXPECT_TRUE(LogContainsEvent(
528 log.entries(), 3, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_TIMED_OUT,
[email protected]9e743cd2010-03-16 07:03:53529 NetLog::PHASE_NONE));
[email protected]e9002a92010-01-29 07:10:46530 EXPECT_TRUE(LogContainsEndEvent(
[email protected]06650c52010-06-03 00:49:17531 log.entries(), 4, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT));
532 EXPECT_TRUE(LogContainsEndEvent(
533 log.entries(), 5, NetLog::TYPE_SOCKET_POOL_CONNECT_JOB));
[email protected]974ebd62009-08-03 23:14:34534}
535
[email protected]5fc08e32009-07-15 17:09:57536TEST_F(ClientSocketPoolBaseTest, BasicSynchronous) {
[email protected]211d21722009-07-22 15:48:53537 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:20538
[email protected]f6d1d6eb2009-06-24 20:16:09539 TestCompletionCallback callback;
[email protected]a512f5982009-08-18 16:01:06540 ClientSocketHandle handle;
[email protected]9e743cd2010-03-16 07:03:53541 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
542
[email protected]a796bcec2010-03-22 17:17:26543 EXPECT_EQ(OK, InitHandle(&handle, "a", kDefaultPriority, &callback, pool_,
544 log.bound()));
[email protected]f6d1d6eb2009-06-24 20:16:09545 EXPECT_TRUE(handle.is_initialized());
546 EXPECT_TRUE(handle.socket());
[email protected]f6d1d6eb2009-06-24 20:16:09547 handle.Reset();
[email protected]fd7b7c92009-08-20 19:38:30548
[email protected]06650c52010-06-03 00:49:17549 EXPECT_EQ(4u, log.entries().size());
[email protected]e9002a92010-01-29 07:10:46550 EXPECT_TRUE(LogContainsBeginEvent(
[email protected]9e743cd2010-03-16 07:03:53551 log.entries(), 0, NetLog::TYPE_SOCKET_POOL));
[email protected]9e743cd2010-03-16 07:03:53552 EXPECT_TRUE(LogContainsEvent(
[email protected]06650c52010-06-03 00:49:17553 log.entries(), 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
554 NetLog::PHASE_NONE));
555 EXPECT_TRUE(LogContainsEvent(
556 log.entries(), 2, NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET,
[email protected]9e743cd2010-03-16 07:03:53557 NetLog::PHASE_NONE));
558 EXPECT_TRUE(LogContainsEndEvent(
[email protected]06650c52010-06-03 00:49:17559 log.entries(), 3, NetLog::TYPE_SOCKET_POOL));
[email protected]f6d1d6eb2009-06-24 20:16:09560}
561
[email protected]ab838892009-06-30 18:49:05562TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) {
[email protected]211d21722009-07-22 15:48:53563 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:20564
[email protected]ab838892009-06-30 18:49:05565 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
[email protected]9e743cd2010-03-16 07:03:53566 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
567
[email protected]a512f5982009-08-18 16:01:06568 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]3ae82302009-06-26 06:01:21569 EXPECT_EQ(ERR_CONNECTION_FAILED,
[email protected]a796bcec2010-03-22 17:17:26570 InitHandle(req.handle(), "a", kDefaultPriority, &req, pool_,
571 log.bound()));
[email protected]fd7b7c92009-08-20 19:38:30572
[email protected]06650c52010-06-03 00:49:17573 EXPECT_EQ(3u, log.entries().size());
[email protected]5a1d7ca2010-04-28 20:12:27574 EXPECT_TRUE(LogContainsBeginEvent(
575 log.entries(), 0, NetLog::TYPE_SOCKET_POOL));
[email protected]06650c52010-06-03 00:49:17576 EXPECT_TRUE(LogContainsEvent(
577 log.entries(), 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
578 NetLog::PHASE_NONE));
[email protected]a2006ece2010-04-23 16:44:02579 EXPECT_TRUE(LogContainsEndEvent(
[email protected]06650c52010-06-03 00:49:17580 log.entries(), 2, NetLog::TYPE_SOCKET_POOL));
[email protected]f6d1d6eb2009-06-24 20:16:09581}
582
[email protected]211d21722009-07-22 15:48:53583TEST_F(ClientSocketPoolBaseTest, TotalLimit) {
584 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
585
[email protected]9e743cd2010-03-16 07:03:53586 // TODO(eroman): Check that the NetLog contains this event.
[email protected]fd7b7c92009-08-20 19:38:30587
[email protected]211d21722009-07-22 15:48:53588 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
589 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
590 EXPECT_EQ(OK, StartRequest("c", kDefaultPriority));
591 EXPECT_EQ(OK, StartRequest("d", kDefaultPriority));
592
593 EXPECT_EQ(static_cast<int>(requests_.size()),
594 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17595 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53596
597 EXPECT_EQ(ERR_IO_PENDING, StartRequest("e", kDefaultPriority));
598 EXPECT_EQ(ERR_IO_PENDING, StartRequest("f", kDefaultPriority));
599 EXPECT_EQ(ERR_IO_PENDING, StartRequest("g", kDefaultPriority));
600
[email protected]89628072010-06-08 05:50:58601 ReleaseAllConnections(NO_KEEP_ALIVE);
[email protected]211d21722009-07-22 15:48:53602
603 EXPECT_EQ(static_cast<int>(requests_.size()),
604 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17605 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53606
607 EXPECT_EQ(1, GetOrderOfRequest(1));
608 EXPECT_EQ(2, GetOrderOfRequest(2));
609 EXPECT_EQ(3, GetOrderOfRequest(3));
610 EXPECT_EQ(4, GetOrderOfRequest(4));
611 EXPECT_EQ(5, GetOrderOfRequest(5));
612 EXPECT_EQ(6, GetOrderOfRequest(6));
613 EXPECT_EQ(7, GetOrderOfRequest(7));
[email protected]75439d3b2009-07-23 22:11:17614
615 // Make sure we test order of all requests made.
616 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8));
[email protected]211d21722009-07-22 15:48:53617}
618
619TEST_F(ClientSocketPoolBaseTest, TotalLimitReachedNewGroup) {
620 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
621
[email protected]9e743cd2010-03-16 07:03:53622 // TODO(eroman): Check that the NetLog contains this event.
[email protected]fd7b7c92009-08-20 19:38:30623
[email protected]211d21722009-07-22 15:48:53624 // Reach all limits: max total sockets, and max sockets per group.
625 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
626 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
627 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
628 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
629
630 EXPECT_EQ(static_cast<int>(requests_.size()),
631 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17632 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53633
634 // Now create a new group and verify that we don't starve it.
635 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kDefaultPriority));
636
[email protected]89628072010-06-08 05:50:58637 ReleaseAllConnections(NO_KEEP_ALIVE);
[email protected]211d21722009-07-22 15:48:53638
639 EXPECT_EQ(static_cast<int>(requests_.size()),
640 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17641 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53642
643 EXPECT_EQ(1, GetOrderOfRequest(1));
644 EXPECT_EQ(2, GetOrderOfRequest(2));
645 EXPECT_EQ(3, GetOrderOfRequest(3));
646 EXPECT_EQ(4, GetOrderOfRequest(4));
647 EXPECT_EQ(5, GetOrderOfRequest(5));
[email protected]75439d3b2009-07-23 22:11:17648
649 // Make sure we test order of all requests made.
650 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(6));
[email protected]211d21722009-07-22 15:48:53651}
652
653TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsPriority) {
654 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
655
[email protected]ac790b42009-12-02 04:31:31656 EXPECT_EQ(OK, StartRequest("b", LOWEST));
657 EXPECT_EQ(OK, StartRequest("a", MEDIUM));
658 EXPECT_EQ(OK, StartRequest("b", HIGHEST));
659 EXPECT_EQ(OK, StartRequest("a", LOWEST));
[email protected]211d21722009-07-22 15:48:53660
661 EXPECT_EQ(static_cast<int>(requests_.size()),
662 client_socket_factory_.allocation_count());
663
[email protected]ac790b42009-12-02 04:31:31664 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", LOWEST));
665 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
666 EXPECT_EQ(ERR_IO_PENDING, StartRequest("b", HIGHEST));
[email protected]211d21722009-07-22 15:48:53667
[email protected]89628072010-06-08 05:50:58668 ReleaseAllConnections(NO_KEEP_ALIVE);
[email protected]211d21722009-07-22 15:48:53669
[email protected]75439d3b2009-07-23 22:11:17670 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53671
672 // First 4 requests don't have to wait, and finish in order.
673 EXPECT_EQ(1, GetOrderOfRequest(1));
674 EXPECT_EQ(2, GetOrderOfRequest(2));
675 EXPECT_EQ(3, GetOrderOfRequest(3));
676 EXPECT_EQ(4, GetOrderOfRequest(4));
677
[email protected]ac790b42009-12-02 04:31:31678 // Request ("b", HIGHEST) has the highest priority, then ("a", MEDIUM),
679 // and then ("c", LOWEST).
[email protected]211d21722009-07-22 15:48:53680 EXPECT_EQ(7, GetOrderOfRequest(5));
681 EXPECT_EQ(6, GetOrderOfRequest(6));
682 EXPECT_EQ(5, GetOrderOfRequest(7));
[email protected]75439d3b2009-07-23 22:11:17683
684 // Make sure we test order of all requests made.
685 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8));
[email protected]211d21722009-07-22 15:48:53686}
687
688TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsGroupLimit) {
689 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
690
[email protected]ac790b42009-12-02 04:31:31691 EXPECT_EQ(OK, StartRequest("a", LOWEST));
692 EXPECT_EQ(OK, StartRequest("a", LOW));
693 EXPECT_EQ(OK, StartRequest("b", HIGHEST));
694 EXPECT_EQ(OK, StartRequest("b", MEDIUM));
[email protected]211d21722009-07-22 15:48:53695
696 EXPECT_EQ(static_cast<int>(requests_.size()),
697 client_socket_factory_.allocation_count());
698
[email protected]ac790b42009-12-02 04:31:31699 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", MEDIUM));
700 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW));
701 EXPECT_EQ(ERR_IO_PENDING, StartRequest("b", HIGHEST));
[email protected]211d21722009-07-22 15:48:53702
[email protected]89628072010-06-08 05:50:58703 ReleaseAllConnections(NO_KEEP_ALIVE);
[email protected]211d21722009-07-22 15:48:53704
[email protected]89628072010-06-08 05:50:58705 EXPECT_EQ(static_cast<int>(requests_.size()),
[email protected]211d21722009-07-22 15:48:53706 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17707 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53708
709 // First 4 requests don't have to wait, and finish in order.
710 EXPECT_EQ(1, GetOrderOfRequest(1));
711 EXPECT_EQ(2, GetOrderOfRequest(2));
712 EXPECT_EQ(3, GetOrderOfRequest(3));
713 EXPECT_EQ(4, GetOrderOfRequest(4));
714
715 // Request ("b", 7) has the highest priority, but we can't make new socket for
716 // group "b", because it has reached the per-group limit. Then we make
717 // socket for ("c", 6), because it has higher priority than ("a", 4),
718 // and we still can't make a socket for group "b".
719 EXPECT_EQ(5, GetOrderOfRequest(5));
720 EXPECT_EQ(6, GetOrderOfRequest(6));
721 EXPECT_EQ(7, GetOrderOfRequest(7));
[email protected]75439d3b2009-07-23 22:11:17722
723 // Make sure we test order of all requests made.
724 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8));
[email protected]211d21722009-07-22 15:48:53725}
726
727// Make sure that we count connecting sockets against the total limit.
728TEST_F(ClientSocketPoolBaseTest, TotalLimitCountsConnectingSockets) {
729 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
730
731 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
732 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
733 EXPECT_EQ(OK, StartRequest("c", kDefaultPriority));
734
735 // Create one asynchronous request.
736 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
737 EXPECT_EQ(ERR_IO_PENDING, StartRequest("d", kDefaultPriority));
738
[email protected]6b175382009-10-13 06:47:47739 // We post all of our delayed tasks with a 2ms delay. I.e. they don't
740 // actually become pending until 2ms after they have been created. In order
741 // to flush all tasks, we need to wait so that we know there are no
742 // soon-to-be-pending tasks waiting.
743 PlatformThread::Sleep(10);
744 MessageLoop::current()->RunAllPending();
745
[email protected]211d21722009-07-22 15:48:53746 // The next synchronous request should wait for its turn.
747 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
748 EXPECT_EQ(ERR_IO_PENDING, StartRequest("e", kDefaultPriority));
749
[email protected]89628072010-06-08 05:50:58750 ReleaseAllConnections(NO_KEEP_ALIVE);
[email protected]211d21722009-07-22 15:48:53751
752 EXPECT_EQ(static_cast<int>(requests_.size()),
753 client_socket_factory_.allocation_count());
754
755 EXPECT_EQ(1, GetOrderOfRequest(1));
756 EXPECT_EQ(2, GetOrderOfRequest(2));
757 EXPECT_EQ(3, GetOrderOfRequest(3));
758 EXPECT_EQ(4, GetOrderOfRequest(4));
[email protected]75439d3b2009-07-23 22:11:17759 EXPECT_EQ(5, GetOrderOfRequest(5));
760
761 // Make sure we test order of all requests made.
762 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(6));
[email protected]211d21722009-07-22 15:48:53763}
764
765// Inside ClientSocketPoolBase we have a may_have_stalled_group flag,
766// which tells it to use more expensive, but accurate, group selection
767// algorithm. Make sure it doesn't get stuck in the "on" state.
768TEST_F(ClientSocketPoolBaseTest, MayHaveStalledGroupReset) {
769 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
770
771 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
772
773 // Reach group socket limit.
774 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
775 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
776 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
777
778 // Reach total limit, but don't request more sockets.
779 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
780 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
781 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
782
783 // Request one more socket while we are at the maximum sockets limit.
784 // This should flip the may_have_stalled_group flag.
785 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kDefaultPriority));
786 EXPECT_TRUE(pool_->base()->may_have_stalled_group());
787
788 // After releasing first connection for "a", we're still at the
789 // maximum sockets limit, but every group's pending queue is empty,
790 // so we reset the flag.
[email protected]89628072010-06-08 05:50:58791 EXPECT_TRUE(ReleaseOneConnection(NO_KEEP_ALIVE));
[email protected]211d21722009-07-22 15:48:53792 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
793
794 // Requesting additional socket while at the total limit should
795 // flip the flag back to "on".
796 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kDefaultPriority));
797 EXPECT_TRUE(pool_->base()->may_have_stalled_group());
798
799 // We'll request one more socket to verify that we don't reset the flag
800 // too eagerly.
801 EXPECT_EQ(ERR_IO_PENDING, StartRequest("d", kDefaultPriority));
802 EXPECT_TRUE(pool_->base()->may_have_stalled_group());
803
804 // We're at the maximum socket limit, and still have one request pending
805 // for "d". Flag should be "on".
[email protected]89628072010-06-08 05:50:58806 EXPECT_TRUE(ReleaseOneConnection(NO_KEEP_ALIVE));
[email protected]211d21722009-07-22 15:48:53807 EXPECT_TRUE(pool_->base()->may_have_stalled_group());
808
809 // Now every group's pending queue should be empty again.
[email protected]89628072010-06-08 05:50:58810 EXPECT_TRUE(ReleaseOneConnection(NO_KEEP_ALIVE));
[email protected]211d21722009-07-22 15:48:53811 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
812
[email protected]89628072010-06-08 05:50:58813 ReleaseAllConnections(NO_KEEP_ALIVE);
[email protected]211d21722009-07-22 15:48:53814 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
815}
816
[email protected]6427fe22010-04-16 22:27:41817TEST_F(ClientSocketPoolBaseTest, CorrectlyCountStalledGroups) {
818 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets);
819 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
820
821 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
822 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
823 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
824 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
825
826 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
827
828 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
829
830 EXPECT_EQ(ERR_IO_PENDING, StartRequest("b", kDefaultPriority));
831 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kDefaultPriority));
832
833 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
834
835 EXPECT_TRUE(ReleaseOneConnection(KEEP_ALIVE));
836 EXPECT_EQ(kDefaultMaxSockets + 1, client_socket_factory_.allocation_count());
837 EXPECT_TRUE(ReleaseOneConnection(KEEP_ALIVE));
838 EXPECT_EQ(kDefaultMaxSockets + 2, client_socket_factory_.allocation_count());
839 EXPECT_TRUE(ReleaseOneConnection(KEEP_ALIVE));
840 EXPECT_TRUE(ReleaseOneConnection(KEEP_ALIVE));
841 EXPECT_EQ(kDefaultMaxSockets + 2, client_socket_factory_.allocation_count());
842}
843
[email protected]d7027bb2010-05-10 18:58:54844TEST_F(ClientSocketPoolBaseTest, StallAndThenCancelAndTriggerAvailableSocket) {
845 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets);
846 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
847
848 ClientSocketHandle handle;
849 TestCompletionCallback callback;
850 EXPECT_EQ(ERR_IO_PENDING,
851 InitHandle(&handle, "a", kDefaultPriority, &callback, pool_,
852 BoundNetLog()));
853
854 ClientSocketHandle handles[4];
855 for (size_t i = 0; i < arraysize(handles); ++i) {
856 TestCompletionCallback callback;
857 EXPECT_EQ(ERR_IO_PENDING,
858 InitHandle(&handles[i], "b", kDefaultPriority, &callback, pool_,
859 BoundNetLog()));
860 }
861
862 // One will be stalled, cancel all the handles now.
863 // This should hit the OnAvailableSocketSlot() code where we previously had
864 // stalled groups, but no longer have any.
865 for (size_t i = 0; i < arraysize(handles); ++i)
866 handles[i].Reset();
867}
868
[email protected]89628072010-06-08 05:50:58869TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimit) {
870 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
871 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
872
873 for (int i = 0; i < kDefaultMaxSockets; ++i) {
874 ClientSocketHandle handle;
875 TestCompletionCallback callback;
876 EXPECT_EQ(OK,
877 InitHandle(&handle, IntToString(i), kDefaultPriority, &callback,
878 pool_, BoundNetLog()));
879 }
880
881 // Stall a group
882 ClientSocketHandle handle;
883 TestCompletionCallback callback;
884 EXPECT_EQ(ERR_IO_PENDING,
885 InitHandle(&handle, "foo", kDefaultPriority, &callback, pool_,
886 BoundNetLog()));
887
888 // Cancel the stalled request.
889 handle.Reset();
890
891 // Flush all the DoReleaseSocket tasks.
892 MessageLoop::current()->RunAllPending();
893
894 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
895 EXPECT_EQ(kDefaultMaxSockets, pool_->IdleSocketCount());
896
897 for (int i = 0; i < kDefaultMaxSockets; ++i) {
898 ClientSocketHandle handle;
899 TestCompletionCallback callback;
900 EXPECT_EQ(OK,
901 InitHandle(&handle, StringPrintf("Take 2: %d", i),
902 kDefaultPriority, &callback, pool_, BoundNetLog()));
903 }
904
905 EXPECT_EQ(2 * kDefaultMaxSockets, client_socket_factory_.allocation_count());
906 EXPECT_EQ(0, pool_->IdleSocketCount());
907
908 // Before the next round of DoReleaseSocket tasks run, we will hit the
909 // socket limit.
910
911 EXPECT_EQ(ERR_IO_PENDING,
912 InitHandle(&handle, "foo", kDefaultPriority, &callback, pool_,
913 BoundNetLog()));
914
915 // But if we wait for it, the released idle sockets will be closed in
916 // preference of the waiting request.
917
918 EXPECT_EQ(OK, callback.WaitForResult());
919}
920
921// Regression test for http://crbug.com/40952.
922TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimitDeleteGroup) {
923 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
924 pool_->EnableBackupJobs();
925 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
926
927 for (int i = 0; i < kDefaultMaxSockets; ++i) {
928 ClientSocketHandle handle;
929 TestCompletionCallback callback;
930 EXPECT_EQ(OK,
931 InitHandle(&handle, IntToString(i), kDefaultPriority, &callback,
932 pool_, BoundNetLog()));
933 }
934
935 // Flush all the DoReleaseSocket tasks.
936 MessageLoop::current()->RunAllPending();
937
938 // Stall a group. Set a pending job so it'll trigger a backup job if we don't
939 // reuse a socket.
940 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
941 ClientSocketHandle handle;
942 TestCompletionCallback callback;
943
944 // "0" is special here, since it should be the first entry in the sorted map,
945 // which is the one which we would close an idle socket for. We shouldn't
946 // close an idle socket though, since we should reuse the idle socket.
947 EXPECT_EQ(
948 OK,
949 InitHandle(
950 &handle, "0", kDefaultPriority, &callback, pool_, BoundNetLog()));
951
952 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
953 EXPECT_EQ(kDefaultMaxSockets - 1, pool_->IdleSocketCount());
954}
955
[email protected]ab838892009-06-30 18:49:05956TEST_F(ClientSocketPoolBaseTest, PendingRequests) {
[email protected]211d21722009-07-22 15:48:53957 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09958
[email protected]c9d6a1d2009-07-14 16:15:20959 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
960 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
[email protected]ac790b42009-12-02 04:31:31961 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
962 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
963 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST));
964 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW));
965 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
[email protected]f6d1d6eb2009-06-24 20:16:09966
[email protected]c9d6a1d2009-07-14 16:15:20967 ReleaseAllConnections(KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09968
[email protected]c9d6a1d2009-07-14 16:15:20969 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
970 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17971 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup, completion_count_);
[email protected]f6d1d6eb2009-06-24 20:16:09972
[email protected]c9d6a1d2009-07-14 16:15:20973 EXPECT_EQ(1, GetOrderOfRequest(1));
974 EXPECT_EQ(2, GetOrderOfRequest(2));
975 EXPECT_EQ(6, GetOrderOfRequest(3));
976 EXPECT_EQ(4, GetOrderOfRequest(4));
977 EXPECT_EQ(3, GetOrderOfRequest(5));
978 EXPECT_EQ(5, GetOrderOfRequest(6));
979 EXPECT_EQ(7, GetOrderOfRequest(7));
[email protected]75439d3b2009-07-23 22:11:17980
981 // Make sure we test order of all requests made.
982 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8));
[email protected]f6d1d6eb2009-06-24 20:16:09983}
984
[email protected]ab838892009-06-30 18:49:05985TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) {
[email protected]211d21722009-07-22 15:48:53986 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09987
[email protected]c9d6a1d2009-07-14 16:15:20988 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
989 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
[email protected]ac790b42009-12-02 04:31:31990 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
991 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
992 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST));
993 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW));
994 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
[email protected]f6d1d6eb2009-06-24 20:16:09995
[email protected]c9d6a1d2009-07-14 16:15:20996 ReleaseAllConnections(NO_KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09997
[email protected]c9d6a1d2009-07-14 16:15:20998 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i)
999 EXPECT_EQ(OK, requests_[i]->WaitForResult());
1000
1001 EXPECT_EQ(static_cast<int>(requests_.size()),
1002 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:171003 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup, completion_count_);
[email protected]f6d1d6eb2009-06-24 20:16:091004}
1005
1006// This test will start up a RequestSocket() and then immediately Cancel() it.
[email protected]ab838892009-06-30 18:49:051007// The pending connect job will be cancelled and should not call back into
1008// ClientSocketPoolBase.
1009TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) {
[email protected]211d21722009-07-22 15:48:531010 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:201011
[email protected]ab838892009-06-30 18:49:051012 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:061013 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]ab838892009-06-30 18:49:051014 EXPECT_EQ(ERR_IO_PENDING,
[email protected]5a1d7ca2010-04-28 20:12:271015 InitHandle(req.handle(), "a", kDefaultPriority, &req, pool_,
1016 BoundNetLog()));
[email protected]a6c59f62009-07-29 16:33:331017 req.handle()->Reset();
[email protected]f6d1d6eb2009-06-24 20:16:091018}
1019
[email protected]ab838892009-06-30 18:49:051020TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) {
[email protected]211d21722009-07-22 15:48:531021 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:201022
[email protected]ab838892009-06-30 18:49:051023 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:061024 ClientSocketHandle handle;
[email protected]f6d1d6eb2009-06-24 20:16:091025 TestCompletionCallback callback;
[email protected]a512f5982009-08-18 16:01:061026 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]f6d1d6eb2009-06-24 20:16:091027
[email protected]ab838892009-06-30 18:49:051028 EXPECT_EQ(ERR_IO_PENDING,
[email protected]5a1d7ca2010-04-28 20:12:271029 InitHandle(&handle, "a", kDefaultPriority, &callback, pool_,
1030 BoundNetLog()));
[email protected]f6d1d6eb2009-06-24 20:16:091031
1032 handle.Reset();
1033
1034 TestCompletionCallback callback2;
[email protected]a796bcec2010-03-22 17:17:261035 EXPECT_EQ(ERR_IO_PENDING, InitHandle(&handle, "a", kDefaultPriority,
[email protected]5a1d7ca2010-04-28 20:12:271036 &callback2, pool_, BoundNetLog()));
[email protected]f6d1d6eb2009-06-24 20:16:091037
1038 EXPECT_EQ(OK, callback2.WaitForResult());
1039 EXPECT_FALSE(callback.have_result());
1040
1041 handle.Reset();
1042}
1043
[email protected]ab838892009-06-30 18:49:051044TEST_F(ClientSocketPoolBaseTest, CancelRequest) {
[email protected]211d21722009-07-22 15:48:531045 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:091046
[email protected]c9d6a1d2009-07-14 16:15:201047 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
1048 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
[email protected]ac790b42009-12-02 04:31:311049 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
1050 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
1051 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST));
1052 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW));
1053 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
[email protected]f6d1d6eb2009-06-24 20:16:091054
1055 // Cancel a request.
[email protected]c9d6a1d2009-07-14 16:15:201056 size_t index_to_cancel = kDefaultMaxSocketsPerGroup + 2;
[email protected]a6c59f62009-07-29 16:33:331057 EXPECT_FALSE(requests_[index_to_cancel]->handle()->is_initialized());
1058 requests_[index_to_cancel]->handle()->Reset();
[email protected]f6d1d6eb2009-06-24 20:16:091059
[email protected]c9d6a1d2009-07-14 16:15:201060 ReleaseAllConnections(KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:091061
[email protected]c9d6a1d2009-07-14 16:15:201062 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
1063 client_socket_factory_.allocation_count());
1064 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup - 1,
[email protected]75439d3b2009-07-23 22:11:171065 completion_count_);
[email protected]f6d1d6eb2009-06-24 20:16:091066
[email protected]c9d6a1d2009-07-14 16:15:201067 EXPECT_EQ(1, GetOrderOfRequest(1));
1068 EXPECT_EQ(2, GetOrderOfRequest(2));
1069 EXPECT_EQ(5, GetOrderOfRequest(3));
1070 EXPECT_EQ(3, GetOrderOfRequest(4));
1071 EXPECT_EQ(kRequestNotFound, GetOrderOfRequest(5)); // Canceled request.
1072 EXPECT_EQ(4, GetOrderOfRequest(6));
1073 EXPECT_EQ(6, GetOrderOfRequest(7));
[email protected]75439d3b2009-07-23 22:11:171074
1075 // Make sure we test order of all requests made.
1076 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8));
[email protected]f6d1d6eb2009-06-24 20:16:091077}
1078
1079class RequestSocketCallback : public CallbackRunner< Tuple1<int> > {
1080 public:
[email protected]2ab05b52009-07-01 23:57:581081 RequestSocketCallback(ClientSocketHandle* handle,
[email protected]a937a06d2009-08-19 21:19:241082 TestClientSocketPool* pool,
[email protected]2ab05b52009-07-01 23:57:581083 TestConnectJobFactory* test_connect_job_factory,
1084 TestConnectJob::JobType next_job_type)
[email protected]f6d1d6eb2009-06-24 20:16:091085 : handle_(handle),
[email protected]a512f5982009-08-18 16:01:061086 pool_(pool),
[email protected]2ab05b52009-07-01 23:57:581087 within_callback_(false),
1088 test_connect_job_factory_(test_connect_job_factory),
1089 next_job_type_(next_job_type) {}
[email protected]f6d1d6eb2009-06-24 20:16:091090
1091 virtual void RunWithParams(const Tuple1<int>& params) {
1092 callback_.RunWithParams(params);
1093 ASSERT_EQ(OK, params.a);
1094
1095 if (!within_callback_) {
[email protected]2ab05b52009-07-01 23:57:581096 test_connect_job_factory_->set_job_type(next_job_type_);
[email protected]5edbf8d2010-01-13 18:44:111097
1098 // Don't allow reuse of the socket. Disconnect it and then release it and
1099 // run through the MessageLoop once to get it completely released.
1100 handle_->socket()->Disconnect();
[email protected]f6d1d6eb2009-06-24 20:16:091101 handle_->Reset();
[email protected]5edbf8d2010-01-13 18:44:111102 {
1103 MessageLoop::ScopedNestableTaskAllower nestable(
1104 MessageLoop::current());
1105 MessageLoop::current()->RunAllPending();
1106 }
[email protected]f6d1d6eb2009-06-24 20:16:091107 within_callback_ = true;
[email protected]6b175382009-10-13 06:47:471108 TestCompletionCallback next_job_callback;
[email protected]a796bcec2010-03-22 17:17:261109 int rv = InitHandle(handle_, "a", kDefaultPriority, &next_job_callback,
[email protected]5a1d7ca2010-04-28 20:12:271110 pool_, BoundNetLog());
[email protected]2ab05b52009-07-01 23:57:581111 switch (next_job_type_) {
1112 case TestConnectJob::kMockJob:
1113 EXPECT_EQ(OK, rv);
1114 break;
1115 case TestConnectJob::kMockPendingJob:
1116 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]6b175382009-10-13 06:47:471117
1118 // For pending jobs, wait for new socket to be created. This makes
1119 // sure there are no more pending operations nor any unclosed sockets
1120 // when the test finishes.
1121 // We need to give it a little bit of time to run, so that all the
1122 // operations that happen on timers (e.g. cleanup of idle
1123 // connections) can execute.
[email protected]5edbf8d2010-01-13 18:44:111124 {
1125 MessageLoop::ScopedNestableTaskAllower nestable(
1126 MessageLoop::current());
1127 PlatformThread::Sleep(10);
1128 EXPECT_EQ(OK, next_job_callback.WaitForResult());
1129 }
[email protected]2ab05b52009-07-01 23:57:581130 break;
1131 default:
1132 FAIL() << "Unexpected job type: " << next_job_type_;
1133 break;
1134 }
[email protected]f6d1d6eb2009-06-24 20:16:091135 }
1136 }
1137
1138 int WaitForResult() {
1139 return callback_.WaitForResult();
1140 }
1141
1142 private:
1143 ClientSocketHandle* const handle_;
[email protected]a937a06d2009-08-19 21:19:241144 const scoped_refptr<TestClientSocketPool> pool_;
[email protected]f6d1d6eb2009-06-24 20:16:091145 bool within_callback_;
[email protected]2ab05b52009-07-01 23:57:581146 TestConnectJobFactory* const test_connect_job_factory_;
1147 TestConnectJob::JobType next_job_type_;
[email protected]f6d1d6eb2009-06-24 20:16:091148 TestCompletionCallback callback_;
1149};
1150
[email protected]2ab05b52009-07-01 23:57:581151TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) {
[email protected]211d21722009-07-22 15:48:531152 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:201153
[email protected]0b7648c2009-07-06 20:14:011154 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:061155 ClientSocketHandle handle;
[email protected]2ab05b52009-07-01 23:57:581156 RequestSocketCallback callback(
[email protected]a512f5982009-08-18 16:01:061157 &handle, pool_.get(), connect_job_factory_,
1158 TestConnectJob::kMockPendingJob);
[email protected]5a1d7ca2010-04-28 20:12:271159 int rv = InitHandle(&handle, "a", kDefaultPriority, &callback, pool_,
1160 BoundNetLog());
[email protected]f6d1d6eb2009-06-24 20:16:091161 ASSERT_EQ(ERR_IO_PENDING, rv);
1162
1163 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ab05b52009-07-01 23:57:581164}
[email protected]f6d1d6eb2009-06-24 20:16:091165
[email protected]2ab05b52009-07-01 23:57:581166TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) {
[email protected]211d21722009-07-22 15:48:531167 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:201168
[email protected]0b7648c2009-07-06 20:14:011169 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:061170 ClientSocketHandle handle;
[email protected]2ab05b52009-07-01 23:57:581171 RequestSocketCallback callback(
[email protected]a512f5982009-08-18 16:01:061172 &handle, pool_.get(), connect_job_factory_, TestConnectJob::kMockJob);
[email protected]5a1d7ca2010-04-28 20:12:271173 int rv = InitHandle(&handle, "a", kDefaultPriority, &callback, pool_,
1174 BoundNetLog());
[email protected]2ab05b52009-07-01 23:57:581175 ASSERT_EQ(ERR_IO_PENDING, rv);
1176
1177 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]f6d1d6eb2009-06-24 20:16:091178}
1179
1180// Make sure that pending requests get serviced after active requests get
1181// cancelled.
[email protected]ab838892009-06-30 18:49:051182TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) {
[email protected]211d21722009-07-22 15:48:531183 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:201184
[email protected]0b7648c2009-07-06 20:14:011185 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:091186
[email protected]c9d6a1d2009-07-14 16:15:201187 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1188 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1189 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1190 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1191 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1192 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1193 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
[email protected]f6d1d6eb2009-06-24 20:16:091194
[email protected]c9d6a1d2009-07-14 16:15:201195 // Now, kDefaultMaxSocketsPerGroup requests should be active.
1196 // Let's cancel them.
1197 for (int i = 0; i < kDefaultMaxSocketsPerGroup; ++i) {
[email protected]a6c59f62009-07-29 16:33:331198 ASSERT_FALSE(requests_[i]->handle()->is_initialized());
1199 requests_[i]->handle()->Reset();
[email protected]f6d1d6eb2009-06-24 20:16:091200 }
1201
[email protected]f6d1d6eb2009-06-24 20:16:091202 // Let's wait for the rest to complete now.
[email protected]c9d6a1d2009-07-14 16:15:201203 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i) {
1204 EXPECT_EQ(OK, requests_[i]->WaitForResult());
[email protected]a6c59f62009-07-29 16:33:331205 requests_[i]->handle()->Reset();
[email protected]f6d1d6eb2009-06-24 20:16:091206 }
1207
[email protected]75439d3b2009-07-23 22:11:171208 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup, completion_count_);
[email protected]f6d1d6eb2009-06-24 20:16:091209}
1210
1211// Make sure that pending requests get serviced after active requests fail.
[email protected]ab838892009-06-30 18:49:051212TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) {
[email protected]211d21722009-07-22 15:48:531213 const size_t kMaxSockets = 5;
1214 CreatePool(kMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:201215
[email protected]0b7648c2009-07-06 20:14:011216 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]f6d1d6eb2009-06-24 20:16:091217
[email protected]211d21722009-07-22 15:48:531218 const size_t kNumberOfRequests = 2 * kDefaultMaxSocketsPerGroup + 1;
1219 ASSERT_LE(kNumberOfRequests, kMaxSockets); // Otherwise the test will hang.
[email protected]f6d1d6eb2009-06-24 20:16:091220
1221 // Queue up all the requests
[email protected]211d21722009-07-22 15:48:531222 for (size_t i = 0; i < kNumberOfRequests; ++i)
1223 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
[email protected]f6d1d6eb2009-06-24 20:16:091224
[email protected]211d21722009-07-22 15:48:531225 for (size_t i = 0; i < kNumberOfRequests; ++i)
1226 EXPECT_EQ(ERR_CONNECTION_FAILED, requests_[i]->WaitForResult());
[email protected]f6d1d6eb2009-06-24 20:16:091227}
1228
[email protected]5fc08e32009-07-15 17:09:571229TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestThenRequestSocket) {
[email protected]211d21722009-07-22 15:48:531230 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571231
1232 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1233
[email protected]a512f5982009-08-18 16:01:061234 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271235 int rv = InitHandle(req.handle(), "a", kDefaultPriority, &req, pool_,
1236 BoundNetLog());
[email protected]5fc08e32009-07-15 17:09:571237 EXPECT_EQ(ERR_IO_PENDING, rv);
1238
1239 // Cancel the active request.
[email protected]a6c59f62009-07-29 16:33:331240 req.handle()->Reset();
[email protected]5fc08e32009-07-15 17:09:571241
[email protected]5a1d7ca2010-04-28 20:12:271242 rv = InitHandle(req.handle(), "a", kDefaultPriority, &req, pool_,
1243 BoundNetLog());
[email protected]5fc08e32009-07-15 17:09:571244 EXPECT_EQ(ERR_IO_PENDING, rv);
1245 EXPECT_EQ(OK, req.WaitForResult());
1246
[email protected]a6c59f62009-07-29 16:33:331247 EXPECT_FALSE(req.handle()->is_reused());
[email protected]75439d3b2009-07-23 22:11:171248 EXPECT_EQ(1U, completion_count_);
[email protected]5fc08e32009-07-15 17:09:571249 EXPECT_EQ(2, client_socket_factory_.allocation_count());
1250}
1251
[email protected]2b7523d2009-07-29 20:29:231252// Regression test for http://crbug.com/17985.
1253TEST_F(ClientSocketPoolBaseTest, GroupWithPendingRequestsIsNotEmpty) {
1254 const int kMaxSockets = 3;
1255 const int kMaxSocketsPerGroup = 2;
1256 CreatePool(kMaxSockets, kMaxSocketsPerGroup);
1257
[email protected]ac790b42009-12-02 04:31:311258 const RequestPriority kHighPriority = HIGHEST;
[email protected]2b7523d2009-07-29 20:29:231259
1260 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
1261 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
1262
1263 // This is going to be a pending request in an otherwise empty group.
1264 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1265
1266 // Reach the maximum socket limit.
1267 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
1268
1269 // Create a stalled group with high priorities.
1270 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kHighPriority));
1271 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kHighPriority));
1272 EXPECT_TRUE(pool_->base()->may_have_stalled_group());
1273
1274 // Release the first two sockets from "a", which will make room
1275 // for requests from "c". After that "a" will have no active sockets
1276 // and one pending request.
1277 EXPECT_TRUE(ReleaseOneConnection(KEEP_ALIVE));
1278 EXPECT_TRUE(ReleaseOneConnection(KEEP_ALIVE));
1279
1280 // Closing idle sockets should not get us into trouble, but in the bug
1281 // we were hitting a CHECK here.
[email protected]4751c742010-05-19 02:44:361282 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
[email protected]89628072010-06-08 05:50:581283 pool_->CloseIdleSockets();
[email protected]2b7523d2009-07-29 20:29:231284}
1285
[email protected]4d3b05d2010-01-27 21:27:291286TEST_F(ClientSocketPoolBaseTest, BasicAsynchronous) {
[email protected]211d21722009-07-22 15:48:531287 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571288
1289 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:061290 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]9e743cd2010-03-16 07:03:531291 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]a796bcec2010-03-22 17:17:261292 int rv = InitHandle(req.handle(), "a", LOWEST, &req, pool_, log.bound());
[email protected]5fc08e32009-07-15 17:09:571293 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a6c59f62009-07-29 16:33:331294 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", req.handle()));
[email protected]5fc08e32009-07-15 17:09:571295 EXPECT_EQ(OK, req.WaitForResult());
[email protected]a6c59f62009-07-29 16:33:331296 EXPECT_TRUE(req.handle()->is_initialized());
1297 EXPECT_TRUE(req.handle()->socket());
1298 req.handle()->Reset();
[email protected]fd7b7c92009-08-20 19:38:301299
[email protected]06650c52010-06-03 00:49:171300 EXPECT_EQ(4u, log.entries().size());
[email protected]e9002a92010-01-29 07:10:461301 EXPECT_TRUE(LogContainsBeginEvent(
[email protected]9e743cd2010-03-16 07:03:531302 log.entries(), 0, NetLog::TYPE_SOCKET_POOL));
[email protected]06650c52010-06-03 00:49:171303 EXPECT_TRUE(LogContainsEvent(
1304 log.entries(), 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
1305 NetLog::PHASE_NONE));
1306 EXPECT_TRUE(LogContainsEvent(
1307 log.entries(), 2, NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET,
1308 NetLog::PHASE_NONE));
[email protected]e9002a92010-01-29 07:10:461309 EXPECT_TRUE(LogContainsEndEvent(
[email protected]06650c52010-06-03 00:49:171310 log.entries(), 3, NetLog::TYPE_SOCKET_POOL));
[email protected]5fc08e32009-07-15 17:09:571311}
1312
[email protected]4d3b05d2010-01-27 21:27:291313TEST_F(ClientSocketPoolBaseTest,
[email protected]5fc08e32009-07-15 17:09:571314 InitConnectionAsynchronousFailure) {
[email protected]211d21722009-07-22 15:48:531315 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571316
1317 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]a512f5982009-08-18 16:01:061318 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]9e743cd2010-03-16 07:03:531319 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]5fc08e32009-07-15 17:09:571320 EXPECT_EQ(ERR_IO_PENDING,
[email protected]a796bcec2010-03-22 17:17:261321 InitHandle(req.handle(), "a", kDefaultPriority, &req, pool_,
1322 log.bound()));
[email protected]a6c59f62009-07-29 16:33:331323 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", req.handle()));
[email protected]5fc08e32009-07-15 17:09:571324 EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult());
[email protected]fd7b7c92009-08-20 19:38:301325
[email protected]06650c52010-06-03 00:49:171326 EXPECT_EQ(3u, log.entries().size());
[email protected]e9002a92010-01-29 07:10:461327 EXPECT_TRUE(LogContainsBeginEvent(
[email protected]9e743cd2010-03-16 07:03:531328 log.entries(), 0, NetLog::TYPE_SOCKET_POOL));
[email protected]06650c52010-06-03 00:49:171329 EXPECT_TRUE(LogContainsEvent(
1330 log.entries(), 1, NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
1331 NetLog::PHASE_NONE));
[email protected]6b624c62010-03-14 08:37:321332 EXPECT_TRUE(LogContainsEndEvent(
[email protected]06650c52010-06-03 00:49:171333 log.entries(), 2, NetLog::TYPE_SOCKET_POOL));
[email protected]5fc08e32009-07-15 17:09:571334}
1335
[email protected]4d3b05d2010-01-27 21:27:291336TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) {
[email protected]b22b5162010-03-16 07:53:101337 // TODO(eroman): Add back the log expectations! Removed them because the
1338 // ordering is difficult, and some may fire during destructor.
[email protected]211d21722009-07-22 15:48:531339 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571340
1341 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:061342 TestSocketRequest req(&request_order_, &completion_count_);
1343 TestSocketRequest req2(&request_order_, &completion_count_);
[email protected]5fc08e32009-07-15 17:09:571344
1345 EXPECT_EQ(ERR_IO_PENDING,
[email protected]a796bcec2010-03-22 17:17:261346 InitHandle(req.handle(), "a", kDefaultPriority, &req, pool_,
1347 BoundNetLog()));
[email protected]9e743cd2010-03-16 07:03:531348 CapturingBoundNetLog log2(CapturingNetLog::kUnbounded);
[email protected]5fc08e32009-07-15 17:09:571349 EXPECT_EQ(ERR_IO_PENDING,
[email protected]a796bcec2010-03-22 17:17:261350 InitHandle(req2.handle(), "a", kDefaultPriority, &req2, pool_,
1351 BoundNetLog()));
[email protected]5fc08e32009-07-15 17:09:571352
[email protected]a6c59f62009-07-29 16:33:331353 req.handle()->Reset();
[email protected]5fc08e32009-07-15 17:09:571354
[email protected]fd7b7c92009-08-20 19:38:301355
1356 // At this point, request 2 is just waiting for the connect job to finish.
[email protected]fd7b7c92009-08-20 19:38:301357
[email protected]5fc08e32009-07-15 17:09:571358 EXPECT_EQ(OK, req2.WaitForResult());
[email protected]a6c59f62009-07-29 16:33:331359 req2.handle()->Reset();
[email protected]fd7b7c92009-08-20 19:38:301360
1361 // Now request 2 has actually finished.
[email protected]9e743cd2010-03-16 07:03:531362 // TODO(eroman): Add back log expectations.
[email protected]5fc08e32009-07-15 17:09:571363}
1364
[email protected]4d3b05d2010-01-27 21:27:291365TEST_F(ClientSocketPoolBaseTest, CancelRequestLimitsJobs) {
[email protected]974ebd62009-08-03 23:14:341366 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
1367
[email protected]17a0c6c2009-08-04 00:07:041368 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1369
[email protected]ac790b42009-12-02 04:31:311370 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
1371 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW));
1372 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
1373 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST));
[email protected]974ebd62009-08-03 23:14:341374
1375 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a"));
1376 requests_[2]->handle()->Reset();
1377 requests_[3]->handle()->Reset();
1378 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a"));
1379
1380 requests_[1]->handle()->Reset();
1381 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a"));
1382
1383 requests_[0]->handle()->Reset();
1384 EXPECT_EQ(kDefaultMaxSocketsPerGroup - 1, pool_->NumConnectJobsInGroup("a"));
1385}
1386
[email protected]5fc08e32009-07-15 17:09:571387// When requests and ConnectJobs are not coupled, the request will get serviced
1388// by whatever comes first.
[email protected]4d3b05d2010-01-27 21:27:291389TEST_F(ClientSocketPoolBaseTest, ReleaseSockets) {
[email protected]211d21722009-07-22 15:48:531390 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571391
1392 // Start job 1 (async OK)
[email protected]b59ff372009-07-15 22:04:321393 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]5fc08e32009-07-15 17:09:571394
[email protected]a512f5982009-08-18 16:01:061395 TestSocketRequest req1(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271396 int rv = InitHandle(req1.handle(), "a", kDefaultPriority, &req1, pool_,
1397 BoundNetLog());
[email protected]5fc08e32009-07-15 17:09:571398 EXPECT_EQ(ERR_IO_PENDING, rv);
1399 EXPECT_EQ(OK, req1.WaitForResult());
1400
1401 // Job 1 finished OK. Start job 2 (also async OK). Request 3 is pending
1402 // without a job.
1403 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
1404
[email protected]a512f5982009-08-18 16:01:061405 TestSocketRequest req2(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271406 rv = InitHandle(req2.handle(), "a", kDefaultPriority, &req2, pool_,
1407 BoundNetLog());
[email protected]5fc08e32009-07-15 17:09:571408 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a512f5982009-08-18 16:01:061409 TestSocketRequest req3(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271410 rv = InitHandle(req3.handle(), "a", kDefaultPriority, &req3, pool_,
1411 BoundNetLog());
[email protected]5fc08e32009-07-15 17:09:571412 EXPECT_EQ(ERR_IO_PENDING, rv);
1413
1414 // Both Requests 2 and 3 are pending. We release socket 1 which should
1415 // service request 2. Request 3 should still be waiting.
[email protected]a6c59f62009-07-29 16:33:331416 req1.handle()->Reset();
[email protected]5fc08e32009-07-15 17:09:571417 MessageLoop::current()->RunAllPending(); // Run the DoReleaseSocket()
[email protected]a6c59f62009-07-29 16:33:331418 ASSERT_TRUE(req2.handle()->socket());
[email protected]5fc08e32009-07-15 17:09:571419 EXPECT_EQ(OK, req2.WaitForResult());
[email protected]a6c59f62009-07-29 16:33:331420 EXPECT_FALSE(req3.handle()->socket());
[email protected]5fc08e32009-07-15 17:09:571421
1422 // Signal job 2, which should service request 3.
1423
1424 client_socket_factory_.SignalJobs();
1425 EXPECT_EQ(OK, req3.WaitForResult());
1426
1427 ASSERT_EQ(3U, request_order_.size());
1428 EXPECT_EQ(&req1, request_order_[0]);
1429 EXPECT_EQ(&req2, request_order_[1]);
1430 EXPECT_EQ(&req3, request_order_[2]);
1431 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
1432}
1433
1434// The requests are not coupled to the jobs. So, the requests should finish in
1435// their priority / insertion order.
[email protected]4d3b05d2010-01-27 21:27:291436TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) {
[email protected]211d21722009-07-22 15:48:531437 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571438 // First two jobs are async.
[email protected]b59ff372009-07-15 22:04:321439 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]5fc08e32009-07-15 17:09:571440
[email protected]a512f5982009-08-18 16:01:061441 TestSocketRequest req1(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271442 int rv = InitHandle(req1.handle(), "a", kDefaultPriority, &req1, pool_,
1443 BoundNetLog());
[email protected]5fc08e32009-07-15 17:09:571444 EXPECT_EQ(ERR_IO_PENDING, rv);
1445
[email protected]a512f5982009-08-18 16:01:061446 TestSocketRequest req2(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271447 rv = InitHandle(req2.handle(), "a", kDefaultPriority, &req2, pool_,
1448 BoundNetLog());
[email protected]5fc08e32009-07-15 17:09:571449 EXPECT_EQ(ERR_IO_PENDING, rv);
1450
1451 // The pending job is sync.
[email protected]b59ff372009-07-15 22:04:321452 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
[email protected]5fc08e32009-07-15 17:09:571453
[email protected]a512f5982009-08-18 16:01:061454 TestSocketRequest req3(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271455 rv = InitHandle(req3.handle(), "a", kDefaultPriority, &req3, pool_,
1456 BoundNetLog());
[email protected]5fc08e32009-07-15 17:09:571457 EXPECT_EQ(ERR_IO_PENDING, rv);
1458
1459 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult());
1460 EXPECT_EQ(OK, req2.WaitForResult());
1461 EXPECT_EQ(ERR_CONNECTION_FAILED, req3.WaitForResult());
1462
1463 ASSERT_EQ(3U, request_order_.size());
1464 EXPECT_EQ(&req1, request_order_[0]);
1465 EXPECT_EQ(&req2, request_order_[1]);
1466 EXPECT_EQ(&req3, request_order_[2]);
1467}
1468
[email protected]4d3b05d2010-01-27 21:27:291469TEST_F(ClientSocketPoolBaseTest, DISABLED_LoadState) {
[email protected]211d21722009-07-22 15:48:531470 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571471 connect_job_factory_->set_job_type(
[email protected]b59ff372009-07-15 22:04:321472 TestConnectJob::kMockAdvancingLoadStateJob);
[email protected]5fc08e32009-07-15 17:09:571473
[email protected]a512f5982009-08-18 16:01:061474 TestSocketRequest req1(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271475 int rv = InitHandle(req1.handle(), "a", kDefaultPriority, &req1, pool_,
1476 BoundNetLog());
[email protected]5fc08e32009-07-15 17:09:571477 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a6c59f62009-07-29 16:33:331478 EXPECT_EQ(LOAD_STATE_IDLE, req1.handle()->GetLoadState());
[email protected]5fc08e32009-07-15 17:09:571479
1480 MessageLoop::current()->RunAllPending();
1481
[email protected]a512f5982009-08-18 16:01:061482 TestSocketRequest req2(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271483 rv = InitHandle(req2.handle(), "a", kDefaultPriority, &req2, pool_,
1484 BoundNetLog());
[email protected]5fc08e32009-07-15 17:09:571485 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a6c59f62009-07-29 16:33:331486 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, req1.handle()->GetLoadState());
1487 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, req2.handle()->GetLoadState());
[email protected]5fc08e32009-07-15 17:09:571488}
1489
[email protected]4d3b05d2010-01-27 21:27:291490TEST_F(ClientSocketPoolBaseTest, CleanupTimedOutIdleSockets) {
[email protected]9bf28db2009-08-29 01:35:161491 CreatePoolWithIdleTimeouts(
1492 kDefaultMaxSockets, kDefaultMaxSocketsPerGroup,
1493 base::TimeDelta(), // Time out unused sockets immediately.
1494 base::TimeDelta::FromDays(1)); // Don't time out used sockets.
1495
1496 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1497
1498 // Startup two mock pending connect jobs, which will sit in the MessageLoop.
1499
1500 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271501 int rv = InitHandle(req.handle(), "a", LOWEST, &req, pool_, BoundNetLog());
[email protected]9bf28db2009-08-29 01:35:161502 EXPECT_EQ(ERR_IO_PENDING, rv);
1503 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", req.handle()));
1504
1505 TestSocketRequest req2(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271506 rv = InitHandle(req2.handle(), "a", LOWEST, &req2, pool_, BoundNetLog());
[email protected]9bf28db2009-08-29 01:35:161507 EXPECT_EQ(ERR_IO_PENDING, rv);
1508 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", req2.handle()));
1509
1510 // Cancel one of the requests. Wait for the other, which will get the first
1511 // job. Release the socket. Run the loop again to make sure the second
1512 // socket is sitting idle and the first one is released (since ReleaseSocket()
1513 // just posts a DoReleaseSocket() task).
1514
1515 req.handle()->Reset();
1516 EXPECT_EQ(OK, req2.WaitForResult());
1517 req2.handle()->Reset();
[email protected]6b175382009-10-13 06:47:471518
1519 // We post all of our delayed tasks with a 2ms delay. I.e. they don't
1520 // actually become pending until 2ms after they have been created. In order
1521 // to flush all tasks, we need to wait so that we know there are no
1522 // soon-to-be-pending tasks waiting.
1523 PlatformThread::Sleep(10);
[email protected]9bf28db2009-08-29 01:35:161524 MessageLoop::current()->RunAllPending();
1525
1526 ASSERT_EQ(2, pool_->IdleSocketCount());
[email protected]d3f66572009-09-09 22:38:041527
[email protected]9bf28db2009-08-29 01:35:161528 // Invoke the idle socket cleanup check. Only one socket should be left, the
1529 // used socket. Request it to make sure that it's used.
1530
1531 pool_->CleanupTimedOutIdleSockets();
[email protected]9e743cd2010-03-16 07:03:531532 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]a796bcec2010-03-22 17:17:261533 rv = InitHandle(req.handle(), "a", LOWEST, &req, pool_, log.bound());
[email protected]9bf28db2009-08-29 01:35:161534 EXPECT_EQ(OK, rv);
1535 EXPECT_TRUE(req.handle()->is_reused());
[email protected]fd4fe0b2010-02-08 23:02:151536 EXPECT_TRUE(LogContainsEntryWithType(
[email protected]d13f51b2010-04-27 23:20:451537 log.entries(), 1, NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET));
[email protected]9bf28db2009-08-29 01:35:161538}
1539
[email protected]2041cf342010-02-19 03:15:591540// Make sure that we process all pending requests even when we're stalling
[email protected]4f2abec2010-02-03 18:10:161541// because of multiple releasing disconnected sockets.
1542TEST_F(ClientSocketPoolBaseTest, MultipleReleasingDisconnectedSockets) {
1543 CreatePoolWithIdleTimeouts(
1544 kDefaultMaxSockets, kDefaultMaxSocketsPerGroup,
1545 base::TimeDelta(), // Time out unused sockets immediately.
1546 base::TimeDelta::FromDays(1)); // Don't time out used sockets.
1547
1548 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
1549
1550 // Startup 4 connect jobs. Two of them will be pending.
1551
1552 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271553 int rv = InitHandle(req.handle(), "a", LOWEST, &req, pool_, BoundNetLog());
[email protected]4f2abec2010-02-03 18:10:161554 EXPECT_EQ(OK, rv);
1555
1556 TestSocketRequest req2(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271557 rv = InitHandle(req2.handle(), "a", LOWEST, &req2, pool_, BoundNetLog());
[email protected]4f2abec2010-02-03 18:10:161558 EXPECT_EQ(OK, rv);
1559
1560 TestSocketRequest req3(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271561 rv = InitHandle(req3.handle(), "a", LOWEST, &req3, pool_, BoundNetLog());
[email protected]4f2abec2010-02-03 18:10:161562 EXPECT_EQ(ERR_IO_PENDING, rv);
1563
1564 TestSocketRequest req4(&request_order_, &completion_count_);
[email protected]5a1d7ca2010-04-28 20:12:271565 rv = InitHandle(req4.handle(), "a", LOWEST, &req4, pool_, BoundNetLog());
[email protected]4f2abec2010-02-03 18:10:161566 EXPECT_EQ(ERR_IO_PENDING, rv);
1567
1568 // Release two disconnected sockets.
1569
1570 req.handle()->socket()->Disconnect();
1571 req.handle()->Reset();
1572 req2.handle()->socket()->Disconnect();
1573 req2.handle()->Reset();
1574
1575 EXPECT_EQ(OK, req3.WaitForResult());
1576 EXPECT_FALSE(req3.handle()->is_reused());
1577 EXPECT_EQ(OK, req4.WaitForResult());
1578 EXPECT_FALSE(req4.handle()->is_reused());
1579}
1580
[email protected]d7027bb2010-05-10 18:58:541581// Regression test for http://crbug.com/42267.
1582// When DoReleaseSocket() is processed for one socket, it is blocked because the
1583// other stalled groups all have releasing sockets, so no progress can be made.
1584TEST_F(ClientSocketPoolBaseTest, SocketLimitReleasingSockets) {
1585 CreatePoolWithIdleTimeouts(
1586 4 /* socket limit */, 4 /* socket limit per group */,
1587 base::TimeDelta(), // Time out unused sockets immediately.
1588 base::TimeDelta::FromDays(1)); // Don't time out used sockets.
1589
1590 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
1591
1592 // Max out the socket limit with 2 per group.
1593
1594 scoped_ptr<TestSocketRequest> req_a[4];
1595 scoped_ptr<TestSocketRequest> req_b[4];
1596
1597 for (int i = 0; i < 2; ++i) {
1598 req_a[i].reset(new TestSocketRequest(&request_order_, &completion_count_));
1599 req_b[i].reset(new TestSocketRequest(&request_order_, &completion_count_));
1600 EXPECT_EQ(OK,
1601 InitHandle(req_a[i]->handle(), "a", LOWEST, req_a[i].get(), pool_,
1602 BoundNetLog()));
1603 EXPECT_EQ(OK,
1604 InitHandle(req_b[i]->handle(), "b", LOWEST, req_b[i].get(), pool_,
1605 BoundNetLog()));
1606 }
[email protected]b89f7e42010-05-20 20:37:001607
[email protected]d7027bb2010-05-10 18:58:541608 // Make 4 pending requests, 2 per group.
1609
1610 for (int i = 2; i < 4; ++i) {
1611 req_a[i].reset(new TestSocketRequest(&request_order_, &completion_count_));
1612 req_b[i].reset(new TestSocketRequest(&request_order_, &completion_count_));
1613 EXPECT_EQ(ERR_IO_PENDING,
1614 InitHandle(req_a[i]->handle(), "a", LOWEST, req_a[i].get(), pool_,
1615 BoundNetLog()));
1616 EXPECT_EQ(ERR_IO_PENDING,
1617 InitHandle(req_b[i]->handle(), "b", LOWEST, req_b[i].get(), pool_,
1618 BoundNetLog()));
1619 }
1620
1621 // Release b's socket first. The order is important, because in
1622 // DoReleaseSocket(), we'll process b's released socket, and since both b and
1623 // a are stalled, but 'a' is lower lexicographically, we'll process group 'a'
1624 // first, which has a releasing socket, so it refuses to start up another
1625 // ConnectJob. So, we used to infinite loop on this.
1626 req_b[0]->handle()->socket()->Disconnect();
1627 req_b[0]->handle()->Reset();
1628 req_a[0]->handle()->socket()->Disconnect();
1629 req_a[0]->handle()->Reset();
1630
1631 // Used to get stuck here.
1632 MessageLoop::current()->RunAllPending();
1633
1634 req_b[1]->handle()->socket()->Disconnect();
1635 req_b[1]->handle()->Reset();
1636 req_a[1]->handle()->socket()->Disconnect();
1637 req_a[1]->handle()->Reset();
1638
1639 for (int i = 2; i < 4; ++i) {
1640 EXPECT_EQ(OK, req_b[i]->WaitForResult());
1641 EXPECT_EQ(OK, req_a[i]->WaitForResult());
1642 }
1643}
1644
[email protected]fd4fe0b2010-02-08 23:02:151645TEST_F(ClientSocketPoolBaseTest,
1646 ReleasingDisconnectedSocketsMaintainsPriorityOrder) {
1647 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
1648
1649 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1650
1651 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1652 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1653 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1654 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1655
1656 EXPECT_EQ(OK, requests_[0]->WaitForResult());
1657 EXPECT_EQ(OK, requests_[1]->WaitForResult());
1658 EXPECT_EQ(2u, completion_count_);
1659
1660 // Releases one connection.
1661 EXPECT_TRUE(ReleaseOneConnection(NO_KEEP_ALIVE));
1662 EXPECT_EQ(OK, requests_[2]->WaitForResult());
1663
1664 EXPECT_TRUE(ReleaseOneConnection(NO_KEEP_ALIVE));
1665 EXPECT_EQ(OK, requests_[3]->WaitForResult());
1666 EXPECT_EQ(4u, completion_count_);
1667
1668 EXPECT_EQ(1, GetOrderOfRequest(1));
1669 EXPECT_EQ(2, GetOrderOfRequest(2));
1670 EXPECT_EQ(3, GetOrderOfRequest(3));
1671 EXPECT_EQ(4, GetOrderOfRequest(4));
1672
1673 // Make sure we test order of all requests made.
1674 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(5));
1675}
1676
[email protected]4f1e4982010-03-02 18:31:041677class TestReleasingSocketRequest : public CallbackRunner< Tuple1<int> > {
1678 public:
1679 explicit TestReleasingSocketRequest(TestClientSocketPool* pool)
1680 : pool_(pool) {}
1681
1682 ClientSocketHandle* handle() { return &handle_; }
1683
1684 int WaitForResult() {
1685 return callback_.WaitForResult();
1686 }
1687
1688 virtual void RunWithParams(const Tuple1<int>& params) {
1689 callback_.RunWithParams(params);
1690 handle_.Reset();
[email protected]a796bcec2010-03-22 17:17:261691 EXPECT_EQ(ERR_IO_PENDING, InitHandle(&handle2_, "a", kDefaultPriority,
[email protected]5a1d7ca2010-04-28 20:12:271692 &callback2_, pool_, BoundNetLog()));
[email protected]4f1e4982010-03-02 18:31:041693 }
1694
1695 private:
1696 TestClientSocketPool* const pool_;
1697 ClientSocketHandle handle_;
1698 ClientSocketHandle handle2_;
1699 TestCompletionCallback callback_;
1700 TestCompletionCallback callback2_;
1701};
1702
1703// This test covers the case where, within the same DoReleaseSocket() callback,
1704// we release the just acquired socket and start up a new request. See bug
1705// 36871 for details.
1706TEST_F(ClientSocketPoolBaseTest, ReleasedSocketReleasesToo) {
1707 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
1708
1709 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
1710
1711 // Complete one request and release the socket.
1712 ClientSocketHandle handle;
1713 TestCompletionCallback callback;
[email protected]a796bcec2010-03-22 17:17:261714 EXPECT_EQ(OK, InitHandle(&handle, "a", kDefaultPriority, &callback, pool_,
[email protected]5a1d7ca2010-04-28 20:12:271715 BoundNetLog()));
[email protected]4f1e4982010-03-02 18:31:041716 handle.Reset();
[email protected]6b624c62010-03-14 08:37:321717
[email protected]4f1e4982010-03-02 18:31:041718 // Before the DoReleaseSocket() task has run, start up a
1719 // TestReleasingSocketRequest. This one will be ERR_IO_PENDING since
1720 // num_releasing_sockets > 0 and there was no idle socket to use yet.
1721 TestReleasingSocketRequest request(pool_.get());
[email protected]a796bcec2010-03-22 17:17:261722 EXPECT_EQ(ERR_IO_PENDING, InitHandle(request.handle(), "a", kDefaultPriority,
[email protected]5a1d7ca2010-04-28 20:12:271723 &request, pool_, BoundNetLog()));
[email protected]4f1e4982010-03-02 18:31:041724
1725 EXPECT_EQ(OK, request.WaitForResult());
1726}
1727
[email protected]b6501d3d2010-06-03 23:53:341728// http://crbug.com/44724 regression test.
1729// We start releasing the pool when we flush on network change. When that
1730// happens, the only active references are in the ClientSocketHandles. When a
1731// ConnectJob completes and calls back into the last ClientSocketHandle, that
1732// callback can release the last reference and delete the pool. After the
1733// callback finishes, we go back to the stack frame within the now-deleted pool.
1734// Executing any code that refers to members of the now-deleted pool can cause
1735// crashes.
1736TEST_F(ClientSocketPoolBaseTest, CallbackThatReleasesPool) {
1737 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
1738 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
1739
1740 ClientSocketHandle handle;
1741 TestCompletionCallback callback;
1742 EXPECT_EQ(ERR_IO_PENDING,
1743 InitHandle(&handle, "a", kDefaultPriority,
1744 &callback, pool_, BoundNetLog()));
1745
1746 // Simulate flushing the pool.
1747 pool_ = NULL;
1748
1749 // We'll call back into this now.
1750 callback.WaitForResult();
1751}
1752
[email protected]a7e38572010-06-07 18:22:241753TEST_F(ClientSocketPoolBaseTest, DoNotReuseSocketAfterFlush) {
1754 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
1755 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1756
1757 ClientSocketHandle handle;
1758 TestCompletionCallback callback;
1759 EXPECT_EQ(ERR_IO_PENDING,
1760 InitHandle(&handle, "a", kDefaultPriority,
1761 &callback, pool_, BoundNetLog()));
1762 EXPECT_EQ(OK, callback.WaitForResult());
1763 EXPECT_EQ(ClientSocketHandle::UNUSED, handle.reuse_type());
1764
1765 pool_->Flush();
1766
1767 handle.Reset();
1768 MessageLoop::current()->RunAllPending();
1769
1770 EXPECT_EQ(ERR_IO_PENDING,
1771 InitHandle(&handle, "a", kDefaultPriority,
1772 &callback, pool_, BoundNetLog()));
1773 EXPECT_EQ(OK, callback.WaitForResult());
1774 EXPECT_EQ(ClientSocketHandle::UNUSED, handle.reuse_type());
1775}
1776
[email protected]f6d1d6eb2009-06-24 20:16:091777} // namespace
1778
1779} // namespace net