blob: 88746866321c3db2440e8d1a27d22f9a6f17179c [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/host_resolver_unittest.h"
11#include "net/base/net_errors.h"
12#include "net/base/test_completion_callback.h"
13#include "net/socket/client_socket.h"
14#include "net/socket/client_socket_factory.h"
15#include "net/socket/client_socket_handle.h"
16#include "testing/gtest/include/gtest/gtest.h"
17
18namespace net {
19
20namespace {
21
[email protected]c9d6a1d2009-07-14 16:15:2022const int kDefaultMaxSocketsPerGroup = 2;
[email protected]f6d1d6eb2009-06-24 20:16:0923
[email protected]0b7648c2009-07-06 20:14:0124const int kDefaultPriority = 5;
25
[email protected]f6d1d6eb2009-06-24 20:16:0926class MockClientSocket : public ClientSocket {
27 public:
28 MockClientSocket() : connected_(false) {}
29
[email protected]ab838892009-06-30 18:49:0530 // Socket methods:
31 virtual int Read(
32 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) {
33 return ERR_UNEXPECTED;
34 }
35
36 virtual int Write(
37 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) {
38 return ERR_UNEXPECTED;
39 }
40
[email protected]f6d1d6eb2009-06-24 20:16:0941 // ClientSocket methods:
[email protected]ab838892009-06-30 18:49:0542
[email protected]f6d1d6eb2009-06-24 20:16:0943 virtual int Connect(CompletionCallback* callback) {
44 connected_ = true;
45 return OK;
46 }
[email protected]f6d1d6eb2009-06-24 20:16:0947
[email protected]ab838892009-06-30 18:49:0548 virtual void Disconnect() { connected_ = false; }
49 virtual bool IsConnected() const { return connected_; }
50 virtual bool IsConnectedAndIdle() const { return connected_; }
[email protected]0b7648c2009-07-06 20:14:0151
[email protected]ab838892009-06-30 18:49:0552#if defined(OS_LINUX)
53 virtual int GetPeerName(struct sockaddr* /* name */,
54 socklen_t* /* namelen */) {
55 return 0;
[email protected]f6d1d6eb2009-06-24 20:16:0956 }
[email protected]ab838892009-06-30 18:49:0557#endif
[email protected]f6d1d6eb2009-06-24 20:16:0958
59 private:
60 bool connected_;
[email protected]f6d1d6eb2009-06-24 20:16:0961
[email protected]ab838892009-06-30 18:49:0562 DISALLOW_COPY_AND_ASSIGN(MockClientSocket);
[email protected]f6d1d6eb2009-06-24 20:16:0963};
64
[email protected]5fc08e32009-07-15 17:09:5765class TestConnectJob;
66
[email protected]f6d1d6eb2009-06-24 20:16:0967class MockClientSocketFactory : public ClientSocketFactory {
68 public:
[email protected]ab838892009-06-30 18:49:0569 MockClientSocketFactory() : allocation_count_(0) {}
[email protected]f6d1d6eb2009-06-24 20:16:0970
71 virtual ClientSocket* CreateTCPClientSocket(const AddressList& addresses) {
72 allocation_count_++;
[email protected]ab838892009-06-30 18:49:0573 return NULL;
[email protected]f6d1d6eb2009-06-24 20:16:0974 }
75
76 virtual SSLClientSocket* CreateSSLClientSocket(
77 ClientSocket* transport_socket,
78 const std::string& hostname,
79 const SSLConfig& ssl_config) {
80 NOTIMPLEMENTED();
81 return NULL;
82 }
83
[email protected]5fc08e32009-07-15 17:09:5784 void WaitForSignal(TestConnectJob* job) { waiting_jobs_.push_back(job); }
85 void SignalJobs();
86
[email protected]f6d1d6eb2009-06-24 20:16:0987 int allocation_count() const { return allocation_count_; }
88
[email protected]f6d1d6eb2009-06-24 20:16:0989 private:
90 int allocation_count_;
[email protected]5fc08e32009-07-15 17:09:5791 std::vector<TestConnectJob*> waiting_jobs_;
[email protected]f6d1d6eb2009-06-24 20:16:0992};
93
94class TestSocketRequest : public CallbackRunner< Tuple1<int> > {
95 public:
96 TestSocketRequest(
97 ClientSocketPool* pool,
98 std::vector<TestSocketRequest*>* request_order)
99 : handle(pool), request_order_(request_order) {}
100
101 ClientSocketHandle handle;
102
103 int WaitForResult() {
104 return callback_.WaitForResult();
105 }
106
107 virtual void RunWithParams(const Tuple1<int>& params) {
108 callback_.RunWithParams(params);
109 completion_count++;
110 request_order_->push_back(this);
111 }
112
[email protected]c9d6a1d2009-07-14 16:15:20113 static size_t completion_count;
[email protected]f6d1d6eb2009-06-24 20:16:09114
115 private:
116 std::vector<TestSocketRequest*>* request_order_;
117 TestCompletionCallback callback_;
118};
119
[email protected]c9d6a1d2009-07-14 16:15:20120size_t TestSocketRequest::completion_count = 0;
[email protected]f6d1d6eb2009-06-24 20:16:09121
[email protected]ab838892009-06-30 18:49:05122class TestConnectJob : public ConnectJob {
123 public:
124 enum JobType {
125 kMockJob,
126 kMockFailingJob,
127 kMockPendingJob,
128 kMockPendingFailingJob,
[email protected]5fc08e32009-07-15 17:09:57129 kMockWaitingJob,
130 kMockAdvancingLoadStateJob,
[email protected]ab838892009-06-30 18:49:05131 };
132
133 TestConnectJob(JobType job_type,
134 const std::string& group_name,
135 const ClientSocketPoolBase::Request& request,
136 ConnectJob::Delegate* delegate,
[email protected]5fc08e32009-07-15 17:09:57137 MockClientSocketFactory* client_socket_factory)
[email protected]2ab05b52009-07-01 23:57:58138 : ConnectJob(group_name, request.handle, delegate),
139 job_type_(job_type),
[email protected]ab838892009-06-30 18:49:05140 client_socket_factory_(client_socket_factory),
[email protected]ab838892009-06-30 18:49:05141 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
142
143 // ConnectJob methods:
144
145 virtual int Connect() {
146 AddressList ignored;
147 client_socket_factory_->CreateTCPClientSocket(ignored);
148 switch (job_type_) {
149 case kMockJob:
150 return DoConnect(true /* successful */, false /* sync */);
151 case kMockFailingJob:
152 return DoConnect(false /* error */, false /* sync */);
153 case kMockPendingJob:
[email protected]5fc08e32009-07-15 17:09:57154 set_load_state(LOAD_STATE_CONNECTING);
[email protected]ab838892009-06-30 18:49:05155 MessageLoop::current()->PostTask(
156 FROM_HERE,
157 method_factory_.NewRunnableMethod(
158 &TestConnectJob::DoConnect,
159 true /* successful */,
160 true /* async */));
161 return ERR_IO_PENDING;
162 case kMockPendingFailingJob:
[email protected]5fc08e32009-07-15 17:09:57163 set_load_state(LOAD_STATE_CONNECTING);
[email protected]ab838892009-06-30 18:49:05164 MessageLoop::current()->PostTask(
165 FROM_HERE,
166 method_factory_.NewRunnableMethod(
167 &TestConnectJob::DoConnect,
168 false /* error */,
169 true /* async */));
170 return ERR_IO_PENDING;
[email protected]5fc08e32009-07-15 17:09:57171 case kMockWaitingJob:
172 client_socket_factory_->WaitForSignal(this);
173 waiting_success_ = true;
174 return ERR_IO_PENDING;
175 case kMockAdvancingLoadStateJob:
176 MessageLoop::current()->PostTask(
177 FROM_HERE,
178 method_factory_.NewRunnableMethod(
179 &TestConnectJob::AdvanceLoadState, load_state()));
180 return ERR_IO_PENDING;
[email protected]ab838892009-06-30 18:49:05181 default:
182 NOTREACHED();
183 return ERR_FAILED;
184 }
185 }
186
[email protected]5fc08e32009-07-15 17:09:57187 void Signal() {
188 DoConnect(waiting_success_, true /* async */);
189 }
190
[email protected]ab838892009-06-30 18:49:05191 private:
192 int DoConnect(bool succeed, bool was_async) {
193 int result = ERR_CONNECTION_FAILED;
[email protected]ab838892009-06-30 18:49:05194 if (succeed) {
195 result = OK;
[email protected]2ab05b52009-07-01 23:57:58196 set_socket(new MockClientSocket());
197 socket()->Connect(NULL);
[email protected]ab838892009-06-30 18:49:05198 }
[email protected]2ab05b52009-07-01 23:57:58199
200 if (was_async)
201 delegate()->OnConnectJobComplete(result, this);
[email protected]ab838892009-06-30 18:49:05202 return result;
203 }
204
[email protected]5fc08e32009-07-15 17:09:57205 void AdvanceLoadState(LoadState state) {
206 int tmp = state;
207 tmp++;
208 state = static_cast<LoadState>(tmp);
209 set_load_state(state);
210 // Post a delayed task so RunAllPending() won't run it.
211 MessageLoop::current()->PostDelayedTask(
212 FROM_HERE,
213 method_factory_.NewRunnableMethod(&TestConnectJob::AdvanceLoadState,
214 state),
215 1 /* 1ms delay */);
216 }
217
218 bool waiting_success_;
[email protected]ab838892009-06-30 18:49:05219 const JobType job_type_;
[email protected]5fc08e32009-07-15 17:09:57220 MockClientSocketFactory* const client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05221 ScopedRunnableMethodFactory<TestConnectJob> method_factory_;
222
223 DISALLOW_COPY_AND_ASSIGN(TestConnectJob);
224};
225
226class TestConnectJobFactory : public ClientSocketPoolBase::ConnectJobFactory {
227 public:
[email protected]5fc08e32009-07-15 17:09:57228 explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory)
[email protected]ab838892009-06-30 18:49:05229 : job_type_(TestConnectJob::kMockJob),
230 client_socket_factory_(client_socket_factory) {}
231
232 virtual ~TestConnectJobFactory() {}
233
234 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; }
235
236 // ConnectJobFactory methods:
237
238 virtual ConnectJob* NewConnectJob(
239 const std::string& group_name,
240 const ClientSocketPoolBase::Request& request,
241 ConnectJob::Delegate* delegate) const {
242 return new TestConnectJob(job_type_,
243 group_name,
244 request,
245 delegate,
246 client_socket_factory_);
247 }
248
249 private:
250 TestConnectJob::JobType job_type_;
[email protected]5fc08e32009-07-15 17:09:57251 MockClientSocketFactory* const client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05252
253 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory);
254};
255
256class TestClientSocketPool : public ClientSocketPool {
257 public:
258 TestClientSocketPool(
259 int max_sockets_per_group,
260 ClientSocketPoolBase::ConnectJobFactory* connect_job_factory)
261 : base_(new ClientSocketPoolBase(
[email protected]c9d6a1d2009-07-14 16:15:20262 max_sockets_per_group, connect_job_factory)) {}
[email protected]ab838892009-06-30 18:49:05263
264 virtual int RequestSocket(
265 const std::string& group_name,
266 const HostResolver::RequestInfo& resolve_info,
267 int priority,
268 ClientSocketHandle* handle,
269 CompletionCallback* callback) {
270 return base_->RequestSocket(
271 group_name, resolve_info, priority, handle, callback);
272 }
273
274 virtual void CancelRequest(
275 const std::string& group_name,
276 const ClientSocketHandle* handle) {
277 base_->CancelRequest(group_name, handle);
278 }
279
280 virtual void ReleaseSocket(
281 const std::string& group_name,
282 ClientSocket* socket) {
283 base_->ReleaseSocket(group_name, socket);
284 }
285
286 virtual void CloseIdleSockets() {
287 base_->CloseIdleSockets();
288 }
289
290 virtual int IdleSocketCount() const { return base_->idle_socket_count(); }
291
292 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
293 return base_->IdleSocketCountInGroup(group_name);
294 }
295
296 virtual LoadState GetLoadState(const std::string& group_name,
297 const ClientSocketHandle* handle) const {
298 return base_->GetLoadState(group_name, handle);
299 }
300
[email protected]c9d6a1d2009-07-14 16:15:20301 int MaxSocketsPerGroup() const {
302 return base_->max_sockets_per_group();
303 }
304
[email protected]ab838892009-06-30 18:49:05305 private:
306 const scoped_refptr<ClientSocketPoolBase> base_;
307
308 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool);
309};
310
[email protected]5fc08e32009-07-15 17:09:57311void MockClientSocketFactory::SignalJobs() {
312 for (std::vector<TestConnectJob*>::iterator it = waiting_jobs_.begin();
313 it != waiting_jobs_.end(); ++it) {
314 (*it)->Signal();
315 }
316 waiting_jobs_.clear();
317}
318
[email protected]ab838892009-06-30 18:49:05319class ClientSocketPoolBaseTest : public testing::Test {
[email protected]f6d1d6eb2009-06-24 20:16:09320 protected:
[email protected]ab838892009-06-30 18:49:05321 ClientSocketPoolBaseTest()
322 : ignored_request_info_("ignored", 80),
323 connect_job_factory_(
[email protected]c9d6a1d2009-07-14 16:15:20324 new TestConnectJobFactory(&client_socket_factory_)) {}
325
326 void CreatePool(int max_sockets_per_group) {
327 DCHECK(!pool_.get());
328 pool_ = new TestClientSocketPool(max_sockets_per_group,
329 connect_job_factory_);
330 }
[email protected]f6d1d6eb2009-06-24 20:16:09331
332 virtual void SetUp() {
[email protected]f6d1d6eb2009-06-24 20:16:09333 TestSocketRequest::completion_count = 0;
334 }
335
336 virtual void TearDown() {
337 // The tests often call Reset() on handles at the end which may post
338 // DoReleaseSocket() tasks.
339 MessageLoop::current()->RunAllPending();
[email protected]5fc08e32009-07-15 17:09:57340 // Need to delete |pool_| before we turn late binding back off.
341 // TODO(willchan): Remove this line when late binding becomes the default.
342 pool_ = NULL;
343 ClientSocketPoolBase::EnableLateBindingOfSockets(false);
[email protected]f6d1d6eb2009-06-24 20:16:09344 }
345
[email protected]c9d6a1d2009-07-14 16:15:20346 int StartRequest(const std::string& group_name, int priority) {
347 DCHECK(pool_.get());
348 TestSocketRequest* request = new TestSocketRequest(pool_.get(),
349 &request_order_);
350 requests_.push_back(request);
351 int rv = request->handle.Init(group_name, ignored_request_info_, priority,
352 request);
353 if (rv != ERR_IO_PENDING)
354 request_order_.push_back(request);
355 return rv;
356 }
[email protected]0b7648c2009-07-06 20:14:01357
[email protected]c9d6a1d2009-07-14 16:15:20358 static const int kIndexOutOfBounds;
359 static const int kRequestNotFound;
[email protected]0b7648c2009-07-06 20:14:01360
[email protected]c9d6a1d2009-07-14 16:15:20361 int GetOrderOfRequest(size_t index) {
362 index--;
363 if (index >= requests_.size())
364 return kIndexOutOfBounds;
365
366 for (size_t i = 0; i < request_order_.size(); i++)
367 if (requests_[index] == request_order_[i])
368 return i + 1;
369
370 return kRequestNotFound;
[email protected]0b7648c2009-07-06 20:14:01371 }
372
373 enum KeepAlive {
374 KEEP_ALIVE,
375 NO_KEEP_ALIVE,
376 };
377
[email protected]c9d6a1d2009-07-14 16:15:20378 void ReleaseAllConnections(KeepAlive keep_alive) {
[email protected]0b7648c2009-07-06 20:14:01379 bool released_one;
380 do {
381 released_one = false;
[email protected]c9d6a1d2009-07-14 16:15:20382 ScopedVector<TestSocketRequest>::iterator i;
383 for (i = requests_.begin(); i != requests_.end(); ++i) {
384 if ((*i)->handle.is_initialized()) {
[email protected]0b7648c2009-07-06 20:14:01385 if (keep_alive == NO_KEEP_ALIVE)
[email protected]c9d6a1d2009-07-14 16:15:20386 (*i)->handle.socket()->Disconnect();
387 (*i)->handle.Reset();
[email protected]0b7648c2009-07-06 20:14:01388 MessageLoop::current()->RunAllPending();
389 released_one = true;
390 }
391 }
392 } while (released_one);
393 }
394
[email protected]ab838892009-06-30 18:49:05395 HostResolver::RequestInfo ignored_request_info_;
[email protected]f6d1d6eb2009-06-24 20:16:09396 MockClientSocketFactory client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05397 TestConnectJobFactory* const connect_job_factory_;
[email protected]c9d6a1d2009-07-14 16:15:20398 scoped_refptr<TestClientSocketPool> pool_;
399 ScopedVector<TestSocketRequest> requests_;
[email protected]f6d1d6eb2009-06-24 20:16:09400 std::vector<TestSocketRequest*> request_order_;
401};
402
[email protected]c9d6a1d2009-07-14 16:15:20403// static
404const int ClientSocketPoolBaseTest::kIndexOutOfBounds = -1;
405
406// static
407const int ClientSocketPoolBaseTest::kRequestNotFound = -2;
408
[email protected]5fc08e32009-07-15 17:09:57409TEST_F(ClientSocketPoolBaseTest, BasicSynchronous) {
[email protected]c9d6a1d2009-07-14 16:15:20410 CreatePool(kDefaultMaxSocketsPerGroup);
411
[email protected]f6d1d6eb2009-06-24 20:16:09412 TestCompletionCallback callback;
413 ClientSocketHandle handle(pool_.get());
[email protected]0b7648c2009-07-06 20:14:01414 EXPECT_EQ(OK, handle.Init("a", ignored_request_info_, kDefaultPriority,
415 &callback));
[email protected]f6d1d6eb2009-06-24 20:16:09416 EXPECT_TRUE(handle.is_initialized());
417 EXPECT_TRUE(handle.socket());
[email protected]f6d1d6eb2009-06-24 20:16:09418 handle.Reset();
419}
420
[email protected]5fc08e32009-07-15 17:09:57421TEST_F(ClientSocketPoolBaseTest, BasicAsynchronous) {
422 CreatePool(kDefaultMaxSocketsPerGroup);
423
424 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
425 TestSocketRequest req(pool_.get(), &request_order_);
426 int rv = req.handle.Init("a", ignored_request_info_, 0, &req);
427 EXPECT_EQ(ERR_IO_PENDING, rv);
428 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &req.handle));
429 EXPECT_EQ(OK, req.WaitForResult());
430 EXPECT_TRUE(req.handle.is_initialized());
431 EXPECT_TRUE(req.handle.socket());
432 req.handle.Reset();
433}
434
[email protected]ab838892009-06-30 18:49:05435TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) {
[email protected]c9d6a1d2009-07-14 16:15:20436 CreatePool(kDefaultMaxSocketsPerGroup);
437
[email protected]ab838892009-06-30 18:49:05438 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09439 TestSocketRequest req(pool_.get(), &request_order_);
[email protected]3ae82302009-06-26 06:01:21440 EXPECT_EQ(ERR_CONNECTION_FAILED,
[email protected]0b7648c2009-07-06 20:14:01441 req.handle.Init("a", ignored_request_info_,
442 kDefaultPriority, &req));
[email protected]f6d1d6eb2009-06-24 20:16:09443}
444
[email protected]5fc08e32009-07-15 17:09:57445TEST_F(ClientSocketPoolBaseTest, InitConnectionAsynchronousFailure) {
446 CreatePool(kDefaultMaxSocketsPerGroup);
447
448 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
449 TestSocketRequest req(pool_.get(), &request_order_);
450 EXPECT_EQ(ERR_IO_PENDING,
451 req.handle.Init("a", ignored_request_info_, 5, &req));
452 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &req.handle));
453 EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult());
454}
455
[email protected]ab838892009-06-30 18:49:05456TEST_F(ClientSocketPoolBaseTest, PendingRequests) {
[email protected]c9d6a1d2009-07-14 16:15:20457 CreatePool(kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09458
[email protected]c9d6a1d2009-07-14 16:15:20459 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
460 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
461 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
462 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
463 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
464 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
465 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
[email protected]f6d1d6eb2009-06-24 20:16:09466
[email protected]c9d6a1d2009-07-14 16:15:20467 ReleaseAllConnections(KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09468
[email protected]c9d6a1d2009-07-14 16:15:20469 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
470 client_socket_factory_.allocation_count());
471 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
472 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09473
[email protected]c9d6a1d2009-07-14 16:15:20474 EXPECT_EQ(1, GetOrderOfRequest(1));
475 EXPECT_EQ(2, GetOrderOfRequest(2));
476 EXPECT_EQ(6, GetOrderOfRequest(3));
477 EXPECT_EQ(4, GetOrderOfRequest(4));
478 EXPECT_EQ(3, GetOrderOfRequest(5));
479 EXPECT_EQ(5, GetOrderOfRequest(6));
480 EXPECT_EQ(7, GetOrderOfRequest(7));
[email protected]f6d1d6eb2009-06-24 20:16:09481}
482
[email protected]ab838892009-06-30 18:49:05483TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) {
[email protected]c9d6a1d2009-07-14 16:15:20484 CreatePool(kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09485
[email protected]c9d6a1d2009-07-14 16:15:20486 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
487 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
488 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
489 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
490 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
491 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
492 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
[email protected]f6d1d6eb2009-06-24 20:16:09493
[email protected]c9d6a1d2009-07-14 16:15:20494 ReleaseAllConnections(NO_KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09495
[email protected]c9d6a1d2009-07-14 16:15:20496 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i)
497 EXPECT_EQ(OK, requests_[i]->WaitForResult());
498
499 EXPECT_EQ(static_cast<int>(requests_.size()),
500 client_socket_factory_.allocation_count());
501 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
502 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09503}
504
505// This test will start up a RequestSocket() and then immediately Cancel() it.
[email protected]ab838892009-06-30 18:49:05506// The pending connect job will be cancelled and should not call back into
507// ClientSocketPoolBase.
508TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) {
[email protected]c9d6a1d2009-07-14 16:15:20509 CreatePool(kDefaultMaxSocketsPerGroup);
510
[email protected]ab838892009-06-30 18:49:05511 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09512 TestSocketRequest req(pool_.get(), &request_order_);
[email protected]ab838892009-06-30 18:49:05513 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01514 req.handle.Init("a", ignored_request_info_,
515 kDefaultPriority, &req));
[email protected]f6d1d6eb2009-06-24 20:16:09516 req.handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09517}
518
[email protected]ab838892009-06-30 18:49:05519TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) {
[email protected]c9d6a1d2009-07-14 16:15:20520 CreatePool(kDefaultMaxSocketsPerGroup);
521
[email protected]ab838892009-06-30 18:49:05522 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09523 TestSocketRequest req(pool_.get(), &request_order_);
524 TestSocketRequest req2(pool_.get(), &request_order_);
525
[email protected]ab838892009-06-30 18:49:05526 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01527 req.handle.Init("a", ignored_request_info_,
528 kDefaultPriority, &req));
[email protected]ab838892009-06-30 18:49:05529 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01530 req2.handle.Init("a", ignored_request_info_,
531 kDefaultPriority, &req2));
[email protected]f6d1d6eb2009-06-24 20:16:09532
533 req.handle.Reset();
534
535 EXPECT_EQ(OK, req2.WaitForResult());
536 req2.handle.Reset();
537}
538
[email protected]ab838892009-06-30 18:49:05539TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) {
[email protected]c9d6a1d2009-07-14 16:15:20540 CreatePool(kDefaultMaxSocketsPerGroup);
541
[email protected]ab838892009-06-30 18:49:05542 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09543 ClientSocketHandle handle(pool_.get());
544 TestCompletionCallback callback;
545 TestSocketRequest req(pool_.get(), &request_order_);
546
[email protected]ab838892009-06-30 18:49:05547 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01548 handle.Init("a", ignored_request_info_,
549 kDefaultPriority, &callback));
[email protected]f6d1d6eb2009-06-24 20:16:09550
551 handle.Reset();
552
553 TestCompletionCallback callback2;
[email protected]ab838892009-06-30 18:49:05554 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01555 handle.Init("a", ignored_request_info_,
556 kDefaultPriority, &callback2));
[email protected]f6d1d6eb2009-06-24 20:16:09557
558 EXPECT_EQ(OK, callback2.WaitForResult());
559 EXPECT_FALSE(callback.have_result());
560
561 handle.Reset();
562}
563
[email protected]ab838892009-06-30 18:49:05564TEST_F(ClientSocketPoolBaseTest, CancelRequest) {
[email protected]c9d6a1d2009-07-14 16:15:20565 CreatePool(kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09566
[email protected]c9d6a1d2009-07-14 16:15:20567 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
568 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
569 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
570 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
571 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
572 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
573 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
[email protected]f6d1d6eb2009-06-24 20:16:09574
575 // Cancel a request.
[email protected]c9d6a1d2009-07-14 16:15:20576 size_t index_to_cancel = kDefaultMaxSocketsPerGroup + 2;
577 EXPECT_FALSE(requests_[index_to_cancel]->handle.is_initialized());
578 requests_[index_to_cancel]->handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09579
[email protected]c9d6a1d2009-07-14 16:15:20580 ReleaseAllConnections(KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09581
[email protected]c9d6a1d2009-07-14 16:15:20582 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
583 client_socket_factory_.allocation_count());
584 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup - 1,
585 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09586
[email protected]c9d6a1d2009-07-14 16:15:20587 EXPECT_EQ(1, GetOrderOfRequest(1));
588 EXPECT_EQ(2, GetOrderOfRequest(2));
589 EXPECT_EQ(5, GetOrderOfRequest(3));
590 EXPECT_EQ(3, GetOrderOfRequest(4));
591 EXPECT_EQ(kRequestNotFound, GetOrderOfRequest(5)); // Canceled request.
592 EXPECT_EQ(4, GetOrderOfRequest(6));
593 EXPECT_EQ(6, GetOrderOfRequest(7));
[email protected]f6d1d6eb2009-06-24 20:16:09594}
595
596class RequestSocketCallback : public CallbackRunner< Tuple1<int> > {
597 public:
[email protected]2ab05b52009-07-01 23:57:58598 RequestSocketCallback(ClientSocketHandle* handle,
599 TestConnectJobFactory* test_connect_job_factory,
600 TestConnectJob::JobType next_job_type)
[email protected]f6d1d6eb2009-06-24 20:16:09601 : handle_(handle),
[email protected]2ab05b52009-07-01 23:57:58602 within_callback_(false),
603 test_connect_job_factory_(test_connect_job_factory),
604 next_job_type_(next_job_type) {}
[email protected]f6d1d6eb2009-06-24 20:16:09605
606 virtual void RunWithParams(const Tuple1<int>& params) {
607 callback_.RunWithParams(params);
608 ASSERT_EQ(OK, params.a);
609
610 if (!within_callback_) {
[email protected]2ab05b52009-07-01 23:57:58611 test_connect_job_factory_->set_job_type(next_job_type_);
[email protected]f6d1d6eb2009-06-24 20:16:09612 handle_->Reset();
613 within_callback_ = true;
614 int rv = handle_->Init(
[email protected]0b7648c2009-07-06 20:14:01615 "a", HostResolver::RequestInfo("www.google.com", 80),
616 kDefaultPriority, this);
[email protected]2ab05b52009-07-01 23:57:58617 switch (next_job_type_) {
618 case TestConnectJob::kMockJob:
619 EXPECT_EQ(OK, rv);
620 break;
621 case TestConnectJob::kMockPendingJob:
622 EXPECT_EQ(ERR_IO_PENDING, rv);
623 break;
624 default:
625 FAIL() << "Unexpected job type: " << next_job_type_;
626 break;
627 }
[email protected]f6d1d6eb2009-06-24 20:16:09628 }
629 }
630
631 int WaitForResult() {
632 return callback_.WaitForResult();
633 }
634
635 private:
636 ClientSocketHandle* const handle_;
637 bool within_callback_;
[email protected]2ab05b52009-07-01 23:57:58638 TestConnectJobFactory* const test_connect_job_factory_;
639 TestConnectJob::JobType next_job_type_;
[email protected]f6d1d6eb2009-06-24 20:16:09640 TestCompletionCallback callback_;
641};
642
[email protected]2ab05b52009-07-01 23:57:58643TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) {
[email protected]c9d6a1d2009-07-14 16:15:20644 CreatePool(kDefaultMaxSocketsPerGroup);
645
[email protected]0b7648c2009-07-06 20:14:01646 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09647 ClientSocketHandle handle(pool_.get());
[email protected]2ab05b52009-07-01 23:57:58648 RequestSocketCallback callback(
649 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09650 int rv = handle.Init(
[email protected]0b7648c2009-07-06 20:14:01651 "a", ignored_request_info_, kDefaultPriority, &callback);
[email protected]f6d1d6eb2009-06-24 20:16:09652 ASSERT_EQ(ERR_IO_PENDING, rv);
653
654 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ab05b52009-07-01 23:57:58655 handle.Reset();
656}
[email protected]f6d1d6eb2009-06-24 20:16:09657
[email protected]2ab05b52009-07-01 23:57:58658TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) {
[email protected]c9d6a1d2009-07-14 16:15:20659 CreatePool(kDefaultMaxSocketsPerGroup);
660
[email protected]0b7648c2009-07-06 20:14:01661 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]2ab05b52009-07-01 23:57:58662 ClientSocketHandle handle(pool_.get());
663 RequestSocketCallback callback(
664 &handle, connect_job_factory_, TestConnectJob::kMockJob);
665 int rv = handle.Init(
[email protected]0b7648c2009-07-06 20:14:01666 "a", ignored_request_info_, kDefaultPriority, &callback);
[email protected]2ab05b52009-07-01 23:57:58667 ASSERT_EQ(ERR_IO_PENDING, rv);
668
669 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]f6d1d6eb2009-06-24 20:16:09670 handle.Reset();
671}
672
673// Make sure that pending requests get serviced after active requests get
674// cancelled.
[email protected]ab838892009-06-30 18:49:05675TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) {
[email protected]c9d6a1d2009-07-14 16:15:20676 CreatePool(kDefaultMaxSocketsPerGroup);
677
[email protected]0b7648c2009-07-06 20:14:01678 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09679
[email protected]c9d6a1d2009-07-14 16:15:20680 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));
686 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
[email protected]f6d1d6eb2009-06-24 20:16:09687
[email protected]c9d6a1d2009-07-14 16:15:20688 // Now, kDefaultMaxSocketsPerGroup requests should be active.
689 // Let's cancel them.
690 for (int i = 0; i < kDefaultMaxSocketsPerGroup; ++i) {
691 ASSERT_FALSE(requests_[i]->handle.is_initialized());
692 requests_[i]->handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09693 }
694
[email protected]f6d1d6eb2009-06-24 20:16:09695 // Let's wait for the rest to complete now.
[email protected]c9d6a1d2009-07-14 16:15:20696 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i) {
697 EXPECT_EQ(OK, requests_[i]->WaitForResult());
698 requests_[i]->handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09699 }
700
[email protected]c9d6a1d2009-07-14 16:15:20701 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
702 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09703}
704
705// Make sure that pending requests get serviced after active requests fail.
[email protected]ab838892009-06-30 18:49:05706TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) {
[email protected]c9d6a1d2009-07-14 16:15:20707 CreatePool(kDefaultMaxSocketsPerGroup);
708
[email protected]0b7648c2009-07-06 20:14:01709 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09710
[email protected]c9d6a1d2009-07-14 16:15:20711 scoped_ptr<TestSocketRequest> reqs[kDefaultMaxSocketsPerGroup * 2 + 1];
[email protected]f6d1d6eb2009-06-24 20:16:09712
713 // Queue up all the requests
[email protected]f6d1d6eb2009-06-24 20:16:09714 for (size_t i = 0; i < arraysize(reqs); ++i) {
715 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
[email protected]0b7648c2009-07-06 20:14:01716 int rv = reqs[i]->handle.Init("a", ignored_request_info_,
717 kDefaultPriority, reqs[i].get());
[email protected]f6d1d6eb2009-06-24 20:16:09718 EXPECT_EQ(ERR_IO_PENDING, rv);
719 }
720
721 for (size_t i = 0; i < arraysize(reqs); ++i)
722 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult());
723}
724
[email protected]5fc08e32009-07-15 17:09:57725TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestThenRequestSocket) {
726 CreatePool(kDefaultMaxSocketsPerGroup);
727
728 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
729
730 TestSocketRequest req(pool_.get(), &request_order_);
731 int rv = req.handle.Init(
732 "a", ignored_request_info_, kDefaultPriority, &req);
733 EXPECT_EQ(ERR_IO_PENDING, rv);
734
735 // Cancel the active request.
736 req.handle.Reset();
737
738 rv = req.handle.Init("a", ignored_request_info_, kDefaultPriority, &req);
739 EXPECT_EQ(ERR_IO_PENDING, rv);
740 EXPECT_EQ(OK, req.WaitForResult());
741
742 EXPECT_FALSE(req.handle.is_reused());
743 EXPECT_EQ(1U, TestSocketRequest::completion_count);
744 EXPECT_EQ(2, client_socket_factory_.allocation_count());
745}
746
[email protected]2ab05b52009-07-01 23:57:58747// A pending asynchronous job completes, which will free up a socket slot. The
748// next job finishes synchronously. The callback for the asynchronous job
749// should be first though.
750TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) {
[email protected]c9d6a1d2009-07-14 16:15:20751 CreatePool(kDefaultMaxSocketsPerGroup);
752
[email protected]2ab05b52009-07-01 23:57:58753 // First two jobs are async.
[email protected]0b7648c2009-07-06 20:14:01754 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]2ab05b52009-07-01 23:57:58755
756 // Start job 1 (async error).
757 TestSocketRequest req1(pool_.get(), &request_order_);
[email protected]0b7648c2009-07-06 20:14:01758 int rv = req1.handle.Init("a", ignored_request_info_,
759 kDefaultPriority, &req1);
[email protected]2ab05b52009-07-01 23:57:58760 EXPECT_EQ(ERR_IO_PENDING, rv);
761
762 // Start job 2 (async error).
763 TestSocketRequest req2(pool_.get(), &request_order_);
[email protected]0b7648c2009-07-06 20:14:01764 rv = req2.handle.Init("a", ignored_request_info_, kDefaultPriority, &req2);
[email protected]2ab05b52009-07-01 23:57:58765 EXPECT_EQ(ERR_IO_PENDING, rv);
766
767 // The pending job is sync.
[email protected]0b7648c2009-07-06 20:14:01768 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
[email protected]2ab05b52009-07-01 23:57:58769
770 // Request 3 does not have a ConnectJob yet. It's just pending.
771 TestSocketRequest req3(pool_.get(), &request_order_);
[email protected]0b7648c2009-07-06 20:14:01772 rv = req3.handle.Init("a", ignored_request_info_, kDefaultPriority, &req3);
[email protected]2ab05b52009-07-01 23:57:58773 EXPECT_EQ(ERR_IO_PENDING, rv);
774
775 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult());
776 EXPECT_EQ(ERR_CONNECTION_FAILED, req2.WaitForResult());
777 EXPECT_EQ(OK, req3.WaitForResult());
778
779 ASSERT_EQ(3U, request_order_.size());
780
781 // After job 1 finishes unsuccessfully, it will try to process the pending
782 // requests queue, so it starts up job 3 for request 3. This job
783 // synchronously succeeds, so the request order is 1, 3, 2.
784 EXPECT_EQ(&req1, request_order_[0]);
785 EXPECT_EQ(&req2, request_order_[2]);
786 EXPECT_EQ(&req3, request_order_[1]);
787}
788
[email protected]5fc08e32009-07-15 17:09:57789// When a ConnectJob is coupled to a request, even if a free socket becomes
790// available, the request will be serviced by the ConnectJob.
791TEST_F(ClientSocketPoolBaseTest, ReleaseSockets) {
792 CreatePool(kDefaultMaxSocketsPerGroup);
793 ClientSocketPoolBase::EnableLateBindingOfSockets(false);
794
795 // Start job 1 (async OK)
796 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
797
798 TestSocketRequest req1(pool_.get(), &request_order_);
799 int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
800 EXPECT_EQ(ERR_IO_PENDING, rv);
801 EXPECT_EQ(OK, req1.WaitForResult());
802
803 // Job 1 finished OK. Start job 2 (also async OK). Release socket 1.
804 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
805
806 TestSocketRequest req2(pool_.get(), &request_order_);
807 rv = req2.handle.Init("a", ignored_request_info_, 5, &req2);
808 EXPECT_EQ(ERR_IO_PENDING, rv);
809 req1.handle.Reset();
810 MessageLoop::current()->RunAllPending(); // Run the DoReleaseSocket()
811
812 // Job 2 is pending. Start request 3 (which has no associated job since it
813 // will use the idle socket).
814
815 TestSocketRequest req3(pool_.get(), &request_order_);
816 rv = req3.handle.Init("a", ignored_request_info_, 5, &req3);
817 EXPECT_EQ(OK, rv);
818
819 EXPECT_FALSE(req2.handle.socket());
820 client_socket_factory_.SignalJobs();
821 EXPECT_EQ(OK, req2.WaitForResult());
822
823 ASSERT_EQ(2U, request_order_.size());
824 EXPECT_EQ(&req1, request_order_[0]);
825 EXPECT_EQ(&req2, request_order_[1]);
826 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
827}
828
829class ClientSocketPoolBaseTest_LateBinding : public ClientSocketPoolBaseTest {
830 protected:
831 virtual void SetUp() {
832 ClientSocketPoolBaseTest::SetUp();
833 ClientSocketPoolBase::EnableLateBindingOfSockets(true);
834 }
835};
836
837TEST_F(ClientSocketPoolBaseTest_LateBinding, BasicSynchronous) {
838 CreatePool(kDefaultMaxSocketsPerGroup);
839
840 TestCompletionCallback callback;
841 ClientSocketHandle handle(pool_.get());
842 EXPECT_EQ(OK, handle.Init("a", ignored_request_info_, kDefaultPriority,
843 &callback));
844 EXPECT_TRUE(handle.is_initialized());
845 EXPECT_TRUE(handle.socket());
846 handle.Reset();
847}
848
849TEST_F(ClientSocketPoolBaseTest_LateBinding, BasicAsynchronous) {
850 CreatePool(kDefaultMaxSocketsPerGroup);
851
852 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
853 TestSocketRequest req(pool_.get(), &request_order_);
854 int rv = req.handle.Init("a", ignored_request_info_, 0, &req);
855 EXPECT_EQ(ERR_IO_PENDING, rv);
856 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &req.handle));
857 EXPECT_EQ(OK, req.WaitForResult());
858 EXPECT_TRUE(req.handle.is_initialized());
859 EXPECT_TRUE(req.handle.socket());
860 req.handle.Reset();
861}
862
863TEST_F(ClientSocketPoolBaseTest_LateBinding, InitConnectionFailure) {
864 CreatePool(kDefaultMaxSocketsPerGroup);
865
866 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
867 TestSocketRequest req(pool_.get(), &request_order_);
868 EXPECT_EQ(ERR_CONNECTION_FAILED,
869 req.handle.Init("a", ignored_request_info_,
870 kDefaultPriority, &req));
871}
872
873TEST_F(ClientSocketPoolBaseTest_LateBinding,
874 InitConnectionAsynchronousFailure) {
875 CreatePool(kDefaultMaxSocketsPerGroup);
876
877 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
878 TestSocketRequest req(pool_.get(), &request_order_);
879 EXPECT_EQ(ERR_IO_PENDING,
880 req.handle.Init("a", ignored_request_info_, 5, &req));
881 EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &req.handle));
882 EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult());
883}
884
885TEST_F(ClientSocketPoolBaseTest_LateBinding, PendingRequests) {
886 CreatePool(kDefaultMaxSocketsPerGroup);
887
888 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
889 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
890 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
891 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
892 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
893 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
894 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
895
896 ReleaseAllConnections(KEEP_ALIVE);
897
898 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
899 client_socket_factory_.allocation_count());
900 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
901 TestSocketRequest::completion_count);
902
903 EXPECT_EQ(1, GetOrderOfRequest(1));
904 EXPECT_EQ(2, GetOrderOfRequest(2));
905 EXPECT_EQ(6, GetOrderOfRequest(3));
906 EXPECT_EQ(4, GetOrderOfRequest(4));
907 EXPECT_EQ(3, GetOrderOfRequest(5));
908 EXPECT_EQ(5, GetOrderOfRequest(6));
909 EXPECT_EQ(7, GetOrderOfRequest(7));
910}
911
912TEST_F(ClientSocketPoolBaseTest_LateBinding, PendingRequests_NoKeepAlive) {
913 CreatePool(kDefaultMaxSocketsPerGroup);
914
915 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
916 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
917 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
918 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
919 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
920 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
921 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
922
923 ReleaseAllConnections(NO_KEEP_ALIVE);
924
925 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i)
926 EXPECT_EQ(OK, requests_[i]->WaitForResult());
927
928 EXPECT_EQ(static_cast<int>(requests_.size()),
929 client_socket_factory_.allocation_count());
930 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
931 TestSocketRequest::completion_count);
932}
933
934// This test will start up a RequestSocket() and then immediately Cancel() it.
935// The pending connect job will be cancelled and should not call back into
936// ClientSocketPoolBase.
937TEST_F(ClientSocketPoolBaseTest_LateBinding, CancelRequestClearGroup) {
938 CreatePool(kDefaultMaxSocketsPerGroup);
939
940 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
941 TestSocketRequest req(pool_.get(), &request_order_);
942 EXPECT_EQ(ERR_IO_PENDING,
943 req.handle.Init("a", ignored_request_info_,
944 kDefaultPriority, &req));
945 req.handle.Reset();
946}
947
948TEST_F(ClientSocketPoolBaseTest_LateBinding, TwoRequestsCancelOne) {
949 CreatePool(kDefaultMaxSocketsPerGroup);
950
951 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
952 TestSocketRequest req(pool_.get(), &request_order_);
953 TestSocketRequest req2(pool_.get(), &request_order_);
954
955 EXPECT_EQ(ERR_IO_PENDING,
956 req.handle.Init("a", ignored_request_info_,
957 kDefaultPriority, &req));
958 EXPECT_EQ(ERR_IO_PENDING,
959 req2.handle.Init("a", ignored_request_info_,
960 kDefaultPriority, &req2));
961
962 req.handle.Reset();
963
964 EXPECT_EQ(OK, req2.WaitForResult());
965 req2.handle.Reset();
966}
967
968TEST_F(ClientSocketPoolBaseTest_LateBinding, ConnectCancelConnect) {
969 CreatePool(kDefaultMaxSocketsPerGroup);
970
971 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
972 ClientSocketHandle handle(pool_.get());
973 TestCompletionCallback callback;
974 TestSocketRequest req(pool_.get(), &request_order_);
975
976 EXPECT_EQ(ERR_IO_PENDING,
977 handle.Init("a", ignored_request_info_,
978 kDefaultPriority, &callback));
979
980 handle.Reset();
981
982 TestCompletionCallback callback2;
983 EXPECT_EQ(ERR_IO_PENDING,
984 handle.Init("a", ignored_request_info_,
985 kDefaultPriority, &callback2));
986
987 EXPECT_EQ(OK, callback2.WaitForResult());
988 EXPECT_FALSE(callback.have_result());
989
990 handle.Reset();
991}
992
993TEST_F(ClientSocketPoolBaseTest_LateBinding, CancelRequest) {
994 CreatePool(kDefaultMaxSocketsPerGroup);
995
996 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
997 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
998 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
999 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
1000 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
1001 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
1002 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
1003
1004 // Cancel a request.
1005 size_t index_to_cancel = kDefaultMaxSocketsPerGroup + 2;
1006 EXPECT_FALSE(requests_[index_to_cancel]->handle.is_initialized());
1007 requests_[index_to_cancel]->handle.Reset();
1008
1009 ReleaseAllConnections(KEEP_ALIVE);
1010
1011 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
1012 client_socket_factory_.allocation_count());
1013 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup - 1,
1014 TestSocketRequest::completion_count);
1015
1016 EXPECT_EQ(1, GetOrderOfRequest(1));
1017 EXPECT_EQ(2, GetOrderOfRequest(2));
1018 EXPECT_EQ(5, GetOrderOfRequest(3));
1019 EXPECT_EQ(3, GetOrderOfRequest(4));
1020 EXPECT_EQ(kRequestNotFound, GetOrderOfRequest(5)); // Canceled request.
1021 EXPECT_EQ(4, GetOrderOfRequest(6));
1022 EXPECT_EQ(6, GetOrderOfRequest(7));
1023}
1024
1025TEST_F(ClientSocketPoolBaseTest_LateBinding, RequestPendingJobTwice) {
1026 CreatePool(kDefaultMaxSocketsPerGroup);
1027
1028 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1029 ClientSocketHandle handle(pool_.get());
1030 RequestSocketCallback callback(
1031 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob);
1032 int rv = handle.Init(
1033 "a", ignored_request_info_, kDefaultPriority, &callback);
1034 ASSERT_EQ(ERR_IO_PENDING, rv);
1035
1036 EXPECT_EQ(OK, callback.WaitForResult());
1037 handle.Reset();
1038}
1039
1040TEST_F(ClientSocketPoolBaseTest_LateBinding, RequestPendingJobThenSynchronous) {
1041 CreatePool(kDefaultMaxSocketsPerGroup);
1042
1043 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1044 ClientSocketHandle handle(pool_.get());
1045 RequestSocketCallback callback(
1046 &handle, connect_job_factory_, TestConnectJob::kMockJob);
1047 int rv = handle.Init(
1048 "a", ignored_request_info_, kDefaultPriority, &callback);
1049 ASSERT_EQ(ERR_IO_PENDING, rv);
1050
1051 EXPECT_EQ(OK, callback.WaitForResult());
1052 handle.Reset();
1053}
1054
1055// Make sure that pending requests get serviced after active requests get
1056// cancelled.
1057TEST_F(ClientSocketPoolBaseTest_LateBinding,
1058 CancelActiveRequestWithPendingRequests) {
1059 CreatePool(kDefaultMaxSocketsPerGroup);
1060
1061 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1062
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 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
1070
1071 // Now, kDefaultMaxSocketsPerGroup requests should be active.
1072 // Let's cancel them.
1073 for (int i = 0; i < kDefaultMaxSocketsPerGroup; ++i) {
1074 ASSERT_FALSE(requests_[i]->handle.is_initialized());
1075 requests_[i]->handle.Reset();
1076 }
1077
1078 // Let's wait for the rest to complete now.
1079 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i) {
1080 EXPECT_EQ(OK, requests_[i]->WaitForResult());
1081 requests_[i]->handle.Reset();
1082 }
1083
1084 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
1085 TestSocketRequest::completion_count);
1086}
1087
1088// Make sure that pending requests get serviced after active requests fail.
1089TEST_F(ClientSocketPoolBaseTest_LateBinding,
1090 FailingActiveRequestWithPendingRequests) {
1091 CreatePool(kDefaultMaxSocketsPerGroup);
1092
1093 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
1094
1095 scoped_ptr<TestSocketRequest> reqs[kDefaultMaxSocketsPerGroup * 2 + 1];
1096
1097 // Queue up all the requests
1098 for (size_t i = 0; i < arraysize(reqs); ++i) {
1099 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
1100 int rv = reqs[i]->handle.Init("a", ignored_request_info_,
1101 kDefaultPriority, reqs[i].get());
1102 EXPECT_EQ(ERR_IO_PENDING, rv);
1103 }
1104
1105 for (size_t i = 0; i < arraysize(reqs); ++i)
1106 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult());
1107}
1108
1109TEST_F(ClientSocketPoolBaseTest_LateBinding,
1110 CancelActiveRequestThenRequestSocket) {
1111 CreatePool(kDefaultMaxSocketsPerGroup);
1112
1113 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1114
1115 TestSocketRequest req(pool_.get(), &request_order_);
1116 int rv = req.handle.Init(
1117 "a", ignored_request_info_, kDefaultPriority, &req);
1118 EXPECT_EQ(ERR_IO_PENDING, rv);
1119
1120 // Cancel the active request.
1121 req.handle.Reset();
1122
1123 rv = req.handle.Init("a", ignored_request_info_, kDefaultPriority, &req);
1124 EXPECT_EQ(ERR_IO_PENDING, rv);
1125 EXPECT_EQ(OK, req.WaitForResult());
1126
1127 EXPECT_FALSE(req.handle.is_reused());
1128 EXPECT_EQ(1U, TestSocketRequest::completion_count);
1129 EXPECT_EQ(2, client_socket_factory_.allocation_count());
1130}
1131
1132// When requests and ConnectJobs are not coupled, the request will get serviced
1133// by whatever comes first.
1134TEST_F(ClientSocketPoolBaseTest_LateBinding, ReleaseSockets) {
1135 CreatePool(kDefaultMaxSocketsPerGroup);
1136
1137 // Start job 1 (async OK)
1138 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1139
1140 TestSocketRequest req1(pool_.get(), &request_order_);
1141 int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
1142 EXPECT_EQ(ERR_IO_PENDING, rv);
1143 EXPECT_EQ(OK, req1.WaitForResult());
1144
1145 // Job 1 finished OK. Start job 2 (also async OK). Request 3 is pending
1146 // without a job.
1147 connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
1148
1149 TestSocketRequest req2(pool_.get(), &request_order_);
1150 rv = req2.handle.Init("a", ignored_request_info_, 5, &req2);
1151 EXPECT_EQ(ERR_IO_PENDING, rv);
1152 TestSocketRequest req3(pool_.get(), &request_order_);
1153 rv = req3.handle.Init("a", ignored_request_info_, 5, &req3);
1154 EXPECT_EQ(ERR_IO_PENDING, rv);
1155
1156 // Both Requests 2 and 3 are pending. We release socket 1 which should
1157 // service request 2. Request 3 should still be waiting.
1158 req1.handle.Reset();
1159 MessageLoop::current()->RunAllPending(); // Run the DoReleaseSocket()
1160 ASSERT_TRUE(req2.handle.socket());
1161 EXPECT_EQ(OK, req2.WaitForResult());
1162 EXPECT_FALSE(req3.handle.socket());
1163
1164 // Signal job 2, which should service request 3.
1165
1166 client_socket_factory_.SignalJobs();
1167 EXPECT_EQ(OK, req3.WaitForResult());
1168
1169 ASSERT_EQ(3U, request_order_.size());
1170 EXPECT_EQ(&req1, request_order_[0]);
1171 EXPECT_EQ(&req2, request_order_[1]);
1172 EXPECT_EQ(&req3, request_order_[2]);
1173 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
1174}
1175
1176// The requests are not coupled to the jobs. So, the requests should finish in
1177// their priority / insertion order.
1178TEST_F(ClientSocketPoolBaseTest_LateBinding, PendingJobCompletionOrder) {
1179 CreatePool(kDefaultMaxSocketsPerGroup);
1180 // First two jobs are async.
1181 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
1182
1183 TestSocketRequest req1(pool_.get(), &request_order_);
1184 int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
1185 EXPECT_EQ(ERR_IO_PENDING, rv);
1186
1187 TestSocketRequest req2(pool_.get(), &request_order_);
1188 rv = req2.handle.Init("a", ignored_request_info_, 5, &req2);
1189 EXPECT_EQ(ERR_IO_PENDING, rv);
1190
1191 // The pending job is sync.
1192 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
1193
1194 TestSocketRequest req3(pool_.get(), &request_order_);
1195 rv = req3.handle.Init("a", ignored_request_info_, 5, &req3);
1196 EXPECT_EQ(ERR_IO_PENDING, rv);
1197
1198 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult());
1199 EXPECT_EQ(OK, req2.WaitForResult());
1200 EXPECT_EQ(ERR_CONNECTION_FAILED, req3.WaitForResult());
1201
1202 ASSERT_EQ(3U, request_order_.size());
1203 EXPECT_EQ(&req1, request_order_[0]);
1204 EXPECT_EQ(&req2, request_order_[1]);
1205 EXPECT_EQ(&req3, request_order_[2]);
1206}
1207
1208TEST_F(ClientSocketPoolBaseTest_LateBinding, LoadState) {
1209 CreatePool(kDefaultMaxSocketsPerGroup);
1210 connect_job_factory_->set_job_type(
1211 TestConnectJob::kMockAdvancingLoadStateJob);
1212
1213 TestSocketRequest req1(pool_.get(), &request_order_);
1214 int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
1215 EXPECT_EQ(ERR_IO_PENDING, rv);
1216 EXPECT_EQ(LOAD_STATE_IDLE, req1.handle.GetLoadState());
1217
1218 MessageLoop::current()->RunAllPending();
1219
1220 TestSocketRequest req2(pool_.get(), &request_order_);
1221 rv = req2.handle.Init("a", ignored_request_info_, 5, &req2);
1222 EXPECT_EQ(ERR_IO_PENDING, rv);
1223 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, req1.handle.GetLoadState());
1224 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, req2.handle.GetLoadState());
1225}
1226
[email protected]f6d1d6eb2009-06-24 20:16:091227} // namespace
1228
1229} // namespace net