blob: 9fe76844a7b1cc3bcfd95dcbbbda085d0ac430d6 [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]fd7b7c92009-08-20 19:38:3012#include "net/base/load_log.h"
13#include "net/base/load_log_unittest.h"
[email protected]fd4fe0b2010-02-08 23:02:1514#include "net/base/load_log_util.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]75439d3b2009-07-23 22:11:1721#include "net/socket/socket_test_util.h"
[email protected]f6d1d6eb2009-06-24 20:16:0922#include "testing/gtest/include/gtest/gtest.h"
23
24namespace net {
25
26namespace {
27
[email protected]211d21722009-07-22 15:48:5328const int kDefaultMaxSockets = 4;
[email protected]c9d6a1d2009-07-14 16:15:2029const int kDefaultMaxSocketsPerGroup = 2;
[email protected]ac790b42009-12-02 04:31:3130const net::RequestPriority kDefaultPriority = MEDIUM;
[email protected]0b7648c2009-07-06 20:14:0131
[email protected]7fc5b09a2010-02-27 00:07:3832typedef const void* TestSocketParams;
33typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase;
[email protected]d80a4322009-08-14 07:07:4934
[email protected]f6d1d6eb2009-06-24 20:16:0935class MockClientSocket : public ClientSocket {
36 public:
37 MockClientSocket() : connected_(false) {}
38
[email protected]ab838892009-06-30 18:49:0539 // Socket methods:
40 virtual int Read(
41 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) {
42 return ERR_UNEXPECTED;
43 }
44
45 virtual int Write(
46 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) {
47 return ERR_UNEXPECTED;
48 }
[email protected]d3f66572009-09-09 22:38:0449 virtual bool SetReceiveBufferSize(int32 size) { return true; };
50 virtual bool SetSendBufferSize(int32 size) { return true; };
[email protected]ab838892009-06-30 18:49:0551
[email protected]f6d1d6eb2009-06-24 20:16:0952 // ClientSocket methods:
[email protected]ab838892009-06-30 18:49:0553
[email protected]5a05c47a2009-11-02 23:25:1954 virtual int Connect(CompletionCallback* callback, LoadLog* load_log) {
[email protected]f6d1d6eb2009-06-24 20:16:0955 connected_ = true;
56 return OK;
57 }
[email protected]f6d1d6eb2009-06-24 20:16:0958
[email protected]ab838892009-06-30 18:49:0559 virtual void Disconnect() { connected_ = false; }
60 virtual bool IsConnected() const { return connected_; }
61 virtual bool IsConnectedAndIdle() const { return connected_; }
[email protected]0b7648c2009-07-06 20:14:0162
[email protected]ac9eec62010-02-20 18:50:3863 virtual int GetPeerAddress(AddressList* /* address */) const {
[email protected]9f864b32010-01-20 15:01:1664 return ERR_UNEXPECTED;
[email protected]f6d1d6eb2009-06-24 20:16:0965 }
[email protected]f6d1d6eb2009-06-24 20:16:0966
67 private:
68 bool connected_;
[email protected]f6d1d6eb2009-06-24 20:16:0969
[email protected]ab838892009-06-30 18:49:0570 DISALLOW_COPY_AND_ASSIGN(MockClientSocket);
[email protected]f6d1d6eb2009-06-24 20:16:0971};
72
[email protected]5fc08e32009-07-15 17:09:5773class TestConnectJob;
74
[email protected]f6d1d6eb2009-06-24 20:16:0975class MockClientSocketFactory : public ClientSocketFactory {
76 public:
[email protected]ab838892009-06-30 18:49:0577 MockClientSocketFactory() : allocation_count_(0) {}
[email protected]f6d1d6eb2009-06-24 20:16:0978
79 virtual ClientSocket* CreateTCPClientSocket(const AddressList& addresses) {
80 allocation_count_++;
[email protected]ab838892009-06-30 18:49:0581 return NULL;
[email protected]f6d1d6eb2009-06-24 20:16:0982 }
83
84 virtual SSLClientSocket* CreateSSLClientSocket(
85 ClientSocket* transport_socket,
86 const std::string& hostname,
87 const SSLConfig& ssl_config) {
88 NOTIMPLEMENTED();
89 return NULL;
90 }
91
[email protected]5fc08e32009-07-15 17:09:5792 void WaitForSignal(TestConnectJob* job) { waiting_jobs_.push_back(job); }
93 void SignalJobs();
94
[email protected]f6d1d6eb2009-06-24 20:16:0995 int allocation_count() const { return allocation_count_; }
96
[email protected]f6d1d6eb2009-06-24 20:16:0997 private:
98 int allocation_count_;
[email protected]5fc08e32009-07-15 17:09:5799 std::vector<TestConnectJob*> waiting_jobs_;
[email protected]f6d1d6eb2009-06-24 20:16:09100};
101
[email protected]ab838892009-06-30 18:49:05102class TestConnectJob : public ConnectJob {
103 public:
104 enum JobType {
105 kMockJob,
106 kMockFailingJob,
107 kMockPendingJob,
108 kMockPendingFailingJob,
[email protected]5fc08e32009-07-15 17:09:57109 kMockWaitingJob,
110 kMockAdvancingLoadStateJob,
[email protected]ab838892009-06-30 18:49:05111 };
112
113 TestConnectJob(JobType job_type,
114 const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49115 const TestClientSocketPoolBase::Request& request,
[email protected]974ebd62009-08-03 23:14:34116 base::TimeDelta timeout_duration,
[email protected]ab838892009-06-30 18:49:05117 ConnectJob::Delegate* delegate,
[email protected]fd7b7c92009-08-20 19:38:30118 MockClientSocketFactory* client_socket_factory,
119 LoadLog* load_log)
[email protected]4d3b05d2010-01-27 21:27:29120 : ConnectJob(group_name, timeout_duration, delegate, load_log),
[email protected]2ab05b52009-07-01 23:57:58121 job_type_(job_type),
[email protected]ab838892009-06-30 18:49:05122 client_socket_factory_(client_socket_factory),
[email protected]46451352009-09-01 14:54:21123 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
124 load_state_(LOAD_STATE_IDLE) {}
[email protected]ab838892009-06-30 18:49:05125
[email protected]974ebd62009-08-03 23:14:34126 void Signal() {
127 DoConnect(waiting_success_, true /* async */);
128 }
129
[email protected]46451352009-09-01 14:54:21130 virtual LoadState GetLoadState() const { return load_state_; }
131
[email protected]974ebd62009-08-03 23:14:34132 private:
[email protected]ab838892009-06-30 18:49:05133 // ConnectJob methods:
134
[email protected]974ebd62009-08-03 23:14:34135 virtual int ConnectInternal() {
[email protected]ab838892009-06-30 18:49:05136 AddressList ignored;
137 client_socket_factory_->CreateTCPClientSocket(ignored);
[email protected]6e713f02009-08-06 02:56:40138 set_socket(new MockClientSocket());
[email protected]ab838892009-06-30 18:49:05139 switch (job_type_) {
140 case kMockJob:
141 return DoConnect(true /* successful */, false /* sync */);
142 case kMockFailingJob:
143 return DoConnect(false /* error */, false /* sync */);
144 case kMockPendingJob:
[email protected]5fc08e32009-07-15 17:09:57145 set_load_state(LOAD_STATE_CONNECTING);
[email protected]6b175382009-10-13 06:47:47146
147 // Depending on execution timings, posting a delayed task can result
148 // in the task getting executed the at the earliest possible
149 // opportunity or only after returning once from the message loop and
150 // then a second call into the message loop. In order to make behavior
151 // more deterministic, we change the default delay to 2ms. This should
152 // always require us to wait for the second call into the message loop.
153 //
154 // N.B. The correct fix for this and similar timing problems is to
155 // abstract time for the purpose of unittests. Unfortunately, we have
156 // a lot of third-party components that directly call the various
157 // time functions, so this change would be rather invasive.
158 MessageLoop::current()->PostDelayedTask(
[email protected]ab838892009-06-30 18:49:05159 FROM_HERE,
160 method_factory_.NewRunnableMethod(
[email protected]6b175382009-10-13 06:47:47161 &TestConnectJob::DoConnect,
162 true /* successful */,
163 true /* async */),
164 2);
[email protected]ab838892009-06-30 18:49:05165 return ERR_IO_PENDING;
166 case kMockPendingFailingJob:
[email protected]5fc08e32009-07-15 17:09:57167 set_load_state(LOAD_STATE_CONNECTING);
[email protected]6b175382009-10-13 06:47:47168 MessageLoop::current()->PostDelayedTask(
[email protected]ab838892009-06-30 18:49:05169 FROM_HERE,
170 method_factory_.NewRunnableMethod(
[email protected]6b175382009-10-13 06:47:47171 &TestConnectJob::DoConnect,
172 false /* error */,
173 true /* async */),
174 2);
[email protected]ab838892009-06-30 18:49:05175 return ERR_IO_PENDING;
[email protected]5fc08e32009-07-15 17:09:57176 case kMockWaitingJob:
177 client_socket_factory_->WaitForSignal(this);
178 waiting_success_ = true;
179 return ERR_IO_PENDING;
180 case kMockAdvancingLoadStateJob:
[email protected]6b175382009-10-13 06:47:47181 MessageLoop::current()->PostDelayedTask(
[email protected]5fc08e32009-07-15 17:09:57182 FROM_HERE,
183 method_factory_.NewRunnableMethod(
[email protected]6b175382009-10-13 06:47:47184 &TestConnectJob::AdvanceLoadState, load_state_),
185 2);
[email protected]5fc08e32009-07-15 17:09:57186 return ERR_IO_PENDING;
[email protected]ab838892009-06-30 18:49:05187 default:
188 NOTREACHED();
[email protected]6e713f02009-08-06 02:56:40189 set_socket(NULL);
[email protected]ab838892009-06-30 18:49:05190 return ERR_FAILED;
191 }
192 }
193
[email protected]46451352009-09-01 14:54:21194 void set_load_state(LoadState load_state) { load_state_ = load_state; }
195
[email protected]ab838892009-06-30 18:49:05196 int DoConnect(bool succeed, bool was_async) {
197 int result = ERR_CONNECTION_FAILED;
[email protected]ab838892009-06-30 18:49:05198 if (succeed) {
199 result = OK;
[email protected]5a05c47a2009-11-02 23:25:19200 socket()->Connect(NULL, NULL);
[email protected]6e713f02009-08-06 02:56:40201 } else {
202 set_socket(NULL);
[email protected]ab838892009-06-30 18:49:05203 }
[email protected]2ab05b52009-07-01 23:57:58204
205 if (was_async)
[email protected]fd7b7c92009-08-20 19:38:30206 NotifyDelegateOfCompletion(result);
[email protected]ab838892009-06-30 18:49:05207 return result;
208 }
209
[email protected]5fc08e32009-07-15 17:09:57210 void AdvanceLoadState(LoadState state) {
211 int tmp = state;
212 tmp++;
213 state = static_cast<LoadState>(tmp);
214 set_load_state(state);
215 // Post a delayed task so RunAllPending() won't run it.
216 MessageLoop::current()->PostDelayedTask(
217 FROM_HERE,
218 method_factory_.NewRunnableMethod(&TestConnectJob::AdvanceLoadState,
219 state),
220 1 /* 1ms delay */);
221 }
222
223 bool waiting_success_;
[email protected]ab838892009-06-30 18:49:05224 const JobType job_type_;
[email protected]5fc08e32009-07-15 17:09:57225 MockClientSocketFactory* const client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05226 ScopedRunnableMethodFactory<TestConnectJob> method_factory_;
[email protected]46451352009-09-01 14:54:21227 LoadState load_state_;
[email protected]ab838892009-06-30 18:49:05228
229 DISALLOW_COPY_AND_ASSIGN(TestConnectJob);
230};
231
[email protected]d80a4322009-08-14 07:07:49232class TestConnectJobFactory
233 : public TestClientSocketPoolBase::ConnectJobFactory {
[email protected]ab838892009-06-30 18:49:05234 public:
[email protected]5fc08e32009-07-15 17:09:57235 explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory)
[email protected]ab838892009-06-30 18:49:05236 : job_type_(TestConnectJob::kMockJob),
237 client_socket_factory_(client_socket_factory) {}
238
239 virtual ~TestConnectJobFactory() {}
240
241 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; }
242
[email protected]974ebd62009-08-03 23:14:34243 void set_timeout_duration(base::TimeDelta timeout_duration) {
244 timeout_duration_ = timeout_duration;
245 }
246
[email protected]ab838892009-06-30 18:49:05247 // ConnectJobFactory methods:
248
249 virtual ConnectJob* NewConnectJob(
250 const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49251 const TestClientSocketPoolBase::Request& request,
[email protected]fd7b7c92009-08-20 19:38:30252 ConnectJob::Delegate* delegate,
253 LoadLog* load_log) const {
[email protected]ab838892009-06-30 18:49:05254 return new TestConnectJob(job_type_,
255 group_name,
256 request,
[email protected]974ebd62009-08-03 23:14:34257 timeout_duration_,
[email protected]ab838892009-06-30 18:49:05258 delegate,
[email protected]fd7b7c92009-08-20 19:38:30259 client_socket_factory_,
260 load_log);
[email protected]ab838892009-06-30 18:49:05261 }
262
263 private:
264 TestConnectJob::JobType job_type_;
[email protected]974ebd62009-08-03 23:14:34265 base::TimeDelta timeout_duration_;
[email protected]5fc08e32009-07-15 17:09:57266 MockClientSocketFactory* const client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05267
268 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory);
269};
270
271class TestClientSocketPool : public ClientSocketPool {
272 public:
273 TestClientSocketPool(
[email protected]211d21722009-07-22 15:48:53274 int max_sockets,
[email protected]ab838892009-06-30 18:49:05275 int max_sockets_per_group,
[email protected]9bf28db2009-08-29 01:35:16276 base::TimeDelta unused_idle_socket_timeout,
277 base::TimeDelta used_idle_socket_timeout,
[email protected]d80a4322009-08-14 07:07:49278 TestClientSocketPoolBase::ConnectJobFactory* connect_job_factory)
[email protected]9bf28db2009-08-29 01:35:16279 : base_(max_sockets, max_sockets_per_group,
280 unused_idle_socket_timeout, used_idle_socket_timeout,
[email protected]100d5fb92009-12-21 21:08:35281 connect_job_factory, NULL) {}
[email protected]ab838892009-06-30 18:49:05282
283 virtual int RequestSocket(
284 const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49285 const void* params,
[email protected]ac790b42009-12-02 04:31:31286 net::RequestPriority priority,
[email protected]ab838892009-06-30 18:49:05287 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46288 CompletionCallback* callback,
289 LoadLog* load_log) {
[email protected]d80a4322009-08-14 07:07:49290 return base_.RequestSocket(
291 group_name, params, priority, handle, callback, load_log);
[email protected]ab838892009-06-30 18:49:05292 }
293
294 virtual void CancelRequest(
295 const std::string& group_name,
296 const ClientSocketHandle* handle) {
[email protected]d80a4322009-08-14 07:07:49297 base_.CancelRequest(group_name, handle);
[email protected]ab838892009-06-30 18:49:05298 }
299
300 virtual void ReleaseSocket(
301 const std::string& group_name,
302 ClientSocket* socket) {
[email protected]d80a4322009-08-14 07:07:49303 base_.ReleaseSocket(group_name, socket);
[email protected]ab838892009-06-30 18:49:05304 }
305
306 virtual void CloseIdleSockets() {
[email protected]d80a4322009-08-14 07:07:49307 base_.CloseIdleSockets();
[email protected]ab838892009-06-30 18:49:05308 }
309
[email protected]d80a4322009-08-14 07:07:49310 virtual int IdleSocketCount() const { return base_.idle_socket_count(); }
[email protected]ab838892009-06-30 18:49:05311
312 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
[email protected]d80a4322009-08-14 07:07:49313 return base_.IdleSocketCountInGroup(group_name);
[email protected]ab838892009-06-30 18:49:05314 }
315
316 virtual LoadState GetLoadState(const std::string& group_name,
317 const ClientSocketHandle* handle) const {
[email protected]d80a4322009-08-14 07:07:49318 return base_.GetLoadState(group_name, handle);
[email protected]ab838892009-06-30 18:49:05319 }
320
[email protected]d80a4322009-08-14 07:07:49321 const TestClientSocketPoolBase* base() const { return &base_; }
[email protected]c9d6a1d2009-07-14 16:15:20322
[email protected]974ebd62009-08-03 23:14:34323 int NumConnectJobsInGroup(const std::string& group_name) const {
[email protected]d80a4322009-08-14 07:07:49324 return base_.NumConnectJobsInGroup(group_name);
[email protected]974ebd62009-08-03 23:14:34325 }
326
[email protected]9bf28db2009-08-29 01:35:16327 void CleanupTimedOutIdleSockets() { base_.CleanupIdleSockets(false); }
328
[email protected]ab838892009-06-30 18:49:05329 private:
[email protected]5389bc72009-11-05 23:34:24330 ~TestClientSocketPool() {}
331
[email protected]d80a4322009-08-14 07:07:49332 TestClientSocketPoolBase base_;
[email protected]ab838892009-06-30 18:49:05333
334 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool);
335};
336
[email protected]a937a06d2009-08-19 21:19:24337} // namespace
338
[email protected]7fc5b09a2010-02-27 00:07:38339REGISTER_SOCKET_PARAMS_FOR_POOL(TestClientSocketPool, TestSocketParams);
[email protected]a937a06d2009-08-19 21:19:24340
341namespace {
342
[email protected]5fc08e32009-07-15 17:09:57343void MockClientSocketFactory::SignalJobs() {
344 for (std::vector<TestConnectJob*>::iterator it = waiting_jobs_.begin();
345 it != waiting_jobs_.end(); ++it) {
346 (*it)->Signal();
347 }
348 waiting_jobs_.clear();
349}
350
[email protected]974ebd62009-08-03 23:14:34351class TestConnectJobDelegate : public ConnectJob::Delegate {
352 public:
353 TestConnectJobDelegate()
354 : have_result_(false), waiting_for_result_(false), result_(OK) {}
355 virtual ~TestConnectJobDelegate() {}
356
357 virtual void OnConnectJobComplete(int result, ConnectJob* job) {
358 result_ = result;
[email protected]6e713f02009-08-06 02:56:40359 scoped_ptr<ClientSocket> socket(job->ReleaseSocket());
[email protected]9b6fee12009-09-29 18:13:07360 // socket.get() should be NULL iff result != OK
361 EXPECT_EQ(socket.get() == NULL, result != OK);
[email protected]974ebd62009-08-03 23:14:34362 delete job;
363 have_result_ = true;
364 if (waiting_for_result_)
365 MessageLoop::current()->Quit();
366 }
367
368 int WaitForResult() {
369 DCHECK(!waiting_for_result_);
370 while (!have_result_) {
371 waiting_for_result_ = true;
372 MessageLoop::current()->Run();
373 waiting_for_result_ = false;
374 }
375 have_result_ = false; // auto-reset for next callback
376 return result_;
377 }
378
379 private:
380 bool have_result_;
381 bool waiting_for_result_;
382 int result_;
383};
384
[email protected]75439d3b2009-07-23 22:11:17385class ClientSocketPoolBaseTest : public ClientSocketPoolTest {
[email protected]f6d1d6eb2009-06-24 20:16:09386 protected:
[email protected]17a0c6c2009-08-04 00:07:04387 ClientSocketPoolBaseTest() {}
[email protected]c9d6a1d2009-07-14 16:15:20388
[email protected]211d21722009-07-22 15:48:53389 void CreatePool(int max_sockets, int max_sockets_per_group) {
[email protected]9bf28db2009-08-29 01:35:16390 CreatePoolWithIdleTimeouts(
391 max_sockets,
392 max_sockets_per_group,
393 base::TimeDelta::FromSeconds(kUnusedIdleSocketTimeout),
394 base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout));
395 }
396
397 void CreatePoolWithIdleTimeouts(
398 int max_sockets, int max_sockets_per_group,
399 base::TimeDelta unused_idle_socket_timeout,
400 base::TimeDelta used_idle_socket_timeout) {
[email protected]c9d6a1d2009-07-14 16:15:20401 DCHECK(!pool_.get());
[email protected]17a0c6c2009-08-04 00:07:04402 connect_job_factory_ = new TestConnectJobFactory(&client_socket_factory_);
[email protected]211d21722009-07-22 15:48:53403 pool_ = new TestClientSocketPool(max_sockets,
404 max_sockets_per_group,
[email protected]9bf28db2009-08-29 01:35:16405 unused_idle_socket_timeout,
406 used_idle_socket_timeout,
[email protected]c9d6a1d2009-07-14 16:15:20407 connect_job_factory_);
408 }
[email protected]f6d1d6eb2009-06-24 20:16:09409
[email protected]ac790b42009-12-02 04:31:31410 int StartRequest(const std::string& group_name,
411 net::RequestPriority priority) {
[email protected]7fc5b09a2010-02-27 00:07:38412 return StartRequestUsingPool<TestClientSocketPool, TestSocketParams>(
[email protected]a937a06d2009-08-19 21:19:24413 pool_.get(), group_name, priority, NULL);
[email protected]f6d1d6eb2009-06-24 20:16:09414 }
415
416 virtual void TearDown() {
[email protected]6b175382009-10-13 06:47:47417 // We post all of our delayed tasks with a 2ms delay. I.e. they don't
418 // actually become pending until 2ms after they have been created. In order
419 // to flush all tasks, we need to wait so that we know there are no
420 // soon-to-be-pending tasks waiting.
421 PlatformThread::Sleep(10);
422 MessageLoop::current()->RunAllPending();
423
[email protected]211d21722009-07-22 15:48:53424 // Need to delete |pool_| before we turn late binding back off. We also need
425 // to delete |requests_| because the pool is reference counted and requests
426 // keep reference to it.
427 // TODO(willchan): Remove this part when late binding becomes the default.
[email protected]5fc08e32009-07-15 17:09:57428 pool_ = NULL;
[email protected]211d21722009-07-22 15:48:53429 requests_.reset();
430
[email protected]75439d3b2009-07-23 22:11:17431 ClientSocketPoolTest::TearDown();
[email protected]f6d1d6eb2009-06-24 20:16:09432 }
433
[email protected]f6d1d6eb2009-06-24 20:16:09434 MockClientSocketFactory client_socket_factory_;
[email protected]17a0c6c2009-08-04 00:07:04435 TestConnectJobFactory* connect_job_factory_;
[email protected]c9d6a1d2009-07-14 16:15:20436 scoped_refptr<TestClientSocketPool> pool_;
[email protected]f6d1d6eb2009-06-24 20:16:09437};
438
[email protected]a937a06d2009-08-19 21:19:24439// Helper function which explicitly specifies the template parameters, since
440// the compiler will infer (in this case, incorrectly) that NULL is of type int.
441int InitHandle(ClientSocketHandle* handle,
442 const std::string& group_name,
[email protected]ac790b42009-12-02 04:31:31443 net::RequestPriority priority,
[email protected]a937a06d2009-08-19 21:19:24444 CompletionCallback* callback,
445 TestClientSocketPool* pool,
446 LoadLog* load_log) {
[email protected]7fc5b09a2010-02-27 00:07:38447 return handle->Init<TestSocketParams, TestClientSocketPool>(
[email protected]a937a06d2009-08-19 21:19:24448 group_name, NULL, priority, callback, pool, load_log);
449}
450
[email protected]974ebd62009-08-03 23:14:34451// Even though a timeout is specified, it doesn't time out on a synchronous
452// completion.
453TEST_F(ClientSocketPoolBaseTest, ConnectJob_NoTimeoutOnSynchronousCompletion) {
454 TestConnectJobDelegate delegate;
[email protected]a512f5982009-08-18 16:01:06455 ClientSocketHandle ignored;
[email protected]d80a4322009-08-14 07:07:49456 TestClientSocketPoolBase::Request request(
457 &ignored, NULL, kDefaultPriority, NULL, NULL);
[email protected]974ebd62009-08-03 23:14:34458 scoped_ptr<TestConnectJob> job(
459 new TestConnectJob(TestConnectJob::kMockJob,
[email protected]ec08bb22009-08-12 00:25:12460 "a",
[email protected]974ebd62009-08-03 23:14:34461 request,
462 base::TimeDelta::FromMicroseconds(1),
463 &delegate,
[email protected]fd7b7c92009-08-20 19:38:30464 &client_socket_factory_,
465 NULL));
[email protected]974ebd62009-08-03 23:14:34466 EXPECT_EQ(OK, job->Connect());
467}
468
469TEST_F(ClientSocketPoolBaseTest, ConnectJob_TimedOut) {
470 TestConnectJobDelegate delegate;
[email protected]a512f5982009-08-18 16:01:06471 ClientSocketHandle ignored;
[email protected]60c4c412009-11-06 19:59:36472 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
[email protected]d80a4322009-08-14 07:07:49473 TestClientSocketPoolBase::Request request(
474 &ignored, NULL, kDefaultPriority, NULL, NULL);
[email protected]974ebd62009-08-03 23:14:34475 // Deleted by TestConnectJobDelegate.
476 TestConnectJob* job =
477 new TestConnectJob(TestConnectJob::kMockPendingJob,
[email protected]ec08bb22009-08-12 00:25:12478 "a",
[email protected]974ebd62009-08-03 23:14:34479 request,
480 base::TimeDelta::FromMicroseconds(1),
481 &delegate,
[email protected]fd7b7c92009-08-20 19:38:30482 &client_socket_factory_,
483 log);
[email protected]974ebd62009-08-03 23:14:34484 ASSERT_EQ(ERR_IO_PENDING, job->Connect());
485 PlatformThread::Sleep(1);
486 EXPECT_EQ(ERR_TIMED_OUT, delegate.WaitForResult());
[email protected]fd7b7c92009-08-20 19:38:30487
[email protected]bf6c087a2009-12-21 20:45:10488 EXPECT_EQ(3u, log->entries().size());
[email protected]e9002a92010-01-29 07:10:46489 EXPECT_TRUE(LogContainsBeginEvent(
490 *log, 0, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
491 EXPECT_TRUE(LogContainsEvent(
492 *log, 1, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB_TIMED_OUT,
493 LoadLog::PHASE_NONE));
494 EXPECT_TRUE(LogContainsEndEvent(
495 *log, 2, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
[email protected]974ebd62009-08-03 23:14:34496}
497
[email protected]5fc08e32009-07-15 17:09:57498TEST_F(ClientSocketPoolBaseTest, BasicSynchronous) {
[email protected]211d21722009-07-22 15:48:53499 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:20500
[email protected]f6d1d6eb2009-06-24 20:16:09501 TestCompletionCallback callback;
[email protected]a512f5982009-08-18 16:01:06502 ClientSocketHandle handle;
[email protected]60c4c412009-11-06 19:59:36503 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
[email protected]a937a06d2009-08-19 21:19:24504 EXPECT_EQ(OK, InitHandle(&handle, "a", kDefaultPriority,
[email protected]fd7b7c92009-08-20 19:38:30505 &callback, pool_.get(), log));
[email protected]f6d1d6eb2009-06-24 20:16:09506 EXPECT_TRUE(handle.is_initialized());
507 EXPECT_TRUE(handle.socket());
[email protected]f6d1d6eb2009-06-24 20:16:09508 handle.Reset();
[email protected]fd7b7c92009-08-20 19:38:30509
[email protected]bf6c087a2009-12-21 20:45:10510 EXPECT_EQ(4u, log->entries().size());
[email protected]e9002a92010-01-29 07:10:46511 EXPECT_TRUE(LogContainsBeginEvent(*log, 0, LoadLog::TYPE_SOCKET_POOL));
512 EXPECT_TRUE(LogContainsBeginEvent(
513 *log, 1, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
514 EXPECT_TRUE(LogContainsEndEvent(
515 *log, 2, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
516 EXPECT_TRUE(LogContainsEndEvent(*log, 3, LoadLog::TYPE_SOCKET_POOL));
[email protected]f6d1d6eb2009-06-24 20:16:09517}
518
[email protected]ab838892009-06-30 18:49:05519TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) {
[email protected]211d21722009-07-22 15:48:53520 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:20521
[email protected]ab838892009-06-30 18:49:05522 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
[email protected]60c4c412009-11-06 19:59:36523 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
[email protected]a512f5982009-08-18 16:01:06524 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]3ae82302009-06-26 06:01:21525 EXPECT_EQ(ERR_CONNECTION_FAILED,
[email protected]a937a06d2009-08-19 21:19:24526 InitHandle(req.handle(), "a", kDefaultPriority, &req,
[email protected]fd7b7c92009-08-20 19:38:30527 pool_.get(), log));
528
[email protected]bf6c087a2009-12-21 20:45:10529 EXPECT_EQ(4u, log->entries().size());
[email protected]e9002a92010-01-29 07:10:46530 EXPECT_TRUE(LogContainsBeginEvent(*log, 0, LoadLog::TYPE_SOCKET_POOL));
531 EXPECT_TRUE(LogContainsBeginEvent(
532 *log, 1, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
533 EXPECT_TRUE(LogContainsEndEvent(
534 *log, 2, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
535 EXPECT_TRUE(LogContainsEndEvent(*log, 3, LoadLog::TYPE_SOCKET_POOL));
[email protected]f6d1d6eb2009-06-24 20:16:09536}
537
[email protected]211d21722009-07-22 15:48:53538TEST_F(ClientSocketPoolBaseTest, TotalLimit) {
539 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
540
[email protected]fd7b7c92009-08-20 19:38:30541 // TODO(eroman): Check that the LoadLog contains this event.
542
[email protected]211d21722009-07-22 15:48:53543 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
544 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
545 EXPECT_EQ(OK, StartRequest("c", kDefaultPriority));
546 EXPECT_EQ(OK, StartRequest("d", kDefaultPriority));
547
548 EXPECT_EQ(static_cast<int>(requests_.size()),
549 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17550 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53551
552 EXPECT_EQ(ERR_IO_PENDING, StartRequest("e", kDefaultPriority));
553 EXPECT_EQ(ERR_IO_PENDING, StartRequest("f", kDefaultPriority));
554 EXPECT_EQ(ERR_IO_PENDING, StartRequest("g", kDefaultPriority));
555
556 ReleaseAllConnections(KEEP_ALIVE);
557
558 EXPECT_EQ(static_cast<int>(requests_.size()),
559 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17560 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53561
562 EXPECT_EQ(1, GetOrderOfRequest(1));
563 EXPECT_EQ(2, GetOrderOfRequest(2));
564 EXPECT_EQ(3, GetOrderOfRequest(3));
565 EXPECT_EQ(4, GetOrderOfRequest(4));
566 EXPECT_EQ(5, GetOrderOfRequest(5));
567 EXPECT_EQ(6, GetOrderOfRequest(6));
568 EXPECT_EQ(7, GetOrderOfRequest(7));
[email protected]75439d3b2009-07-23 22:11:17569
570 // Make sure we test order of all requests made.
571 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8));
[email protected]211d21722009-07-22 15:48:53572}
573
574TEST_F(ClientSocketPoolBaseTest, TotalLimitReachedNewGroup) {
575 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
576
[email protected]fd7b7c92009-08-20 19:38:30577 // TODO(eroman): Check that the LoadLog contains this event.
578
[email protected]211d21722009-07-22 15:48:53579 // Reach all limits: max total sockets, and max sockets per group.
580 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
581 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
582 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
583 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
584
585 EXPECT_EQ(static_cast<int>(requests_.size()),
586 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17587 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53588
589 // Now create a new group and verify that we don't starve it.
590 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kDefaultPriority));
591
592 ReleaseAllConnections(KEEP_ALIVE);
593
594 EXPECT_EQ(static_cast<int>(requests_.size()),
595 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17596 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53597
598 EXPECT_EQ(1, GetOrderOfRequest(1));
599 EXPECT_EQ(2, GetOrderOfRequest(2));
600 EXPECT_EQ(3, GetOrderOfRequest(3));
601 EXPECT_EQ(4, GetOrderOfRequest(4));
602 EXPECT_EQ(5, GetOrderOfRequest(5));
[email protected]75439d3b2009-07-23 22:11:17603
604 // Make sure we test order of all requests made.
605 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(6));
[email protected]211d21722009-07-22 15:48:53606}
607
608TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsPriority) {
609 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
610
[email protected]ac790b42009-12-02 04:31:31611 EXPECT_EQ(OK, StartRequest("b", LOWEST));
612 EXPECT_EQ(OK, StartRequest("a", MEDIUM));
613 EXPECT_EQ(OK, StartRequest("b", HIGHEST));
614 EXPECT_EQ(OK, StartRequest("a", LOWEST));
[email protected]211d21722009-07-22 15:48:53615
616 EXPECT_EQ(static_cast<int>(requests_.size()),
617 client_socket_factory_.allocation_count());
618
[email protected]ac790b42009-12-02 04:31:31619 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", LOWEST));
620 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
621 EXPECT_EQ(ERR_IO_PENDING, StartRequest("b", HIGHEST));
[email protected]211d21722009-07-22 15:48:53622
623 ReleaseAllConnections(KEEP_ALIVE);
624
625 // We're re-using one socket for group "a", and one for "b".
626 EXPECT_EQ(static_cast<int>(requests_.size()) - 2,
627 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17628 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53629
630 // First 4 requests don't have to wait, and finish in order.
631 EXPECT_EQ(1, GetOrderOfRequest(1));
632 EXPECT_EQ(2, GetOrderOfRequest(2));
633 EXPECT_EQ(3, GetOrderOfRequest(3));
634 EXPECT_EQ(4, GetOrderOfRequest(4));
635
[email protected]ac790b42009-12-02 04:31:31636 // Request ("b", HIGHEST) has the highest priority, then ("a", MEDIUM),
637 // and then ("c", LOWEST).
[email protected]211d21722009-07-22 15:48:53638 EXPECT_EQ(7, GetOrderOfRequest(5));
639 EXPECT_EQ(6, GetOrderOfRequest(6));
640 EXPECT_EQ(5, GetOrderOfRequest(7));
[email protected]75439d3b2009-07-23 22:11:17641
642 // Make sure we test order of all requests made.
643 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8));
[email protected]211d21722009-07-22 15:48:53644}
645
646TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsGroupLimit) {
647 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
648
[email protected]ac790b42009-12-02 04:31:31649 EXPECT_EQ(OK, StartRequest("a", LOWEST));
650 EXPECT_EQ(OK, StartRequest("a", LOW));
651 EXPECT_EQ(OK, StartRequest("b", HIGHEST));
652 EXPECT_EQ(OK, StartRequest("b", MEDIUM));
[email protected]211d21722009-07-22 15:48:53653
654 EXPECT_EQ(static_cast<int>(requests_.size()),
655 client_socket_factory_.allocation_count());
656
[email protected]ac790b42009-12-02 04:31:31657 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", MEDIUM));
658 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW));
659 EXPECT_EQ(ERR_IO_PENDING, StartRequest("b", HIGHEST));
[email protected]211d21722009-07-22 15:48:53660
661 ReleaseAllConnections(KEEP_ALIVE);
662
663 // We're re-using one socket for group "a", and one for "b".
664 EXPECT_EQ(static_cast<int>(requests_.size()) - 2,
665 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17666 EXPECT_EQ(requests_.size() - kDefaultMaxSockets, completion_count_);
[email protected]211d21722009-07-22 15:48:53667
668 // First 4 requests don't have to wait, and finish in order.
669 EXPECT_EQ(1, GetOrderOfRequest(1));
670 EXPECT_EQ(2, GetOrderOfRequest(2));
671 EXPECT_EQ(3, GetOrderOfRequest(3));
672 EXPECT_EQ(4, GetOrderOfRequest(4));
673
674 // Request ("b", 7) has the highest priority, but we can't make new socket for
675 // group "b", because it has reached the per-group limit. Then we make
676 // socket for ("c", 6), because it has higher priority than ("a", 4),
677 // and we still can't make a socket for group "b".
678 EXPECT_EQ(5, GetOrderOfRequest(5));
679 EXPECT_EQ(6, GetOrderOfRequest(6));
680 EXPECT_EQ(7, GetOrderOfRequest(7));
[email protected]75439d3b2009-07-23 22:11:17681
682 // Make sure we test order of all requests made.
683 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8));
[email protected]211d21722009-07-22 15:48:53684}
685
686// Make sure that we count connecting sockets against the total limit.
687TEST_F(ClientSocketPoolBaseTest, TotalLimitCountsConnectingSockets) {
688 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
689
690 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
691 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
692 EXPECT_EQ(OK, StartRequest("c", kDefaultPriority));
693
694 // Create one asynchronous request.
695 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
696 EXPECT_EQ(ERR_IO_PENDING, StartRequest("d", kDefaultPriority));
697
[email protected]6b175382009-10-13 06:47:47698 // We post all of our delayed tasks with a 2ms delay. I.e. they don't
699 // actually become pending until 2ms after they have been created. In order
700 // to flush all tasks, we need to wait so that we know there are no
701 // soon-to-be-pending tasks waiting.
702 PlatformThread::Sleep(10);
703 MessageLoop::current()->RunAllPending();
704
[email protected]211d21722009-07-22 15:48:53705 // The next synchronous request should wait for its turn.
706 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
707 EXPECT_EQ(ERR_IO_PENDING, StartRequest("e", kDefaultPriority));
708
709 ReleaseAllConnections(KEEP_ALIVE);
710
711 EXPECT_EQ(static_cast<int>(requests_.size()),
712 client_socket_factory_.allocation_count());
713
714 EXPECT_EQ(1, GetOrderOfRequest(1));
715 EXPECT_EQ(2, GetOrderOfRequest(2));
716 EXPECT_EQ(3, GetOrderOfRequest(3));
717 EXPECT_EQ(4, GetOrderOfRequest(4));
[email protected]75439d3b2009-07-23 22:11:17718 EXPECT_EQ(5, GetOrderOfRequest(5));
719
720 // Make sure we test order of all requests made.
721 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(6));
[email protected]211d21722009-07-22 15:48:53722}
723
724// Inside ClientSocketPoolBase we have a may_have_stalled_group flag,
725// which tells it to use more expensive, but accurate, group selection
726// algorithm. Make sure it doesn't get stuck in the "on" state.
727TEST_F(ClientSocketPoolBaseTest, MayHaveStalledGroupReset) {
728 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
729
730 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
731
732 // Reach group socket limit.
733 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
734 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
735 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
736
737 // Reach total limit, but don't request more sockets.
738 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
739 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
740 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
741
742 // Request one more socket while we are at the maximum sockets limit.
743 // This should flip the may_have_stalled_group flag.
744 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kDefaultPriority));
745 EXPECT_TRUE(pool_->base()->may_have_stalled_group());
746
747 // After releasing first connection for "a", we're still at the
748 // maximum sockets limit, but every group's pending queue is empty,
749 // so we reset the flag.
750 EXPECT_TRUE(ReleaseOneConnection(KEEP_ALIVE));
751 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
752
753 // Requesting additional socket while at the total limit should
754 // flip the flag back to "on".
755 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kDefaultPriority));
756 EXPECT_TRUE(pool_->base()->may_have_stalled_group());
757
758 // We'll request one more socket to verify that we don't reset the flag
759 // too eagerly.
760 EXPECT_EQ(ERR_IO_PENDING, StartRequest("d", kDefaultPriority));
761 EXPECT_TRUE(pool_->base()->may_have_stalled_group());
762
763 // We're at the maximum socket limit, and still have one request pending
764 // for "d". Flag should be "on".
765 EXPECT_TRUE(ReleaseOneConnection(KEEP_ALIVE));
766 EXPECT_TRUE(pool_->base()->may_have_stalled_group());
767
768 // Now every group's pending queue should be empty again.
769 EXPECT_TRUE(ReleaseOneConnection(KEEP_ALIVE));
770 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
771
772 ReleaseAllConnections(KEEP_ALIVE);
773 EXPECT_FALSE(pool_->base()->may_have_stalled_group());
774}
775
[email protected]ab838892009-06-30 18:49:05776TEST_F(ClientSocketPoolBaseTest, PendingRequests) {
[email protected]211d21722009-07-22 15:48:53777 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09778
[email protected]c9d6a1d2009-07-14 16:15:20779 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
780 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
[email protected]ac790b42009-12-02 04:31:31781 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
782 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
783 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST));
784 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW));
785 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
[email protected]f6d1d6eb2009-06-24 20:16:09786
[email protected]c9d6a1d2009-07-14 16:15:20787 ReleaseAllConnections(KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09788
[email protected]c9d6a1d2009-07-14 16:15:20789 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
790 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17791 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup, completion_count_);
[email protected]f6d1d6eb2009-06-24 20:16:09792
[email protected]c9d6a1d2009-07-14 16:15:20793 EXPECT_EQ(1, GetOrderOfRequest(1));
794 EXPECT_EQ(2, GetOrderOfRequest(2));
795 EXPECT_EQ(6, GetOrderOfRequest(3));
796 EXPECT_EQ(4, GetOrderOfRequest(4));
797 EXPECT_EQ(3, GetOrderOfRequest(5));
798 EXPECT_EQ(5, GetOrderOfRequest(6));
799 EXPECT_EQ(7, GetOrderOfRequest(7));
[email protected]75439d3b2009-07-23 22:11:17800
801 // Make sure we test order of all requests made.
802 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8));
[email protected]f6d1d6eb2009-06-24 20:16:09803}
804
[email protected]ab838892009-06-30 18:49:05805TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) {
[email protected]211d21722009-07-22 15:48:53806 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09807
[email protected]c9d6a1d2009-07-14 16:15:20808 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
809 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
[email protected]ac790b42009-12-02 04:31:31810 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
811 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
812 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST));
813 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW));
814 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
[email protected]f6d1d6eb2009-06-24 20:16:09815
[email protected]c9d6a1d2009-07-14 16:15:20816 ReleaseAllConnections(NO_KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09817
[email protected]c9d6a1d2009-07-14 16:15:20818 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i)
819 EXPECT_EQ(OK, requests_[i]->WaitForResult());
820
821 EXPECT_EQ(static_cast<int>(requests_.size()),
822 client_socket_factory_.allocation_count());
[email protected]75439d3b2009-07-23 22:11:17823 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup, completion_count_);
[email protected]f6d1d6eb2009-06-24 20:16:09824}
825
826// This test will start up a RequestSocket() and then immediately Cancel() it.
[email protected]ab838892009-06-30 18:49:05827// The pending connect job will be cancelled and should not call back into
828// ClientSocketPoolBase.
829TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) {
[email protected]211d21722009-07-22 15:48:53830 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:20831
[email protected]ab838892009-06-30 18:49:05832 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:06833 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]ab838892009-06-30 18:49:05834 EXPECT_EQ(ERR_IO_PENDING,
[email protected]a937a06d2009-08-19 21:19:24835 InitHandle(req.handle(), "a", kDefaultPriority, &req,
836 pool_.get(), NULL));
[email protected]a6c59f62009-07-29 16:33:33837 req.handle()->Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09838}
839
[email protected]ab838892009-06-30 18:49:05840TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) {
[email protected]211d21722009-07-22 15:48:53841 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:20842
[email protected]ab838892009-06-30 18:49:05843 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:06844 ClientSocketHandle handle;
[email protected]f6d1d6eb2009-06-24 20:16:09845 TestCompletionCallback callback;
[email protected]a512f5982009-08-18 16:01:06846 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]f6d1d6eb2009-06-24 20:16:09847
[email protected]ab838892009-06-30 18:49:05848 EXPECT_EQ(ERR_IO_PENDING,
[email protected]a937a06d2009-08-19 21:19:24849 InitHandle(&handle, "a", kDefaultPriority, &callback,
850 pool_.get(), NULL));
[email protected]f6d1d6eb2009-06-24 20:16:09851
852 handle.Reset();
853
854 TestCompletionCallback callback2;
[email protected]ab838892009-06-30 18:49:05855 EXPECT_EQ(ERR_IO_PENDING,
[email protected]a937a06d2009-08-19 21:19:24856 InitHandle(&handle, "a", kDefaultPriority, &callback2,
857 pool_.get(), NULL));
[email protected]f6d1d6eb2009-06-24 20:16:09858
859 EXPECT_EQ(OK, callback2.WaitForResult());
860 EXPECT_FALSE(callback.have_result());
861
862 handle.Reset();
863}
864
[email protected]ab838892009-06-30 18:49:05865TEST_F(ClientSocketPoolBaseTest, CancelRequest) {
[email protected]211d21722009-07-22 15:48:53866 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09867
[email protected]c9d6a1d2009-07-14 16:15:20868 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
869 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
[email protected]ac790b42009-12-02 04:31:31870 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
871 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
872 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST));
873 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW));
874 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
[email protected]f6d1d6eb2009-06-24 20:16:09875
876 // Cancel a request.
[email protected]c9d6a1d2009-07-14 16:15:20877 size_t index_to_cancel = kDefaultMaxSocketsPerGroup + 2;
[email protected]a6c59f62009-07-29 16:33:33878 EXPECT_FALSE(requests_[index_to_cancel]->handle()->is_initialized());
879 requests_[index_to_cancel]->handle()->Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09880
[email protected]c9d6a1d2009-07-14 16:15:20881 ReleaseAllConnections(KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09882
[email protected]c9d6a1d2009-07-14 16:15:20883 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
884 client_socket_factory_.allocation_count());
885 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup - 1,
[email protected]75439d3b2009-07-23 22:11:17886 completion_count_);
[email protected]f6d1d6eb2009-06-24 20:16:09887
[email protected]c9d6a1d2009-07-14 16:15:20888 EXPECT_EQ(1, GetOrderOfRequest(1));
889 EXPECT_EQ(2, GetOrderOfRequest(2));
890 EXPECT_EQ(5, GetOrderOfRequest(3));
891 EXPECT_EQ(3, GetOrderOfRequest(4));
892 EXPECT_EQ(kRequestNotFound, GetOrderOfRequest(5)); // Canceled request.
893 EXPECT_EQ(4, GetOrderOfRequest(6));
894 EXPECT_EQ(6, GetOrderOfRequest(7));
[email protected]75439d3b2009-07-23 22:11:17895
896 // Make sure we test order of all requests made.
897 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8));
[email protected]f6d1d6eb2009-06-24 20:16:09898}
899
900class RequestSocketCallback : public CallbackRunner< Tuple1<int> > {
901 public:
[email protected]2ab05b52009-07-01 23:57:58902 RequestSocketCallback(ClientSocketHandle* handle,
[email protected]a937a06d2009-08-19 21:19:24903 TestClientSocketPool* pool,
[email protected]2ab05b52009-07-01 23:57:58904 TestConnectJobFactory* test_connect_job_factory,
905 TestConnectJob::JobType next_job_type)
[email protected]f6d1d6eb2009-06-24 20:16:09906 : handle_(handle),
[email protected]a512f5982009-08-18 16:01:06907 pool_(pool),
[email protected]2ab05b52009-07-01 23:57:58908 within_callback_(false),
909 test_connect_job_factory_(test_connect_job_factory),
910 next_job_type_(next_job_type) {}
[email protected]f6d1d6eb2009-06-24 20:16:09911
912 virtual void RunWithParams(const Tuple1<int>& params) {
913 callback_.RunWithParams(params);
914 ASSERT_EQ(OK, params.a);
915
916 if (!within_callback_) {
[email protected]2ab05b52009-07-01 23:57:58917 test_connect_job_factory_->set_job_type(next_job_type_);
[email protected]5edbf8d2010-01-13 18:44:11918
919 // Don't allow reuse of the socket. Disconnect it and then release it and
920 // run through the MessageLoop once to get it completely released.
921 handle_->socket()->Disconnect();
[email protected]f6d1d6eb2009-06-24 20:16:09922 handle_->Reset();
[email protected]5edbf8d2010-01-13 18:44:11923 {
924 MessageLoop::ScopedNestableTaskAllower nestable(
925 MessageLoop::current());
926 MessageLoop::current()->RunAllPending();
927 }
[email protected]f6d1d6eb2009-06-24 20:16:09928 within_callback_ = true;
[email protected]6b175382009-10-13 06:47:47929 TestCompletionCallback next_job_callback;
[email protected]a937a06d2009-08-19 21:19:24930 int rv = InitHandle(
[email protected]6b175382009-10-13 06:47:47931 handle_, "a", kDefaultPriority, &next_job_callback, pool_.get(),
932 NULL);
[email protected]2ab05b52009-07-01 23:57:58933 switch (next_job_type_) {
934 case TestConnectJob::kMockJob:
935 EXPECT_EQ(OK, rv);
936 break;
937 case TestConnectJob::kMockPendingJob:
938 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]6b175382009-10-13 06:47:47939
940 // For pending jobs, wait for new socket to be created. This makes
941 // sure there are no more pending operations nor any unclosed sockets
942 // when the test finishes.
943 // We need to give it a little bit of time to run, so that all the
944 // operations that happen on timers (e.g. cleanup of idle
945 // connections) can execute.
[email protected]5edbf8d2010-01-13 18:44:11946 {
947 MessageLoop::ScopedNestableTaskAllower nestable(
948 MessageLoop::current());
949 PlatformThread::Sleep(10);
950 EXPECT_EQ(OK, next_job_callback.WaitForResult());
951 }
[email protected]2ab05b52009-07-01 23:57:58952 break;
953 default:
954 FAIL() << "Unexpected job type: " << next_job_type_;
955 break;
956 }
[email protected]f6d1d6eb2009-06-24 20:16:09957 }
958 }
959
960 int WaitForResult() {
961 return callback_.WaitForResult();
962 }
963
964 private:
965 ClientSocketHandle* const handle_;
[email protected]a937a06d2009-08-19 21:19:24966 const scoped_refptr<TestClientSocketPool> pool_;
[email protected]f6d1d6eb2009-06-24 20:16:09967 bool within_callback_;
[email protected]2ab05b52009-07-01 23:57:58968 TestConnectJobFactory* const test_connect_job_factory_;
969 TestConnectJob::JobType next_job_type_;
[email protected]f6d1d6eb2009-06-24 20:16:09970 TestCompletionCallback callback_;
971};
972
[email protected]2ab05b52009-07-01 23:57:58973TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) {
[email protected]211d21722009-07-22 15:48:53974 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:20975
[email protected]0b7648c2009-07-06 20:14:01976 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:06977 ClientSocketHandle handle;
[email protected]2ab05b52009-07-01 23:57:58978 RequestSocketCallback callback(
[email protected]a512f5982009-08-18 16:01:06979 &handle, pool_.get(), connect_job_factory_,
980 TestConnectJob::kMockPendingJob);
[email protected]a937a06d2009-08-19 21:19:24981 int rv = InitHandle(&handle, "a", kDefaultPriority, &callback,
982 pool_.get(), NULL);
[email protected]f6d1d6eb2009-06-24 20:16:09983 ASSERT_EQ(ERR_IO_PENDING, rv);
984
985 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ab05b52009-07-01 23:57:58986}
[email protected]f6d1d6eb2009-06-24 20:16:09987
[email protected]2ab05b52009-07-01 23:57:58988TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) {
[email protected]211d21722009-07-22 15:48:53989 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:20990
[email protected]0b7648c2009-07-06 20:14:01991 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:06992 ClientSocketHandle handle;
[email protected]2ab05b52009-07-01 23:57:58993 RequestSocketCallback callback(
[email protected]a512f5982009-08-18 16:01:06994 &handle, pool_.get(), connect_job_factory_, TestConnectJob::kMockJob);
[email protected]a937a06d2009-08-19 21:19:24995 int rv = InitHandle(&handle, "a", kDefaultPriority, &callback,
996 pool_.get(), NULL);
[email protected]2ab05b52009-07-01 23:57:58997 ASSERT_EQ(ERR_IO_PENDING, rv);
998
999 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]f6d1d6eb2009-06-24 20:16:091000}
1001
1002// Make sure that pending requests get serviced after active requests get
1003// cancelled.
[email protected]ab838892009-06-30 18:49:051004TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) {
[email protected]211d21722009-07-22 15:48:531005 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:201006
[email protected]0b7648c2009-07-06 20:14:011007 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:091008
[email protected]c9d6a1d2009-07-14 16:15:201009 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1010 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1011 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1012 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1013 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1014 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1015 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
[email protected]f6d1d6eb2009-06-24 20:16:091016
[email protected]c9d6a1d2009-07-14 16:15:201017 // Now, kDefaultMaxSocketsPerGroup requests should be active.
1018 // Let's cancel them.
1019 for (int i = 0; i < kDefaultMaxSocketsPerGroup; ++i) {
[email protected]a6c59f62009-07-29 16:33:331020 ASSERT_FALSE(requests_[i]->handle()->is_initialized());
1021 requests_[i]->handle()->Reset();
[email protected]f6d1d6eb2009-06-24 20:16:091022 }
1023
[email protected]f6d1d6eb2009-06-24 20:16:091024 // Let's wait for the rest to complete now.
[email protected]c9d6a1d2009-07-14 16:15:201025 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i) {
1026 EXPECT_EQ(OK, requests_[i]->WaitForResult());
[email protected]a6c59f62009-07-29 16:33:331027 requests_[i]->handle()->Reset();
[email protected]f6d1d6eb2009-06-24 20:16:091028 }
1029
[email protected]75439d3b2009-07-23 22:11:171030 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup, completion_count_);
[email protected]f6d1d6eb2009-06-24 20:16:091031}
1032
1033// Make sure that pending requests get serviced after active requests fail.
[email protected]ab838892009-06-30 18:49:051034TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) {
[email protected]211d21722009-07-22 15:48:531035 const size_t kMaxSockets = 5;
1036 CreatePool(kMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]c9d6a1d2009-07-14 16:15:201037
[email protected]0b7648c2009-07-06 20:14:011038 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]f6d1d6eb2009-06-24 20:16:091039
[email protected]211d21722009-07-22 15:48:531040 const size_t kNumberOfRequests = 2 * kDefaultMaxSocketsPerGroup + 1;
1041 ASSERT_LE(kNumberOfRequests, kMaxSockets); // Otherwise the test will hang.
[email protected]f6d1d6eb2009-06-24 20:16:091042
1043 // Queue up all the requests
[email protected]211d21722009-07-22 15:48:531044 for (size_t i = 0; i < kNumberOfRequests; ++i)
1045 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
[email protected]f6d1d6eb2009-06-24 20:16:091046
[email protected]211d21722009-07-22 15:48:531047 for (size_t i = 0; i < kNumberOfRequests; ++i)
1048 EXPECT_EQ(ERR_CONNECTION_FAILED, requests_[i]->WaitForResult());
[email protected]f6d1d6eb2009-06-24 20:16:091049}
1050
[email protected]5fc08e32009-07-15 17:09:571051TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestThenRequestSocket) {
[email protected]211d21722009-07-22 15:48:531052 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571053
1054 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1055
[email protected]a512f5982009-08-18 16:01:061056 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]a937a06d2009-08-19 21:19:241057 int rv = InitHandle(req.handle(), "a", kDefaultPriority, &req,
1058 pool_.get(), NULL);
[email protected]5fc08e32009-07-15 17:09:571059 EXPECT_EQ(ERR_IO_PENDING, rv);
1060
1061 // Cancel the active request.
[email protected]a6c59f62009-07-29 16:33:331062 req.handle()->Reset();
[email protected]5fc08e32009-07-15 17:09:571063
[email protected]a937a06d2009-08-19 21:19:241064 rv = InitHandle(req.handle(), "a", kDefaultPriority, &req,
1065 pool_.get(), NULL);
[email protected]5fc08e32009-07-15 17:09:571066 EXPECT_EQ(ERR_IO_PENDING, rv);
1067 EXPECT_EQ(OK, req.WaitForResult());
1068
[email protected]a6c59f62009-07-29 16:33:331069 EXPECT_FALSE(req.handle()->is_reused());
[email protected]75439d3b2009-07-23 22:11:171070 EXPECT_EQ(1U, completion_count_);
[email protected]5fc08e32009-07-15 17:09:571071 EXPECT_EQ(2, client_socket_factory_.allocation_count());
1072}
1073
[email protected]2b7523d2009-07-29 20:29:231074// Regression test for http://crbug.com/17985.
1075TEST_F(ClientSocketPoolBaseTest, GroupWithPendingRequestsIsNotEmpty) {
1076 const int kMaxSockets = 3;
1077 const int kMaxSocketsPerGroup = 2;
1078 CreatePool(kMaxSockets, kMaxSocketsPerGroup);
1079
[email protected]ac790b42009-12-02 04:31:311080 const RequestPriority kHighPriority = HIGHEST;
[email protected]2b7523d2009-07-29 20:29:231081
1082 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
1083 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
1084
1085 // This is going to be a pending request in an otherwise empty group.
1086 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1087
1088 // Reach the maximum socket limit.
1089 EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
1090
1091 // Create a stalled group with high priorities.
1092 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kHighPriority));
1093 EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kHighPriority));
1094 EXPECT_TRUE(pool_->base()->may_have_stalled_group());
1095
1096 // Release the first two sockets from "a", which will make room
1097 // for requests from "c". After that "a" will have no active sockets
1098 // and one pending request.
1099 EXPECT_TRUE(ReleaseOneConnection(KEEP_ALIVE));
1100 EXPECT_TRUE(ReleaseOneConnection(KEEP_ALIVE));
1101
1102 // Closing idle sockets should not get us into trouble, but in the bug
1103 // we were hitting a CHECK here.
1104 EXPECT_EQ(2, pool_->IdleSocketCountInGroup("a"));
1105 pool_->CloseIdleSockets();
1106 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
1107}
1108
[email protected]4d3b05d2010-01-27 21:27:291109TEST_F(ClientSocketPoolBaseTest, BasicAsynchronous) {
[email protected]211d21722009-07-22 15:48:531110 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571111
1112 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:061113 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]60c4c412009-11-06 19:59:361114 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
[email protected]ac790b42009-12-02 04:31:311115 int rv = InitHandle(req.handle(), "a", LOWEST, &req, pool_.get(), log);
[email protected]5fc08e32009-07-15 17:09:571116 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a6c59f62009-07-29 16:33:331117 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", req.handle()));
[email protected]5fc08e32009-07-15 17:09:571118 EXPECT_EQ(OK, req.WaitForResult());
[email protected]a6c59f62009-07-29 16:33:331119 EXPECT_TRUE(req.handle()->is_initialized());
1120 EXPECT_TRUE(req.handle()->socket());
1121 req.handle()->Reset();
[email protected]fd7b7c92009-08-20 19:38:301122
[email protected]fd4fe0b2010-02-08 23:02:151123 EXPECT_EQ(4u, log->entries().size());
[email protected]e9002a92010-01-29 07:10:461124 EXPECT_TRUE(LogContainsBeginEvent(*log, 0, LoadLog::TYPE_SOCKET_POOL));
1125 EXPECT_TRUE(LogContainsBeginEvent(
[email protected]fd4fe0b2010-02-08 23:02:151126 *log, 1, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
[email protected]e9002a92010-01-29 07:10:461127 EXPECT_TRUE(LogContainsEndEvent(
[email protected]fd4fe0b2010-02-08 23:02:151128 *log, 2, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
[email protected]e9002a92010-01-29 07:10:461129 EXPECT_TRUE(LogContainsEndEvent(
[email protected]fd4fe0b2010-02-08 23:02:151130 *log, 3, LoadLog::TYPE_SOCKET_POOL));
[email protected]5fc08e32009-07-15 17:09:571131}
1132
[email protected]4d3b05d2010-01-27 21:27:291133TEST_F(ClientSocketPoolBaseTest,
[email protected]5fc08e32009-07-15 17:09:571134 InitConnectionAsynchronousFailure) {
[email protected]211d21722009-07-22 15:48:531135 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571136
1137 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]a512f5982009-08-18 16:01:061138 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]60c4c412009-11-06 19:59:361139 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
[email protected]5fc08e32009-07-15 17:09:571140 EXPECT_EQ(ERR_IO_PENDING,
[email protected]a937a06d2009-08-19 21:19:241141 InitHandle(req.handle(), "a", kDefaultPriority, &req,
[email protected]fd7b7c92009-08-20 19:38:301142 pool_.get(), log));
[email protected]a6c59f62009-07-29 16:33:331143 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", req.handle()));
[email protected]5fc08e32009-07-15 17:09:571144 EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult());
[email protected]fd7b7c92009-08-20 19:38:301145
[email protected]fd4fe0b2010-02-08 23:02:151146 EXPECT_EQ(4u, log->entries().size());
[email protected]e9002a92010-01-29 07:10:461147 EXPECT_TRUE(LogContainsBeginEvent(*log, 0, LoadLog::TYPE_SOCKET_POOL));
1148 EXPECT_TRUE(LogContainsBeginEvent(
[email protected]fd4fe0b2010-02-08 23:02:151149 *log, 1, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
[email protected]e9002a92010-01-29 07:10:461150 EXPECT_TRUE(LogContainsEndEvent(
[email protected]fd4fe0b2010-02-08 23:02:151151 *log, 2, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
1152 EXPECT_TRUE(LogContainsEndEvent(*log, 3, LoadLog::TYPE_SOCKET_POOL));
[email protected]5fc08e32009-07-15 17:09:571153}
1154
[email protected]4d3b05d2010-01-27 21:27:291155TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) {
[email protected]211d21722009-07-22 15:48:531156 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571157
1158 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]a512f5982009-08-18 16:01:061159 TestSocketRequest req(&request_order_, &completion_count_);
1160 TestSocketRequest req2(&request_order_, &completion_count_);
[email protected]5fc08e32009-07-15 17:09:571161
[email protected]60c4c412009-11-06 19:59:361162 scoped_refptr<LoadLog> log1(new LoadLog(LoadLog::kUnbounded));
[email protected]5fc08e32009-07-15 17:09:571163 EXPECT_EQ(ERR_IO_PENDING,
[email protected]a937a06d2009-08-19 21:19:241164 InitHandle(req.handle(), "a", kDefaultPriority, &req,
[email protected]fd7b7c92009-08-20 19:38:301165 pool_.get(), log1));
[email protected]60c4c412009-11-06 19:59:361166 scoped_refptr<LoadLog> log2(new LoadLog(LoadLog::kUnbounded));
[email protected]5fc08e32009-07-15 17:09:571167 EXPECT_EQ(ERR_IO_PENDING,
[email protected]a937a06d2009-08-19 21:19:241168 InitHandle(req2.handle(), "a", kDefaultPriority, &req2,
[email protected]fd7b7c92009-08-20 19:38:301169 pool_.get(), log2));
[email protected]5fc08e32009-07-15 17:09:571170
[email protected]a6c59f62009-07-29 16:33:331171 req.handle()->Reset();
[email protected]5fc08e32009-07-15 17:09:571172
[email protected]fd4fe0b2010-02-08 23:02:151173 EXPECT_EQ(3u, log1->entries().size());
[email protected]e9002a92010-01-29 07:10:461174 EXPECT_TRUE(LogContainsBeginEvent(*log1, 0, LoadLog::TYPE_SOCKET_POOL));
[email protected]e9002a92010-01-29 07:10:461175 EXPECT_TRUE(LogContainsEvent(
[email protected]fd4fe0b2010-02-08 23:02:151176 *log1, 1, LoadLog::TYPE_CANCELLED, LoadLog::PHASE_NONE));
1177 EXPECT_TRUE(LogContainsEndEvent(*log1, 2, LoadLog::TYPE_SOCKET_POOL));
[email protected]fd7b7c92009-08-20 19:38:301178
1179 // At this point, request 2 is just waiting for the connect job to finish.
[email protected]fd4fe0b2010-02-08 23:02:151180 EXPECT_EQ(1u, log2->entries().size());
[email protected]e9002a92010-01-29 07:10:461181 EXPECT_TRUE(LogContainsBeginEvent(*log2, 0, LoadLog::TYPE_SOCKET_POOL));
[email protected]fd7b7c92009-08-20 19:38:301182
[email protected]5fc08e32009-07-15 17:09:571183 EXPECT_EQ(OK, req2.WaitForResult());
[email protected]a6c59f62009-07-29 16:33:331184 req2.handle()->Reset();
[email protected]fd7b7c92009-08-20 19:38:301185
1186 // Now request 2 has actually finished.
[email protected]fd4fe0b2010-02-08 23:02:151187 EXPECT_EQ(4u, log2->entries().size());
[email protected]e9002a92010-01-29 07:10:461188 EXPECT_TRUE(LogContainsBeginEvent(*log2, 0, LoadLog::TYPE_SOCKET_POOL));
1189 EXPECT_TRUE(LogContainsBeginEvent(
[email protected]fd4fe0b2010-02-08 23:02:151190 *log2, 1, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
[email protected]e9002a92010-01-29 07:10:461191 EXPECT_TRUE(LogContainsEndEvent(
[email protected]fd4fe0b2010-02-08 23:02:151192 *log2, 2, LoadLog::TYPE_SOCKET_POOL_CONNECT_JOB));
1193 EXPECT_TRUE(LogContainsEndEvent(*log2, 3, LoadLog::TYPE_SOCKET_POOL));
[email protected]fd7b7c92009-08-20 19:38:301194
[email protected]5fc08e32009-07-15 17:09:571195}
1196
[email protected]4d3b05d2010-01-27 21:27:291197TEST_F(ClientSocketPoolBaseTest, CancelRequestLimitsJobs) {
[email protected]974ebd62009-08-03 23:14:341198 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
1199
[email protected]17a0c6c2009-08-04 00:07:041200 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1201
[email protected]ac790b42009-12-02 04:31:311202 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
1203 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOW));
1204 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
1205 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST));
[email protected]974ebd62009-08-03 23:14:341206
1207 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a"));
1208 requests_[2]->handle()->Reset();
1209 requests_[3]->handle()->Reset();
1210 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a"));
1211
1212 requests_[1]->handle()->Reset();
1213 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a"));
1214
1215 requests_[0]->handle()->Reset();
1216 EXPECT_EQ(kDefaultMaxSocketsPerGroup - 1, pool_->NumConnectJobsInGroup("a"));
1217}
1218
[email protected]5fc08e32009-07-15 17:09:571219// When requests and ConnectJobs are not coupled, the request will get serviced
1220// by whatever comes first.
[email protected]4d3b05d2010-01-27 21:27:291221TEST_F(ClientSocketPoolBaseTest, ReleaseSockets) {
[email protected]211d21722009-07-22 15:48:531222 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571223
1224 // Start job 1 (async OK)
[email protected]b59ff372009-07-15 22:04:321225 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]5fc08e32009-07-15 17:09:571226
[email protected]a512f5982009-08-18 16:01:061227 TestSocketRequest req1(&request_order_, &completion_count_);
[email protected]a937a06d2009-08-19 21:19:241228 int rv = InitHandle(req1.handle(), "a", kDefaultPriority,
1229 &req1, pool_.get(), NULL);
[email protected]5fc08e32009-07-15 17:09:571230 EXPECT_EQ(ERR_IO_PENDING, rv);
1231 EXPECT_EQ(OK, req1.WaitForResult());
1232
1233 // Job 1 finished OK. Start job 2 (also async OK). Request 3 is pending
1234 // without a job.
1235 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
1236
[email protected]a512f5982009-08-18 16:01:061237 TestSocketRequest req2(&request_order_, &completion_count_);
[email protected]a937a06d2009-08-19 21:19:241238 rv = InitHandle(req2.handle(), "a", kDefaultPriority, &req2,
1239 pool_.get(), NULL);
[email protected]5fc08e32009-07-15 17:09:571240 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a512f5982009-08-18 16:01:061241 TestSocketRequest req3(&request_order_, &completion_count_);
[email protected]a937a06d2009-08-19 21:19:241242 rv = InitHandle(
1243 req3.handle(), "a", kDefaultPriority, &req3, pool_.get(), NULL);
[email protected]5fc08e32009-07-15 17:09:571244 EXPECT_EQ(ERR_IO_PENDING, rv);
1245
1246 // Both Requests 2 and 3 are pending. We release socket 1 which should
1247 // service request 2. Request 3 should still be waiting.
[email protected]a6c59f62009-07-29 16:33:331248 req1.handle()->Reset();
[email protected]5fc08e32009-07-15 17:09:571249 MessageLoop::current()->RunAllPending(); // Run the DoReleaseSocket()
[email protected]a6c59f62009-07-29 16:33:331250 ASSERT_TRUE(req2.handle()->socket());
[email protected]5fc08e32009-07-15 17:09:571251 EXPECT_EQ(OK, req2.WaitForResult());
[email protected]a6c59f62009-07-29 16:33:331252 EXPECT_FALSE(req3.handle()->socket());
[email protected]5fc08e32009-07-15 17:09:571253
1254 // Signal job 2, which should service request 3.
1255
1256 client_socket_factory_.SignalJobs();
1257 EXPECT_EQ(OK, req3.WaitForResult());
1258
1259 ASSERT_EQ(3U, request_order_.size());
1260 EXPECT_EQ(&req1, request_order_[0]);
1261 EXPECT_EQ(&req2, request_order_[1]);
1262 EXPECT_EQ(&req3, request_order_[2]);
1263 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
1264}
1265
1266// The requests are not coupled to the jobs. So, the requests should finish in
1267// their priority / insertion order.
[email protected]4d3b05d2010-01-27 21:27:291268TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) {
[email protected]211d21722009-07-22 15:48:531269 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571270 // First two jobs are async.
[email protected]b59ff372009-07-15 22:04:321271 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]5fc08e32009-07-15 17:09:571272
[email protected]a512f5982009-08-18 16:01:061273 TestSocketRequest req1(&request_order_, &completion_count_);
[email protected]a937a06d2009-08-19 21:19:241274 int rv = InitHandle(
1275 req1.handle(), "a", kDefaultPriority, &req1, pool_.get(), NULL);
[email protected]5fc08e32009-07-15 17:09:571276 EXPECT_EQ(ERR_IO_PENDING, rv);
1277
[email protected]a512f5982009-08-18 16:01:061278 TestSocketRequest req2(&request_order_, &completion_count_);
[email protected]a937a06d2009-08-19 21:19:241279 rv = InitHandle(req2.handle(), "a", kDefaultPriority, &req2,
1280 pool_.get(), NULL);
[email protected]5fc08e32009-07-15 17:09:571281 EXPECT_EQ(ERR_IO_PENDING, rv);
1282
1283 // The pending job is sync.
[email protected]b59ff372009-07-15 22:04:321284 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
[email protected]5fc08e32009-07-15 17:09:571285
[email protected]a512f5982009-08-18 16:01:061286 TestSocketRequest req3(&request_order_, &completion_count_);
[email protected]a937a06d2009-08-19 21:19:241287 rv = InitHandle(
1288 req3.handle(), "a", kDefaultPriority, &req3, pool_.get(), NULL);
[email protected]5fc08e32009-07-15 17:09:571289 EXPECT_EQ(ERR_IO_PENDING, rv);
1290
1291 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult());
1292 EXPECT_EQ(OK, req2.WaitForResult());
1293 EXPECT_EQ(ERR_CONNECTION_FAILED, req3.WaitForResult());
1294
1295 ASSERT_EQ(3U, request_order_.size());
1296 EXPECT_EQ(&req1, request_order_[0]);
1297 EXPECT_EQ(&req2, request_order_[1]);
1298 EXPECT_EQ(&req3, request_order_[2]);
1299}
1300
[email protected]4d3b05d2010-01-27 21:27:291301TEST_F(ClientSocketPoolBaseTest, DISABLED_LoadState) {
[email protected]211d21722009-07-22 15:48:531302 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
[email protected]5fc08e32009-07-15 17:09:571303 connect_job_factory_->set_job_type(
[email protected]b59ff372009-07-15 22:04:321304 TestConnectJob::kMockAdvancingLoadStateJob);
[email protected]5fc08e32009-07-15 17:09:571305
[email protected]a512f5982009-08-18 16:01:061306 TestSocketRequest req1(&request_order_, &completion_count_);
[email protected]a937a06d2009-08-19 21:19:241307 int rv = InitHandle(
1308 req1.handle(), "a", kDefaultPriority, &req1, pool_.get(), NULL);
[email protected]5fc08e32009-07-15 17:09:571309 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a6c59f62009-07-29 16:33:331310 EXPECT_EQ(LOAD_STATE_IDLE, req1.handle()->GetLoadState());
[email protected]5fc08e32009-07-15 17:09:571311
1312 MessageLoop::current()->RunAllPending();
1313
[email protected]a512f5982009-08-18 16:01:061314 TestSocketRequest req2(&request_order_, &completion_count_);
[email protected]a937a06d2009-08-19 21:19:241315 rv = InitHandle(req2.handle(), "a", kDefaultPriority, &req2,
1316 pool_.get(), NULL);
[email protected]5fc08e32009-07-15 17:09:571317 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a6c59f62009-07-29 16:33:331318 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, req1.handle()->GetLoadState());
1319 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, req2.handle()->GetLoadState());
[email protected]5fc08e32009-07-15 17:09:571320}
1321
[email protected]4d3b05d2010-01-27 21:27:291322TEST_F(ClientSocketPoolBaseTest, CleanupTimedOutIdleSockets) {
[email protected]9bf28db2009-08-29 01:35:161323 CreatePoolWithIdleTimeouts(
1324 kDefaultMaxSockets, kDefaultMaxSocketsPerGroup,
1325 base::TimeDelta(), // Time out unused sockets immediately.
1326 base::TimeDelta::FromDays(1)); // Don't time out used sockets.
1327
1328 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1329
1330 // Startup two mock pending connect jobs, which will sit in the MessageLoop.
1331
1332 TestSocketRequest req(&request_order_, &completion_count_);
[email protected]ac790b42009-12-02 04:31:311333 int rv = InitHandle(req.handle(), "a", LOWEST, &req, pool_.get(), NULL);
[email protected]9bf28db2009-08-29 01:35:161334 EXPECT_EQ(ERR_IO_PENDING, rv);
1335 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", req.handle()));
1336
1337 TestSocketRequest req2(&request_order_, &completion_count_);
[email protected]ac790b42009-12-02 04:31:311338 rv = InitHandle(req2.handle(), "a", LOWEST, &req2, pool_.get(), NULL);
[email protected]9bf28db2009-08-29 01:35:161339 EXPECT_EQ(ERR_IO_PENDING, rv);
1340 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", req2.handle()));
1341
1342 // Cancel one of the requests. Wait for the other, which will get the first
1343 // job. Release the socket. Run the loop again to make sure the second
1344 // socket is sitting idle and the first one is released (since ReleaseSocket()
1345 // just posts a DoReleaseSocket() task).
1346
1347 req.handle()->Reset();
1348 EXPECT_EQ(OK, req2.WaitForResult());
1349 req2.handle()->Reset();
[email protected]6b175382009-10-13 06:47:471350
1351 // We post all of our delayed tasks with a 2ms delay. I.e. they don't
1352 // actually become pending until 2ms after they have been created. In order
1353 // to flush all tasks, we need to wait so that we know there are no
1354 // soon-to-be-pending tasks waiting.
1355 PlatformThread::Sleep(10);
[email protected]9bf28db2009-08-29 01:35:161356 MessageLoop::current()->RunAllPending();
1357
1358 ASSERT_EQ(2, pool_->IdleSocketCount());
[email protected]d3f66572009-09-09 22:38:041359
[email protected]9bf28db2009-08-29 01:35:161360 // Invoke the idle socket cleanup check. Only one socket should be left, the
1361 // used socket. Request it to make sure that it's used.
1362
1363 pool_->CleanupTimedOutIdleSockets();
[email protected]fd4fe0b2010-02-08 23:02:151364 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
1365 rv = InitHandle(req.handle(), "a", LOWEST, &req, pool_.get(), log);
[email protected]9bf28db2009-08-29 01:35:161366 EXPECT_EQ(OK, rv);
1367 EXPECT_TRUE(req.handle()->is_reused());
[email protected]fd4fe0b2010-02-08 23:02:151368 EXPECT_TRUE(LogContainsEntryWithType(
1369 *log, 1, LoadLog::Entry::TYPE_STRING_LITERAL))
1370 << LoadLogUtil::PrettyPrintAsEventTree(log);
[email protected]9bf28db2009-08-29 01:35:161371}
1372
[email protected]2041cf342010-02-19 03:15:591373// Make sure that we process all pending requests even when we're stalling
[email protected]4f2abec2010-02-03 18:10:161374// because of multiple releasing disconnected sockets.
1375TEST_F(ClientSocketPoolBaseTest, MultipleReleasingDisconnectedSockets) {
1376 CreatePoolWithIdleTimeouts(
1377 kDefaultMaxSockets, kDefaultMaxSocketsPerGroup,
1378 base::TimeDelta(), // Time out unused sockets immediately.
1379 base::TimeDelta::FromDays(1)); // Don't time out used sockets.
1380
1381 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
1382
1383 // Startup 4 connect jobs. Two of them will be pending.
1384
1385 TestSocketRequest req(&request_order_, &completion_count_);
1386 int rv = InitHandle(req.handle(), "a", LOWEST, &req, pool_.get(), NULL);
1387 EXPECT_EQ(OK, rv);
1388
1389 TestSocketRequest req2(&request_order_, &completion_count_);
1390 rv = InitHandle(req2.handle(), "a", LOWEST, &req2, pool_.get(), NULL);
1391 EXPECT_EQ(OK, rv);
1392
1393 TestSocketRequest req3(&request_order_, &completion_count_);
1394 rv = InitHandle(req3.handle(), "a", LOWEST, &req3, pool_.get(), NULL);
1395 EXPECT_EQ(ERR_IO_PENDING, rv);
1396
1397 TestSocketRequest req4(&request_order_, &completion_count_);
1398 rv = InitHandle(req4.handle(), "a", LOWEST, &req4, pool_.get(), NULL);
1399 EXPECT_EQ(ERR_IO_PENDING, rv);
1400
1401 // Release two disconnected sockets.
1402
1403 req.handle()->socket()->Disconnect();
1404 req.handle()->Reset();
1405 req2.handle()->socket()->Disconnect();
1406 req2.handle()->Reset();
1407
1408 EXPECT_EQ(OK, req3.WaitForResult());
1409 EXPECT_FALSE(req3.handle()->is_reused());
1410 EXPECT_EQ(OK, req4.WaitForResult());
1411 EXPECT_FALSE(req4.handle()->is_reused());
1412}
1413
[email protected]fd4fe0b2010-02-08 23:02:151414TEST_F(ClientSocketPoolBaseTest,
1415 ReleasingDisconnectedSocketsMaintainsPriorityOrder) {
1416 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
1417
1418 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1419
1420 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1421 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1422 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1423 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1424
1425 EXPECT_EQ(OK, requests_[0]->WaitForResult());
1426 EXPECT_EQ(OK, requests_[1]->WaitForResult());
1427 EXPECT_EQ(2u, completion_count_);
1428
1429 // Releases one connection.
1430 EXPECT_TRUE(ReleaseOneConnection(NO_KEEP_ALIVE));
1431 EXPECT_EQ(OK, requests_[2]->WaitForResult());
1432
1433 EXPECT_TRUE(ReleaseOneConnection(NO_KEEP_ALIVE));
1434 EXPECT_EQ(OK, requests_[3]->WaitForResult());
1435 EXPECT_EQ(4u, completion_count_);
1436
1437 EXPECT_EQ(1, GetOrderOfRequest(1));
1438 EXPECT_EQ(2, GetOrderOfRequest(2));
1439 EXPECT_EQ(3, GetOrderOfRequest(3));
1440 EXPECT_EQ(4, GetOrderOfRequest(4));
1441
1442 // Make sure we test order of all requests made.
1443 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(5));
1444}
1445
[email protected]4f1e4982010-03-02 18:31:041446class TestReleasingSocketRequest : public CallbackRunner< Tuple1<int> > {
1447 public:
1448 explicit TestReleasingSocketRequest(TestClientSocketPool* pool)
1449 : pool_(pool) {}
1450
1451 ClientSocketHandle* handle() { return &handle_; }
1452
1453 int WaitForResult() {
1454 return callback_.WaitForResult();
1455 }
1456
1457 virtual void RunWithParams(const Tuple1<int>& params) {
1458 callback_.RunWithParams(params);
1459 handle_.Reset();
1460 EXPECT_EQ(ERR_IO_PENDING,
1461 InitHandle(&handle2_, "a", kDefaultPriority,
1462 &callback2_, pool_, NULL));
1463 }
1464
1465 private:
1466 TestClientSocketPool* const pool_;
1467 ClientSocketHandle handle_;
1468 ClientSocketHandle handle2_;
1469 TestCompletionCallback callback_;
1470 TestCompletionCallback callback2_;
1471};
1472
1473// This test covers the case where, within the same DoReleaseSocket() callback,
1474// we release the just acquired socket and start up a new request. See bug
1475// 36871 for details.
1476TEST_F(ClientSocketPoolBaseTest, ReleasedSocketReleasesToo) {
1477 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
1478
1479 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
1480
1481 // Complete one request and release the socket.
1482 ClientSocketHandle handle;
1483 TestCompletionCallback callback;
1484 EXPECT_EQ(OK, InitHandle(
1485 &handle, "a", kDefaultPriority, &callback, pool_.get(), NULL));
1486 handle.Reset();
1487
1488 // Before the DoReleaseSocket() task has run, start up a
1489 // TestReleasingSocketRequest. This one will be ERR_IO_PENDING since
1490 // num_releasing_sockets > 0 and there was no idle socket to use yet.
1491 TestReleasingSocketRequest request(pool_.get());
1492 EXPECT_EQ(ERR_IO_PENDING,
1493 InitHandle(request.handle(), "a", kDefaultPriority, &request,
1494 pool_.get(), NULL));
1495
1496 EXPECT_EQ(OK, request.WaitForResult());
1497}
1498
[email protected]f6d1d6eb2009-06-24 20:16:091499} // namespace
1500
1501} // namespace net