blob: 5f6c6fc02c8785a71ef0a262ee3403ca967ab902 [file] [log] [blame]
[email protected]f6d1d6eb2009-06-24 20:16:091// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// 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
7#include "base/compiler_specific.h"
8#include "base/message_loop.h"
[email protected]c9d6a1d2009-07-14 16:15:209#include "base/scoped_vector.h"
[email protected]f6d1d6eb2009-06-24 20:16:0910#include "net/base/net_errors.h"
11#include "net/base/test_completion_callback.h"
12#include "net/socket/client_socket.h"
13#include "net/socket/client_socket_factory.h"
14#include "net/socket/client_socket_handle.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace net {
18
19namespace {
20
[email protected]c9d6a1d2009-07-14 16:15:2021const int kDefaultMaxSocketsPerGroup = 2;
[email protected]f6d1d6eb2009-06-24 20:16:0922
[email protected]0b7648c2009-07-06 20:14:0123const int kDefaultPriority = 5;
24
[email protected]f6d1d6eb2009-06-24 20:16:0925class MockClientSocket : public ClientSocket {
26 public:
27 MockClientSocket() : connected_(false) {}
28
[email protected]ab838892009-06-30 18:49:0529 // Socket methods:
30 virtual int Read(
31 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) {
32 return ERR_UNEXPECTED;
33 }
34
35 virtual int Write(
36 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) {
37 return ERR_UNEXPECTED;
38 }
39
[email protected]f6d1d6eb2009-06-24 20:16:0940 // ClientSocket methods:
[email protected]ab838892009-06-30 18:49:0541
[email protected]f6d1d6eb2009-06-24 20:16:0942 virtual int Connect(CompletionCallback* callback) {
43 connected_ = true;
44 return OK;
45 }
[email protected]f6d1d6eb2009-06-24 20:16:0946
[email protected]ab838892009-06-30 18:49:0547 virtual void Disconnect() { connected_ = false; }
48 virtual bool IsConnected() const { return connected_; }
49 virtual bool IsConnectedAndIdle() const { return connected_; }
[email protected]0b7648c2009-07-06 20:14:0150
[email protected]ab838892009-06-30 18:49:0551#if defined(OS_LINUX)
52 virtual int GetPeerName(struct sockaddr* /* name */,
53 socklen_t* /* namelen */) {
54 return 0;
[email protected]f6d1d6eb2009-06-24 20:16:0955 }
[email protected]ab838892009-06-30 18:49:0556#endif
[email protected]f6d1d6eb2009-06-24 20:16:0957
58 private:
59 bool connected_;
[email protected]f6d1d6eb2009-06-24 20:16:0960
[email protected]ab838892009-06-30 18:49:0561 DISALLOW_COPY_AND_ASSIGN(MockClientSocket);
[email protected]f6d1d6eb2009-06-24 20:16:0962};
63
[email protected]5fc08e32009-07-15 17:09:5764class TestConnectJob;
65
[email protected]f6d1d6eb2009-06-24 20:16:0966class MockClientSocketFactory : public ClientSocketFactory {
67 public:
[email protected]ab838892009-06-30 18:49:0568 MockClientSocketFactory() : allocation_count_(0) {}
[email protected]f6d1d6eb2009-06-24 20:16:0969
70 virtual ClientSocket* CreateTCPClientSocket(const AddressList& addresses) {
71 allocation_count_++;
[email protected]ab838892009-06-30 18:49:0572 return NULL;
[email protected]f6d1d6eb2009-06-24 20:16:0973 }
74
75 virtual SSLClientSocket* CreateSSLClientSocket(
76 ClientSocket* transport_socket,
77 const std::string& hostname,
78 const SSLConfig& ssl_config) {
79 NOTIMPLEMENTED();
80 return NULL;
81 }
82
[email protected]5fc08e32009-07-15 17:09:5783 void WaitForSignal(TestConnectJob* job) { waiting_jobs_.push_back(job); }
84 void SignalJobs();
85
[email protected]f6d1d6eb2009-06-24 20:16:0986 int allocation_count() const { return allocation_count_; }
87
[email protected]f6d1d6eb2009-06-24 20:16:0988 private:
89 int allocation_count_;
[email protected]5fc08e32009-07-15 17:09:5790 std::vector<TestConnectJob*> waiting_jobs_;
[email protected]f6d1d6eb2009-06-24 20:16:0991};
92
93class TestSocketRequest : public CallbackRunner< Tuple1<int> > {
94 public:
95 TestSocketRequest(
96 ClientSocketPool* pool,
97 std::vector<TestSocketRequest*>* request_order)
98 : handle(pool), request_order_(request_order) {}
99
100 ClientSocketHandle handle;
101
102 int WaitForResult() {
103 return callback_.WaitForResult();
104 }
105
106 virtual void RunWithParams(const Tuple1<int>& params) {
107 callback_.RunWithParams(params);
108 completion_count++;
109 request_order_->push_back(this);
110 }
111
[email protected]c9d6a1d2009-07-14 16:15:20112 static size_t completion_count;
[email protected]f6d1d6eb2009-06-24 20:16:09113
114 private:
115 std::vector<TestSocketRequest*>* request_order_;
116 TestCompletionCallback callback_;
117};
118
[email protected]c9d6a1d2009-07-14 16:15:20119size_t TestSocketRequest::completion_count = 0;
[email protected]f6d1d6eb2009-06-24 20:16:09120
[email protected]ab838892009-06-30 18:49:05121class TestConnectJob : public ConnectJob {
122 public:
123 enum JobType {
124 kMockJob,
125 kMockFailingJob,
126 kMockPendingJob,
127 kMockPendingFailingJob,
[email protected]5fc08e32009-07-15 17:09:57128 kMockWaitingJob,
129 kMockAdvancingLoadStateJob,
[email protected]ab838892009-06-30 18:49:05130 };
131
132 TestConnectJob(JobType job_type,
133 const std::string& group_name,
134 const ClientSocketPoolBase::Request& request,
135 ConnectJob::Delegate* delegate,
[email protected]5fc08e32009-07-15 17:09:57136 MockClientSocketFactory* client_socket_factory)
[email protected]2ab05b52009-07-01 23:57:58137 : ConnectJob(group_name, request.handle, delegate),
138 job_type_(job_type),
[email protected]ab838892009-06-30 18:49:05139 client_socket_factory_(client_socket_factory),
[email protected]ab838892009-06-30 18:49:05140 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
141
142 // ConnectJob methods:
143
144 virtual int Connect() {
145 AddressList ignored;
146 client_socket_factory_->CreateTCPClientSocket(ignored);
147 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]ab838892009-06-30 18:49:05154 MessageLoop::current()->PostTask(
155 FROM_HERE,
156 method_factory_.NewRunnableMethod(
157 &TestConnectJob::DoConnect,
158 true /* successful */,
159 true /* async */));
160 return ERR_IO_PENDING;
161 case kMockPendingFailingJob:
[email protected]5fc08e32009-07-15 17:09:57162 set_load_state(LOAD_STATE_CONNECTING);
[email protected]ab838892009-06-30 18:49:05163 MessageLoop::current()->PostTask(
164 FROM_HERE,
165 method_factory_.NewRunnableMethod(
166 &TestConnectJob::DoConnect,
167 false /* error */,
168 true /* async */));
169 return ERR_IO_PENDING;
[email protected]5fc08e32009-07-15 17:09:57170 case kMockWaitingJob:
171 client_socket_factory_->WaitForSignal(this);
172 waiting_success_ = true;
173 return ERR_IO_PENDING;
174 case kMockAdvancingLoadStateJob:
175 MessageLoop::current()->PostTask(
176 FROM_HERE,
177 method_factory_.NewRunnableMethod(
178 &TestConnectJob::AdvanceLoadState, load_state()));
179 return ERR_IO_PENDING;
[email protected]ab838892009-06-30 18:49:05180 default:
181 NOTREACHED();
182 return ERR_FAILED;
183 }
184 }
185
[email protected]5fc08e32009-07-15 17:09:57186 void Signal() {
187 DoConnect(waiting_success_, true /* async */);
188 }
189
[email protected]ab838892009-06-30 18:49:05190 private:
191 int DoConnect(bool succeed, bool was_async) {
192 int result = ERR_CONNECTION_FAILED;
[email protected]ab838892009-06-30 18:49:05193 if (succeed) {
194 result = OK;
[email protected]2ab05b52009-07-01 23:57:58195 set_socket(new MockClientSocket());
196 socket()->Connect(NULL);
[email protected]ab838892009-06-30 18:49:05197 }
[email protected]2ab05b52009-07-01 23:57:58198
199 if (was_async)
200 delegate()->OnConnectJobComplete(result, this);
[email protected]ab838892009-06-30 18:49:05201 return result;
202 }
203
[email protected]5fc08e32009-07-15 17:09:57204 void AdvanceLoadState(LoadState state) {
205 int tmp = state;
206 tmp++;
207 state = static_cast<LoadState>(tmp);
208 set_load_state(state);
209 // Post a delayed task so RunAllPending() won't run it.
210 MessageLoop::current()->PostDelayedTask(
211 FROM_HERE,
212 method_factory_.NewRunnableMethod(&TestConnectJob::AdvanceLoadState,
213 state),
214 1 /* 1ms delay */);
215 }
216
217 bool waiting_success_;
[email protected]ab838892009-06-30 18:49:05218 const JobType job_type_;
[email protected]5fc08e32009-07-15 17:09:57219 MockClientSocketFactory* const client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05220 ScopedRunnableMethodFactory<TestConnectJob> method_factory_;
221
222 DISALLOW_COPY_AND_ASSIGN(TestConnectJob);
223};
224
225class TestConnectJobFactory : public ClientSocketPoolBase::ConnectJobFactory {
226 public:
[email protected]5fc08e32009-07-15 17:09:57227 explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory)
[email protected]ab838892009-06-30 18:49:05228 : job_type_(TestConnectJob::kMockJob),
229 client_socket_factory_(client_socket_factory) {}
230
231 virtual ~TestConnectJobFactory() {}
232
233 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; }
234
235 // ConnectJobFactory methods:
236
237 virtual ConnectJob* NewConnectJob(
238 const std::string& group_name,
239 const ClientSocketPoolBase::Request& request,
240 ConnectJob::Delegate* delegate) const {
241 return new TestConnectJob(job_type_,
242 group_name,
243 request,
244 delegate,
245 client_socket_factory_);
246 }
247
248 private:
249 TestConnectJob::JobType job_type_;
[email protected]5fc08e32009-07-15 17:09:57250 MockClientSocketFactory* const client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05251
252 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory);
253};
254
255class TestClientSocketPool : public ClientSocketPool {
256 public:
257 TestClientSocketPool(
258 int max_sockets_per_group,
259 ClientSocketPoolBase::ConnectJobFactory* connect_job_factory)
260 : base_(new ClientSocketPoolBase(
[email protected]c9d6a1d2009-07-14 16:15:20261 max_sockets_per_group, connect_job_factory)) {}
[email protected]ab838892009-06-30 18:49:05262
263 virtual int RequestSocket(
264 const std::string& group_name,
265 const HostResolver::RequestInfo& resolve_info,
266 int priority,
267 ClientSocketHandle* handle,
268 CompletionCallback* callback) {
269 return base_->RequestSocket(
270 group_name, resolve_info, priority, handle, callback);
271 }
272
273 virtual void CancelRequest(
274 const std::string& group_name,
275 const ClientSocketHandle* handle) {
276 base_->CancelRequest(group_name, handle);
277 }
278
279 virtual void ReleaseSocket(
280 const std::string& group_name,
281 ClientSocket* socket) {
282 base_->ReleaseSocket(group_name, socket);
283 }
284
285 virtual void CloseIdleSockets() {
286 base_->CloseIdleSockets();
287 }
288
289 virtual int IdleSocketCount() const { return base_->idle_socket_count(); }
290
291 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
292 return base_->IdleSocketCountInGroup(group_name);
293 }
294
295 virtual LoadState GetLoadState(const std::string& group_name,
296 const ClientSocketHandle* handle) const {
297 return base_->GetLoadState(group_name, handle);
298 }
299
[email protected]c9d6a1d2009-07-14 16:15:20300 int MaxSocketsPerGroup() const {
301 return base_->max_sockets_per_group();
302 }
303
[email protected]ab838892009-06-30 18:49:05304 private:
305 const scoped_refptr<ClientSocketPoolBase> base_;
306
307 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool);
308};
309
[email protected]5fc08e32009-07-15 17:09:57310void MockClientSocketFactory::SignalJobs() {
311 for (std::vector<TestConnectJob*>::iterator it = waiting_jobs_.begin();
312 it != waiting_jobs_.end(); ++it) {
313 (*it)->Signal();
314 }
315 waiting_jobs_.clear();
316}
317
[email protected]ab838892009-06-30 18:49:05318class ClientSocketPoolBaseTest : public testing::Test {
[email protected]f6d1d6eb2009-06-24 20:16:09319 protected:
[email protected]ab838892009-06-30 18:49:05320 ClientSocketPoolBaseTest()
321 : ignored_request_info_("ignored", 80),
322 connect_job_factory_(
[email protected]c9d6a1d2009-07-14 16:15:20323 new TestConnectJobFactory(&client_socket_factory_)) {}
324
325 void CreatePool(int max_sockets_per_group) {
326 DCHECK(!pool_.get());
327 pool_ = new TestClientSocketPool(max_sockets_per_group,
328 connect_job_factory_);
329 }
[email protected]f6d1d6eb2009-06-24 20:16:09330
331 virtual void SetUp() {
[email protected]f6d1d6eb2009-06-24 20:16:09332 TestSocketRequest::completion_count = 0;
333 }
334
335 virtual void TearDown() {
336 // The tests often call Reset() on handles at the end which may post
337 // DoReleaseSocket() tasks.
338 MessageLoop::current()->RunAllPending();
[email protected]5fc08e32009-07-15 17:09:57339 // Need to delete |pool_| before we turn late binding back off.
340 // TODO(willchan): Remove this line when late binding becomes the default.
341 pool_ = NULL;
342 ClientSocketPoolBase::EnableLateBindingOfSockets(false);
[email protected]f6d1d6eb2009-06-24 20:16:09343 }
344
[email protected]c9d6a1d2009-07-14 16:15:20345 int StartRequest(const std::string& group_name, int priority) {
346 DCHECK(pool_.get());
347 TestSocketRequest* request = new TestSocketRequest(pool_.get(),
348 &request_order_);
349 requests_.push_back(request);
350 int rv = request->handle.Init(group_name, ignored_request_info_, priority,
351 request);
352 if (rv != ERR_IO_PENDING)
353 request_order_.push_back(request);
354 return rv;
355 }
[email protected]0b7648c2009-07-06 20:14:01356
[email protected]c9d6a1d2009-07-14 16:15:20357 static const int kIndexOutOfBounds;
358 static const int kRequestNotFound;
[email protected]0b7648c2009-07-06 20:14:01359
[email protected]c9d6a1d2009-07-14 16:15:20360 int GetOrderOfRequest(size_t index) {
361 index--;
362 if (index >= requests_.size())
363 return kIndexOutOfBounds;
364
365 for (size_t i = 0; i < request_order_.size(); i++)
366 if (requests_[index] == request_order_[i])
367 return i + 1;
368
369 return kRequestNotFound;
[email protected]0b7648c2009-07-06 20:14:01370 }
371
372 enum KeepAlive {
373 KEEP_ALIVE,
374 NO_KEEP_ALIVE,
375 };
376
[email protected]c9d6a1d2009-07-14 16:15:20377 void ReleaseAllConnections(KeepAlive keep_alive) {
[email protected]0b7648c2009-07-06 20:14:01378 bool released_one;
379 do {
380 released_one = false;
[email protected]c9d6a1d2009-07-14 16:15:20381 ScopedVector<TestSocketRequest>::iterator i;
382 for (i = requests_.begin(); i != requests_.end(); ++i) {
383 if ((*i)->handle.is_initialized()) {
[email protected]0b7648c2009-07-06 20:14:01384 if (keep_alive == NO_KEEP_ALIVE)
[email protected]c9d6a1d2009-07-14 16:15:20385 (*i)->handle.socket()->Disconnect();
386 (*i)->handle.Reset();
[email protected]0b7648c2009-07-06 20:14:01387 MessageLoop::current()->RunAllPending();
388 released_one = true;
389 }
390 }
391 } while (released_one);
392 }
393
[email protected]ab838892009-06-30 18:49:05394 HostResolver::RequestInfo ignored_request_info_;
[email protected]f6d1d6eb2009-06-24 20:16:09395 MockClientSocketFactory client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05396 TestConnectJobFactory* const connect_job_factory_;
[email protected]c9d6a1d2009-07-14 16:15:20397 scoped_refptr<TestClientSocketPool> pool_;
398 ScopedVector<TestSocketRequest> requests_;
[email protected]f6d1d6eb2009-06-24 20:16:09399 std::vector<TestSocketRequest*> request_order_;
400};
401
[email protected]c9d6a1d2009-07-14 16:15:20402// static
403const int ClientSocketPoolBaseTest::kIndexOutOfBounds = -1;
404
405// static
406const int ClientSocketPoolBaseTest::kRequestNotFound = -2;
407
[email protected]5fc08e32009-07-15 17:09:57408TEST_F(ClientSocketPoolBaseTest, BasicSynchronous) {
[email protected]c9d6a1d2009-07-14 16:15:20409 CreatePool(kDefaultMaxSocketsPerGroup);
410
[email protected]f6d1d6eb2009-06-24 20:16:09411 TestCompletionCallback callback;
412 ClientSocketHandle handle(pool_.get());
[email protected]0b7648c2009-07-06 20:14:01413 EXPECT_EQ(OK, handle.Init("a", ignored_request_info_, kDefaultPriority,
414 &callback));
[email protected]f6d1d6eb2009-06-24 20:16:09415 EXPECT_TRUE(handle.is_initialized());
416 EXPECT_TRUE(handle.socket());
[email protected]f6d1d6eb2009-06-24 20:16:09417 handle.Reset();
418}
419
[email protected]5fc08e32009-07-15 17:09:57420TEST_F(ClientSocketPoolBaseTest, BasicAsynchronous) {
421 CreatePool(kDefaultMaxSocketsPerGroup);
422
423 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
424 TestSocketRequest req(pool_.get(), &request_order_);
425 int rv = req.handle.Init("a", ignored_request_info_, 0, &req);
426 EXPECT_EQ(ERR_IO_PENDING, rv);
427 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &req.handle));
428 EXPECT_EQ(OK, req.WaitForResult());
429 EXPECT_TRUE(req.handle.is_initialized());
430 EXPECT_TRUE(req.handle.socket());
431 req.handle.Reset();
432}
433
[email protected]ab838892009-06-30 18:49:05434TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) {
[email protected]c9d6a1d2009-07-14 16:15:20435 CreatePool(kDefaultMaxSocketsPerGroup);
436
[email protected]ab838892009-06-30 18:49:05437 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09438 TestSocketRequest req(pool_.get(), &request_order_);
[email protected]3ae82302009-06-26 06:01:21439 EXPECT_EQ(ERR_CONNECTION_FAILED,
[email protected]0b7648c2009-07-06 20:14:01440 req.handle.Init("a", ignored_request_info_,
441 kDefaultPriority, &req));
[email protected]f6d1d6eb2009-06-24 20:16:09442}
443
[email protected]5fc08e32009-07-15 17:09:57444TEST_F(ClientSocketPoolBaseTest, InitConnectionAsynchronousFailure) {
445 CreatePool(kDefaultMaxSocketsPerGroup);
446
447 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
448 TestSocketRequest req(pool_.get(), &request_order_);
449 EXPECT_EQ(ERR_IO_PENDING,
450 req.handle.Init("a", ignored_request_info_, 5, &req));
451 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &req.handle));
452 EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult());
453}
454
[email protected]ab838892009-06-30 18:49:05455TEST_F(ClientSocketPoolBaseTest, PendingRequests) {
[email protected]c9d6a1d2009-07-14 16:15:20456 CreatePool(kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09457
[email protected]c9d6a1d2009-07-14 16:15:20458 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
459 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
460 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
461 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
462 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
463 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
464 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
[email protected]f6d1d6eb2009-06-24 20:16:09465
[email protected]c9d6a1d2009-07-14 16:15:20466 ReleaseAllConnections(KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09467
[email protected]c9d6a1d2009-07-14 16:15:20468 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
469 client_socket_factory_.allocation_count());
470 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
471 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09472
[email protected]c9d6a1d2009-07-14 16:15:20473 EXPECT_EQ(1, GetOrderOfRequest(1));
474 EXPECT_EQ(2, GetOrderOfRequest(2));
475 EXPECT_EQ(6, GetOrderOfRequest(3));
476 EXPECT_EQ(4, GetOrderOfRequest(4));
477 EXPECT_EQ(3, GetOrderOfRequest(5));
478 EXPECT_EQ(5, GetOrderOfRequest(6));
479 EXPECT_EQ(7, GetOrderOfRequest(7));
[email protected]f6d1d6eb2009-06-24 20:16:09480}
481
[email protected]ab838892009-06-30 18:49:05482TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) {
[email protected]c9d6a1d2009-07-14 16:15:20483 CreatePool(kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09484
[email protected]c9d6a1d2009-07-14 16:15:20485 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
486 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
487 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
488 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
489 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
490 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
491 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
[email protected]f6d1d6eb2009-06-24 20:16:09492
[email protected]c9d6a1d2009-07-14 16:15:20493 ReleaseAllConnections(NO_KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09494
[email protected]c9d6a1d2009-07-14 16:15:20495 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i)
496 EXPECT_EQ(OK, requests_[i]->WaitForResult());
497
498 EXPECT_EQ(static_cast<int>(requests_.size()),
499 client_socket_factory_.allocation_count());
500 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
501 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09502}
503
504// This test will start up a RequestSocket() and then immediately Cancel() it.
[email protected]ab838892009-06-30 18:49:05505// The pending connect job will be cancelled and should not call back into
506// ClientSocketPoolBase.
507TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) {
[email protected]c9d6a1d2009-07-14 16:15:20508 CreatePool(kDefaultMaxSocketsPerGroup);
509
[email protected]ab838892009-06-30 18:49:05510 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09511 TestSocketRequest req(pool_.get(), &request_order_);
[email protected]ab838892009-06-30 18:49:05512 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01513 req.handle.Init("a", ignored_request_info_,
514 kDefaultPriority, &req));
[email protected]f6d1d6eb2009-06-24 20:16:09515 req.handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09516}
517
[email protected]ab838892009-06-30 18:49:05518TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) {
[email protected]c9d6a1d2009-07-14 16:15:20519 CreatePool(kDefaultMaxSocketsPerGroup);
520
[email protected]ab838892009-06-30 18:49:05521 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09522 TestSocketRequest req(pool_.get(), &request_order_);
523 TestSocketRequest req2(pool_.get(), &request_order_);
524
[email protected]ab838892009-06-30 18:49:05525 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01526 req.handle.Init("a", ignored_request_info_,
527 kDefaultPriority, &req));
[email protected]ab838892009-06-30 18:49:05528 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01529 req2.handle.Init("a", ignored_request_info_,
530 kDefaultPriority, &req2));
[email protected]f6d1d6eb2009-06-24 20:16:09531
532 req.handle.Reset();
533
534 EXPECT_EQ(OK, req2.WaitForResult());
535 req2.handle.Reset();
536}
537
[email protected]ab838892009-06-30 18:49:05538TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) {
[email protected]c9d6a1d2009-07-14 16:15:20539 CreatePool(kDefaultMaxSocketsPerGroup);
540
[email protected]ab838892009-06-30 18:49:05541 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09542 ClientSocketHandle handle(pool_.get());
543 TestCompletionCallback callback;
544 TestSocketRequest req(pool_.get(), &request_order_);
545
[email protected]ab838892009-06-30 18:49:05546 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01547 handle.Init("a", ignored_request_info_,
548 kDefaultPriority, &callback));
[email protected]f6d1d6eb2009-06-24 20:16:09549
550 handle.Reset();
551
552 TestCompletionCallback callback2;
[email protected]ab838892009-06-30 18:49:05553 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01554 handle.Init("a", ignored_request_info_,
555 kDefaultPriority, &callback2));
[email protected]f6d1d6eb2009-06-24 20:16:09556
557 EXPECT_EQ(OK, callback2.WaitForResult());
558 EXPECT_FALSE(callback.have_result());
559
560 handle.Reset();
561}
562
[email protected]ab838892009-06-30 18:49:05563TEST_F(ClientSocketPoolBaseTest, CancelRequest) {
[email protected]c9d6a1d2009-07-14 16:15:20564 CreatePool(kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09565
[email protected]c9d6a1d2009-07-14 16:15:20566 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
567 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
568 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
569 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
570 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
571 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
572 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
[email protected]f6d1d6eb2009-06-24 20:16:09573
574 // Cancel a request.
[email protected]c9d6a1d2009-07-14 16:15:20575 size_t index_to_cancel = kDefaultMaxSocketsPerGroup + 2;
576 EXPECT_FALSE(requests_[index_to_cancel]->handle.is_initialized());
577 requests_[index_to_cancel]->handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09578
[email protected]c9d6a1d2009-07-14 16:15:20579 ReleaseAllConnections(KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09580
[email protected]c9d6a1d2009-07-14 16:15:20581 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
582 client_socket_factory_.allocation_count());
583 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup - 1,
584 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09585
[email protected]c9d6a1d2009-07-14 16:15:20586 EXPECT_EQ(1, GetOrderOfRequest(1));
587 EXPECT_EQ(2, GetOrderOfRequest(2));
588 EXPECT_EQ(5, GetOrderOfRequest(3));
589 EXPECT_EQ(3, GetOrderOfRequest(4));
590 EXPECT_EQ(kRequestNotFound, GetOrderOfRequest(5)); // Canceled request.
591 EXPECT_EQ(4, GetOrderOfRequest(6));
592 EXPECT_EQ(6, GetOrderOfRequest(7));
[email protected]f6d1d6eb2009-06-24 20:16:09593}
594
595class RequestSocketCallback : public CallbackRunner< Tuple1<int> > {
596 public:
[email protected]2ab05b52009-07-01 23:57:58597 RequestSocketCallback(ClientSocketHandle* handle,
598 TestConnectJobFactory* test_connect_job_factory,
599 TestConnectJob::JobType next_job_type)
[email protected]f6d1d6eb2009-06-24 20:16:09600 : handle_(handle),
[email protected]2ab05b52009-07-01 23:57:58601 within_callback_(false),
602 test_connect_job_factory_(test_connect_job_factory),
603 next_job_type_(next_job_type) {}
[email protected]f6d1d6eb2009-06-24 20:16:09604
605 virtual void RunWithParams(const Tuple1<int>& params) {
606 callback_.RunWithParams(params);
607 ASSERT_EQ(OK, params.a);
608
609 if (!within_callback_) {
[email protected]2ab05b52009-07-01 23:57:58610 test_connect_job_factory_->set_job_type(next_job_type_);
[email protected]f6d1d6eb2009-06-24 20:16:09611 handle_->Reset();
612 within_callback_ = true;
613 int rv = handle_->Init(
[email protected]0b7648c2009-07-06 20:14:01614 "a", HostResolver::RequestInfo("www.google.com", 80),
615 kDefaultPriority, this);
[email protected]2ab05b52009-07-01 23:57:58616 switch (next_job_type_) {
617 case TestConnectJob::kMockJob:
618 EXPECT_EQ(OK, rv);
619 break;
620 case TestConnectJob::kMockPendingJob:
621 EXPECT_EQ(ERR_IO_PENDING, rv);
622 break;
623 default:
624 FAIL() << "Unexpected job type: " << next_job_type_;
625 break;
626 }
[email protected]f6d1d6eb2009-06-24 20:16:09627 }
628 }
629
630 int WaitForResult() {
631 return callback_.WaitForResult();
632 }
633
634 private:
635 ClientSocketHandle* const handle_;
636 bool within_callback_;
[email protected]2ab05b52009-07-01 23:57:58637 TestConnectJobFactory* const test_connect_job_factory_;
638 TestConnectJob::JobType next_job_type_;
[email protected]f6d1d6eb2009-06-24 20:16:09639 TestCompletionCallback callback_;
640};
641
[email protected]2ab05b52009-07-01 23:57:58642TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) {
[email protected]c9d6a1d2009-07-14 16:15:20643 CreatePool(kDefaultMaxSocketsPerGroup);
644
[email protected]0b7648c2009-07-06 20:14:01645 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09646 ClientSocketHandle handle(pool_.get());
[email protected]2ab05b52009-07-01 23:57:58647 RequestSocketCallback callback(
648 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09649 int rv = handle.Init(
[email protected]0b7648c2009-07-06 20:14:01650 "a", ignored_request_info_, kDefaultPriority, &callback);
[email protected]f6d1d6eb2009-06-24 20:16:09651 ASSERT_EQ(ERR_IO_PENDING, rv);
652
653 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ab05b52009-07-01 23:57:58654 handle.Reset();
655}
[email protected]f6d1d6eb2009-06-24 20:16:09656
[email protected]2ab05b52009-07-01 23:57:58657TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) {
[email protected]c9d6a1d2009-07-14 16:15:20658 CreatePool(kDefaultMaxSocketsPerGroup);
659
[email protected]0b7648c2009-07-06 20:14:01660 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]2ab05b52009-07-01 23:57:58661 ClientSocketHandle handle(pool_.get());
662 RequestSocketCallback callback(
663 &handle, connect_job_factory_, TestConnectJob::kMockJob);
664 int rv = handle.Init(
[email protected]0b7648c2009-07-06 20:14:01665 "a", ignored_request_info_, kDefaultPriority, &callback);
[email protected]2ab05b52009-07-01 23:57:58666 ASSERT_EQ(ERR_IO_PENDING, rv);
667
668 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]f6d1d6eb2009-06-24 20:16:09669 handle.Reset();
670}
671
672// Make sure that pending requests get serviced after active requests get
673// cancelled.
[email protected]ab838892009-06-30 18:49:05674TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) {
[email protected]c9d6a1d2009-07-14 16:15:20675 CreatePool(kDefaultMaxSocketsPerGroup);
676
[email protected]0b7648c2009-07-06 20:14:01677 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09678
[email protected]c9d6a1d2009-07-14 16:15:20679 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
680 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
681 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
682 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
683 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
684 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
685 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
[email protected]f6d1d6eb2009-06-24 20:16:09686
[email protected]c9d6a1d2009-07-14 16:15:20687 // Now, kDefaultMaxSocketsPerGroup requests should be active.
688 // Let's cancel them.
689 for (int i = 0; i < kDefaultMaxSocketsPerGroup; ++i) {
690 ASSERT_FALSE(requests_[i]->handle.is_initialized());
691 requests_[i]->handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09692 }
693
[email protected]f6d1d6eb2009-06-24 20:16:09694 // Let's wait for the rest to complete now.
[email protected]c9d6a1d2009-07-14 16:15:20695 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i) {
696 EXPECT_EQ(OK, requests_[i]->WaitForResult());
697 requests_[i]->handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09698 }
699
[email protected]c9d6a1d2009-07-14 16:15:20700 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
701 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09702}
703
704// Make sure that pending requests get serviced after active requests fail.
[email protected]ab838892009-06-30 18:49:05705TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) {
[email protected]c9d6a1d2009-07-14 16:15:20706 CreatePool(kDefaultMaxSocketsPerGroup);
707
[email protected]0b7648c2009-07-06 20:14:01708 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09709
[email protected]c9d6a1d2009-07-14 16:15:20710 scoped_ptr<TestSocketRequest> reqs[kDefaultMaxSocketsPerGroup * 2 + 1];
[email protected]f6d1d6eb2009-06-24 20:16:09711
712 // Queue up all the requests
[email protected]f6d1d6eb2009-06-24 20:16:09713 for (size_t i = 0; i < arraysize(reqs); ++i) {
714 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
[email protected]0b7648c2009-07-06 20:14:01715 int rv = reqs[i]->handle.Init("a", ignored_request_info_,
716 kDefaultPriority, reqs[i].get());
[email protected]f6d1d6eb2009-06-24 20:16:09717 EXPECT_EQ(ERR_IO_PENDING, rv);
718 }
719
720 for (size_t i = 0; i < arraysize(reqs); ++i)
721 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult());
722}
723
[email protected]5fc08e32009-07-15 17:09:57724TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestThenRequestSocket) {
725 CreatePool(kDefaultMaxSocketsPerGroup);
726
727 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
728
729 TestSocketRequest req(pool_.get(), &request_order_);
730 int rv = req.handle.Init(
731 "a", ignored_request_info_, kDefaultPriority, &req);
732 EXPECT_EQ(ERR_IO_PENDING, rv);
733
734 // Cancel the active request.
735 req.handle.Reset();
736
737 rv = req.handle.Init("a", ignored_request_info_, kDefaultPriority, &req);
738 EXPECT_EQ(ERR_IO_PENDING, rv);
739 EXPECT_EQ(OK, req.WaitForResult());
740
741 EXPECT_FALSE(req.handle.is_reused());
742 EXPECT_EQ(1U, TestSocketRequest::completion_count);
743 EXPECT_EQ(2, client_socket_factory_.allocation_count());
744}
745
[email protected]2ab05b52009-07-01 23:57:58746// A pending asynchronous job completes, which will free up a socket slot. The
747// next job finishes synchronously. The callback for the asynchronous job
748// should be first though.
749TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) {
[email protected]c9d6a1d2009-07-14 16:15:20750 CreatePool(kDefaultMaxSocketsPerGroup);
751
[email protected]2ab05b52009-07-01 23:57:58752 // First two jobs are async.
[email protected]0b7648c2009-07-06 20:14:01753 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]2ab05b52009-07-01 23:57:58754
755 // Start job 1 (async error).
756 TestSocketRequest req1(pool_.get(), &request_order_);
[email protected]0b7648c2009-07-06 20:14:01757 int rv = req1.handle.Init("a", ignored_request_info_,
758 kDefaultPriority, &req1);
[email protected]2ab05b52009-07-01 23:57:58759 EXPECT_EQ(ERR_IO_PENDING, rv);
760
761 // Start job 2 (async error).
762 TestSocketRequest req2(pool_.get(), &request_order_);
[email protected]0b7648c2009-07-06 20:14:01763 rv = req2.handle.Init("a", ignored_request_info_, kDefaultPriority, &req2);
[email protected]2ab05b52009-07-01 23:57:58764 EXPECT_EQ(ERR_IO_PENDING, rv);
765
766 // The pending job is sync.
[email protected]0b7648c2009-07-06 20:14:01767 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
[email protected]2ab05b52009-07-01 23:57:58768
769 // Request 3 does not have a ConnectJob yet. It's just pending.
770 TestSocketRequest req3(pool_.get(), &request_order_);
[email protected]0b7648c2009-07-06 20:14:01771 rv = req3.handle.Init("a", ignored_request_info_, kDefaultPriority, &req3);
[email protected]2ab05b52009-07-01 23:57:58772 EXPECT_EQ(ERR_IO_PENDING, rv);
773
774 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult());
775 EXPECT_EQ(ERR_CONNECTION_FAILED, req2.WaitForResult());
776 EXPECT_EQ(OK, req3.WaitForResult());
777
778 ASSERT_EQ(3U, request_order_.size());
779
780 // After job 1 finishes unsuccessfully, it will try to process the pending
781 // requests queue, so it starts up job 3 for request 3. This job
782 // synchronously succeeds, so the request order is 1, 3, 2.
783 EXPECT_EQ(&req1, request_order_[0]);
784 EXPECT_EQ(&req2, request_order_[2]);
785 EXPECT_EQ(&req3, request_order_[1]);
786}
787
[email protected]5fc08e32009-07-15 17:09:57788// When a ConnectJob is coupled to a request, even if a free socket becomes
789// available, the request will be serviced by the ConnectJob.
790TEST_F(ClientSocketPoolBaseTest, ReleaseSockets) {
791 CreatePool(kDefaultMaxSocketsPerGroup);
792 ClientSocketPoolBase::EnableLateBindingOfSockets(false);
793
794 // Start job 1 (async OK)
[email protected]b59ff372009-07-15 22:04:32795 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]5fc08e32009-07-15 17:09:57796
797 TestSocketRequest req1(pool_.get(), &request_order_);
798 int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
799 EXPECT_EQ(ERR_IO_PENDING, rv);
800 EXPECT_EQ(OK, req1.WaitForResult());
801
802 // Job 1 finished OK. Start job 2 (also async OK). Release socket 1.
803 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
804
805 TestSocketRequest req2(pool_.get(), &request_order_);
806 rv = req2.handle.Init("a", ignored_request_info_, 5, &req2);
807 EXPECT_EQ(ERR_IO_PENDING, rv);
808 req1.handle.Reset();
809 MessageLoop::current()->RunAllPending(); // Run the DoReleaseSocket()
810
811 // Job 2 is pending. Start request 3 (which has no associated job since it
812 // will use the idle socket).
813
814 TestSocketRequest req3(pool_.get(), &request_order_);
815 rv = req3.handle.Init("a", ignored_request_info_, 5, &req3);
816 EXPECT_EQ(OK, rv);
817
818 EXPECT_FALSE(req2.handle.socket());
819 client_socket_factory_.SignalJobs();
820 EXPECT_EQ(OK, req2.WaitForResult());
821
822 ASSERT_EQ(2U, request_order_.size());
823 EXPECT_EQ(&req1, request_order_[0]);
824 EXPECT_EQ(&req2, request_order_[1]);
825 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
826}
827
828class ClientSocketPoolBaseTest_LateBinding : public ClientSocketPoolBaseTest {
829 protected:
830 virtual void SetUp() {
831 ClientSocketPoolBaseTest::SetUp();
832 ClientSocketPoolBase::EnableLateBindingOfSockets(true);
833 }
834};
835
836TEST_F(ClientSocketPoolBaseTest_LateBinding, BasicSynchronous) {
837 CreatePool(kDefaultMaxSocketsPerGroup);
838
839 TestCompletionCallback callback;
840 ClientSocketHandle handle(pool_.get());
841 EXPECT_EQ(OK, handle.Init("a", ignored_request_info_, kDefaultPriority,
842 &callback));
843 EXPECT_TRUE(handle.is_initialized());
844 EXPECT_TRUE(handle.socket());
845 handle.Reset();
846}
847
848TEST_F(ClientSocketPoolBaseTest_LateBinding, BasicAsynchronous) {
849 CreatePool(kDefaultMaxSocketsPerGroup);
850
851 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
852 TestSocketRequest req(pool_.get(), &request_order_);
853 int rv = req.handle.Init("a", ignored_request_info_, 0, &req);
854 EXPECT_EQ(ERR_IO_PENDING, rv);
855 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &req.handle));
856 EXPECT_EQ(OK, req.WaitForResult());
857 EXPECT_TRUE(req.handle.is_initialized());
858 EXPECT_TRUE(req.handle.socket());
859 req.handle.Reset();
860}
861
862TEST_F(ClientSocketPoolBaseTest_LateBinding, InitConnectionFailure) {
863 CreatePool(kDefaultMaxSocketsPerGroup);
864
865 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
866 TestSocketRequest req(pool_.get(), &request_order_);
867 EXPECT_EQ(ERR_CONNECTION_FAILED,
868 req.handle.Init("a", ignored_request_info_,
869 kDefaultPriority, &req));
870}
871
872TEST_F(ClientSocketPoolBaseTest_LateBinding,
873 InitConnectionAsynchronousFailure) {
874 CreatePool(kDefaultMaxSocketsPerGroup);
875
876 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
877 TestSocketRequest req(pool_.get(), &request_order_);
878 EXPECT_EQ(ERR_IO_PENDING,
879 req.handle.Init("a", ignored_request_info_, 5, &req));
880 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &req.handle));
881 EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult());
882}
883
884TEST_F(ClientSocketPoolBaseTest_LateBinding, PendingRequests) {
885 CreatePool(kDefaultMaxSocketsPerGroup);
886
887 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
888 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
889 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
890 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
891 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
892 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
893 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
894
895 ReleaseAllConnections(KEEP_ALIVE);
896
897 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
898 client_socket_factory_.allocation_count());
899 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
900 TestSocketRequest::completion_count);
901
902 EXPECT_EQ(1, GetOrderOfRequest(1));
903 EXPECT_EQ(2, GetOrderOfRequest(2));
904 EXPECT_EQ(6, GetOrderOfRequest(3));
905 EXPECT_EQ(4, GetOrderOfRequest(4));
906 EXPECT_EQ(3, GetOrderOfRequest(5));
907 EXPECT_EQ(5, GetOrderOfRequest(6));
908 EXPECT_EQ(7, GetOrderOfRequest(7));
909}
910
911TEST_F(ClientSocketPoolBaseTest_LateBinding, PendingRequests_NoKeepAlive) {
912 CreatePool(kDefaultMaxSocketsPerGroup);
913
914 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
915 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
916 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
917 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
918 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
919 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
920 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
921
922 ReleaseAllConnections(NO_KEEP_ALIVE);
923
924 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i)
925 EXPECT_EQ(OK, requests_[i]->WaitForResult());
926
927 EXPECT_EQ(static_cast<int>(requests_.size()),
928 client_socket_factory_.allocation_count());
929 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
930 TestSocketRequest::completion_count);
931}
932
933// This test will start up a RequestSocket() and then immediately Cancel() it.
934// The pending connect job will be cancelled and should not call back into
935// ClientSocketPoolBase.
936TEST_F(ClientSocketPoolBaseTest_LateBinding, CancelRequestClearGroup) {
937 CreatePool(kDefaultMaxSocketsPerGroup);
938
939 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
940 TestSocketRequest req(pool_.get(), &request_order_);
941 EXPECT_EQ(ERR_IO_PENDING,
942 req.handle.Init("a", ignored_request_info_,
943 kDefaultPriority, &req));
944 req.handle.Reset();
945}
946
947TEST_F(ClientSocketPoolBaseTest_LateBinding, TwoRequestsCancelOne) {
948 CreatePool(kDefaultMaxSocketsPerGroup);
949
950 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
951 TestSocketRequest req(pool_.get(), &request_order_);
952 TestSocketRequest req2(pool_.get(), &request_order_);
953
954 EXPECT_EQ(ERR_IO_PENDING,
955 req.handle.Init("a", ignored_request_info_,
956 kDefaultPriority, &req));
957 EXPECT_EQ(ERR_IO_PENDING,
958 req2.handle.Init("a", ignored_request_info_,
959 kDefaultPriority, &req2));
960
961 req.handle.Reset();
962
963 EXPECT_EQ(OK, req2.WaitForResult());
964 req2.handle.Reset();
965}
966
967TEST_F(ClientSocketPoolBaseTest_LateBinding, ConnectCancelConnect) {
968 CreatePool(kDefaultMaxSocketsPerGroup);
969
970 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
971 ClientSocketHandle handle(pool_.get());
972 TestCompletionCallback callback;
973 TestSocketRequest req(pool_.get(), &request_order_);
974
975 EXPECT_EQ(ERR_IO_PENDING,
976 handle.Init("a", ignored_request_info_,
977 kDefaultPriority, &callback));
978
979 handle.Reset();
980
981 TestCompletionCallback callback2;
982 EXPECT_EQ(ERR_IO_PENDING,
983 handle.Init("a", ignored_request_info_,
984 kDefaultPriority, &callback2));
985
986 EXPECT_EQ(OK, callback2.WaitForResult());
987 EXPECT_FALSE(callback.have_result());
988
989 handle.Reset();
990}
991
992TEST_F(ClientSocketPoolBaseTest_LateBinding, CancelRequest) {
993 CreatePool(kDefaultMaxSocketsPerGroup);
994
995 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
996 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
997 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
998 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
999 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
1000 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
1001 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
1002
1003 // Cancel a request.
1004 size_t index_to_cancel = kDefaultMaxSocketsPerGroup + 2;
1005 EXPECT_FALSE(requests_[index_to_cancel]->handle.is_initialized());
1006 requests_[index_to_cancel]->handle.Reset();
1007
1008 ReleaseAllConnections(KEEP_ALIVE);
1009
1010 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
1011 client_socket_factory_.allocation_count());
1012 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup - 1,
1013 TestSocketRequest::completion_count);
1014
1015 EXPECT_EQ(1, GetOrderOfRequest(1));
1016 EXPECT_EQ(2, GetOrderOfRequest(2));
1017 EXPECT_EQ(5, GetOrderOfRequest(3));
1018 EXPECT_EQ(3, GetOrderOfRequest(4));
1019 EXPECT_EQ(kRequestNotFound, GetOrderOfRequest(5)); // Canceled request.
1020 EXPECT_EQ(4, GetOrderOfRequest(6));
1021 EXPECT_EQ(6, GetOrderOfRequest(7));
1022}
1023
1024TEST_F(ClientSocketPoolBaseTest_LateBinding, RequestPendingJobTwice) {
1025 CreatePool(kDefaultMaxSocketsPerGroup);
1026
1027 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1028 ClientSocketHandle handle(pool_.get());
1029 RequestSocketCallback callback(
1030 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob);
1031 int rv = handle.Init(
1032 "a", ignored_request_info_, kDefaultPriority, &callback);
1033 ASSERT_EQ(ERR_IO_PENDING, rv);
1034
1035 EXPECT_EQ(OK, callback.WaitForResult());
1036 handle.Reset();
1037}
1038
1039TEST_F(ClientSocketPoolBaseTest_LateBinding, RequestPendingJobThenSynchronous) {
1040 CreatePool(kDefaultMaxSocketsPerGroup);
1041
1042 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1043 ClientSocketHandle handle(pool_.get());
1044 RequestSocketCallback callback(
1045 &handle, connect_job_factory_, TestConnectJob::kMockJob);
1046 int rv = handle.Init(
1047 "a", ignored_request_info_, kDefaultPriority, &callback);
1048 ASSERT_EQ(ERR_IO_PENDING, rv);
1049
1050 EXPECT_EQ(OK, callback.WaitForResult());
1051 handle.Reset();
1052}
1053
1054// Make sure that pending requests get serviced after active requests get
1055// cancelled.
1056TEST_F(ClientSocketPoolBaseTest_LateBinding,
1057 CancelActiveRequestWithPendingRequests) {
1058 CreatePool(kDefaultMaxSocketsPerGroup);
1059
1060 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1061
1062 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1063 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1064 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1065 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1066 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1067 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1068 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1069
1070 // Now, kDefaultMaxSocketsPerGroup requests should be active.
1071 // Let's cancel them.
1072 for (int i = 0; i < kDefaultMaxSocketsPerGroup; ++i) {
1073 ASSERT_FALSE(requests_[i]->handle.is_initialized());
1074 requests_[i]->handle.Reset();
1075 }
1076
1077 // Let's wait for the rest to complete now.
1078 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i) {
1079 EXPECT_EQ(OK, requests_[i]->WaitForResult());
1080 requests_[i]->handle.Reset();
1081 }
1082
1083 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
1084 TestSocketRequest::completion_count);
1085}
1086
1087// Make sure that pending requests get serviced after active requests fail.
1088TEST_F(ClientSocketPoolBaseTest_LateBinding,
1089 FailingActiveRequestWithPendingRequests) {
1090 CreatePool(kDefaultMaxSocketsPerGroup);
1091
1092 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
1093
1094 scoped_ptr<TestSocketRequest> reqs[kDefaultMaxSocketsPerGroup * 2 + 1];
1095
1096 // Queue up all the requests
1097 for (size_t i = 0; i < arraysize(reqs); ++i) {
1098 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
1099 int rv = reqs[i]->handle.Init("a", ignored_request_info_,
1100 kDefaultPriority, reqs[i].get());
1101 EXPECT_EQ(ERR_IO_PENDING, rv);
1102 }
1103
1104 for (size_t i = 0; i < arraysize(reqs); ++i)
1105 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult());
1106}
1107
1108TEST_F(ClientSocketPoolBaseTest_LateBinding,
1109 CancelActiveRequestThenRequestSocket) {
1110 CreatePool(kDefaultMaxSocketsPerGroup);
1111
1112 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1113
1114 TestSocketRequest req(pool_.get(), &request_order_);
1115 int rv = req.handle.Init(
1116 "a", ignored_request_info_, kDefaultPriority, &req);
1117 EXPECT_EQ(ERR_IO_PENDING, rv);
1118
1119 // Cancel the active request.
1120 req.handle.Reset();
1121
1122 rv = req.handle.Init("a", ignored_request_info_, kDefaultPriority, &req);
1123 EXPECT_EQ(ERR_IO_PENDING, rv);
1124 EXPECT_EQ(OK, req.WaitForResult());
1125
1126 EXPECT_FALSE(req.handle.is_reused());
1127 EXPECT_EQ(1U, TestSocketRequest::completion_count);
1128 EXPECT_EQ(2, client_socket_factory_.allocation_count());
1129}
1130
1131// When requests and ConnectJobs are not coupled, the request will get serviced
1132// by whatever comes first.
1133TEST_F(ClientSocketPoolBaseTest_LateBinding, ReleaseSockets) {
1134 CreatePool(kDefaultMaxSocketsPerGroup);
1135
1136 // Start job 1 (async OK)
[email protected]b59ff372009-07-15 22:04:321137 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]5fc08e32009-07-15 17:09:571138
1139 TestSocketRequest req1(pool_.get(), &request_order_);
1140 int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
1141 EXPECT_EQ(ERR_IO_PENDING, rv);
1142 EXPECT_EQ(OK, req1.WaitForResult());
1143
1144 // Job 1 finished OK. Start job 2 (also async OK). Request 3 is pending
1145 // without a job.
1146 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
1147
1148 TestSocketRequest req2(pool_.get(), &request_order_);
1149 rv = req2.handle.Init("a", ignored_request_info_, 5, &req2);
1150 EXPECT_EQ(ERR_IO_PENDING, rv);
1151 TestSocketRequest req3(pool_.get(), &request_order_);
1152 rv = req3.handle.Init("a", ignored_request_info_, 5, &req3);
1153 EXPECT_EQ(ERR_IO_PENDING, rv);
1154
1155 // Both Requests 2 and 3 are pending. We release socket 1 which should
1156 // service request 2. Request 3 should still be waiting.
1157 req1.handle.Reset();
1158 MessageLoop::current()->RunAllPending(); // Run the DoReleaseSocket()
1159 ASSERT_TRUE(req2.handle.socket());
1160 EXPECT_EQ(OK, req2.WaitForResult());
1161 EXPECT_FALSE(req3.handle.socket());
1162
1163 // Signal job 2, which should service request 3.
1164
1165 client_socket_factory_.SignalJobs();
1166 EXPECT_EQ(OK, req3.WaitForResult());
1167
1168 ASSERT_EQ(3U, request_order_.size());
1169 EXPECT_EQ(&req1, request_order_[0]);
1170 EXPECT_EQ(&req2, request_order_[1]);
1171 EXPECT_EQ(&req3, request_order_[2]);
1172 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
1173}
1174
1175// The requests are not coupled to the jobs. So, the requests should finish in
1176// their priority / insertion order.
1177TEST_F(ClientSocketPoolBaseTest_LateBinding, PendingJobCompletionOrder) {
1178 CreatePool(kDefaultMaxSocketsPerGroup);
1179 // First two jobs are async.
[email protected]b59ff372009-07-15 22:04:321180 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]5fc08e32009-07-15 17:09:571181
1182 TestSocketRequest req1(pool_.get(), &request_order_);
1183 int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
1184 EXPECT_EQ(ERR_IO_PENDING, rv);
1185
1186 TestSocketRequest req2(pool_.get(), &request_order_);
1187 rv = req2.handle.Init("a", ignored_request_info_, 5, &req2);
1188 EXPECT_EQ(ERR_IO_PENDING, rv);
1189
1190 // The pending job is sync.
[email protected]b59ff372009-07-15 22:04:321191 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
[email protected]5fc08e32009-07-15 17:09:571192
1193 TestSocketRequest req3(pool_.get(), &request_order_);
1194 rv = req3.handle.Init("a", ignored_request_info_, 5, &req3);
1195 EXPECT_EQ(ERR_IO_PENDING, rv);
1196
1197 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult());
1198 EXPECT_EQ(OK, req2.WaitForResult());
1199 EXPECT_EQ(ERR_CONNECTION_FAILED, req3.WaitForResult());
1200
1201 ASSERT_EQ(3U, request_order_.size());
1202 EXPECT_EQ(&req1, request_order_[0]);
1203 EXPECT_EQ(&req2, request_order_[1]);
1204 EXPECT_EQ(&req3, request_order_[2]);
1205}
1206
[email protected]f0109a7d2009-07-16 00:09:521207TEST_F(ClientSocketPoolBaseTest_LateBinding, DISABLED_LoadState) {
[email protected]5fc08e32009-07-15 17:09:571208 CreatePool(kDefaultMaxSocketsPerGroup);
1209 connect_job_factory_->set_job_type(
[email protected]b59ff372009-07-15 22:04:321210 TestConnectJob::kMockAdvancingLoadStateJob);
[email protected]5fc08e32009-07-15 17:09:571211
1212 TestSocketRequest req1(pool_.get(), &request_order_);
1213 int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
1214 EXPECT_EQ(ERR_IO_PENDING, rv);
1215 EXPECT_EQ(LOAD_STATE_IDLE, req1.handle.GetLoadState());
1216
1217 MessageLoop::current()->RunAllPending();
1218
1219 TestSocketRequest req2(pool_.get(), &request_order_);
1220 rv = req2.handle.Init("a", ignored_request_info_, 5, &req2);
1221 EXPECT_EQ(ERR_IO_PENDING, rv);
1222 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, req1.handle.GetLoadState());
1223 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, req2.handle.GetLoadState());
1224}
1225
[email protected]f6d1d6eb2009-06-24 20:16:091226} // namespace
1227
1228} // namespace net