blob: d3c73971c5588090b171dc0b3e743f2ad2bdb862 [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
65class MockClientSocketFactory : public ClientSocketFactory {
66 public:
[email protected]ab838892009-06-30 18:49:0567 MockClientSocketFactory() : allocation_count_(0) {}
[email protected]f6d1d6eb2009-06-24 20:16:0968
69 virtual ClientSocket* CreateTCPClientSocket(const AddressList& addresses) {
70 allocation_count_++;
[email protected]ab838892009-06-30 18:49:0571 return NULL;
[email protected]f6d1d6eb2009-06-24 20:16:0972 }
73
74 virtual SSLClientSocket* CreateSSLClientSocket(
75 ClientSocket* transport_socket,
76 const std::string& hostname,
77 const SSLConfig& ssl_config) {
78 NOTIMPLEMENTED();
79 return NULL;
80 }
81
82 int allocation_count() const { return allocation_count_; }
83
[email protected]f6d1d6eb2009-06-24 20:16:0984 private:
85 int allocation_count_;
[email protected]f6d1d6eb2009-06-24 20:16:0986};
87
88class TestSocketRequest : public CallbackRunner< Tuple1<int> > {
89 public:
90 TestSocketRequest(
91 ClientSocketPool* pool,
92 std::vector<TestSocketRequest*>* request_order)
93 : handle(pool), request_order_(request_order) {}
94
95 ClientSocketHandle handle;
96
97 int WaitForResult() {
98 return callback_.WaitForResult();
99 }
100
101 virtual void RunWithParams(const Tuple1<int>& params) {
102 callback_.RunWithParams(params);
103 completion_count++;
104 request_order_->push_back(this);
105 }
106
[email protected]c9d6a1d2009-07-14 16:15:20107 static size_t completion_count;
[email protected]f6d1d6eb2009-06-24 20:16:09108
109 private:
110 std::vector<TestSocketRequest*>* request_order_;
111 TestCompletionCallback callback_;
112};
113
[email protected]c9d6a1d2009-07-14 16:15:20114size_t TestSocketRequest::completion_count = 0;
[email protected]f6d1d6eb2009-06-24 20:16:09115
[email protected]ab838892009-06-30 18:49:05116class TestConnectJob : public ConnectJob {
117 public:
118 enum JobType {
119 kMockJob,
120 kMockFailingJob,
121 kMockPendingJob,
122 kMockPendingFailingJob,
123 };
124
125 TestConnectJob(JobType job_type,
126 const std::string& group_name,
127 const ClientSocketPoolBase::Request& request,
128 ConnectJob::Delegate* delegate,
129 ClientSocketFactory* client_socket_factory)
[email protected]2ab05b52009-07-01 23:57:58130 : ConnectJob(group_name, request.handle, delegate),
131 job_type_(job_type),
[email protected]ab838892009-06-30 18:49:05132 client_socket_factory_(client_socket_factory),
[email protected]ab838892009-06-30 18:49:05133 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
134
135 // ConnectJob methods:
136
137 virtual int Connect() {
138 AddressList ignored;
139 client_socket_factory_->CreateTCPClientSocket(ignored);
140 switch (job_type_) {
141 case kMockJob:
142 return DoConnect(true /* successful */, false /* sync */);
143 case kMockFailingJob:
144 return DoConnect(false /* error */, false /* sync */);
145 case kMockPendingJob:
146 MessageLoop::current()->PostTask(
147 FROM_HERE,
148 method_factory_.NewRunnableMethod(
149 &TestConnectJob::DoConnect,
150 true /* successful */,
151 true /* async */));
152 return ERR_IO_PENDING;
153 case kMockPendingFailingJob:
154 MessageLoop::current()->PostTask(
155 FROM_HERE,
156 method_factory_.NewRunnableMethod(
157 &TestConnectJob::DoConnect,
158 false /* error */,
159 true /* async */));
160 return ERR_IO_PENDING;
161 default:
162 NOTREACHED();
163 return ERR_FAILED;
164 }
165 }
166
167 private:
168 int DoConnect(bool succeed, bool was_async) {
169 int result = ERR_CONNECTION_FAILED;
[email protected]ab838892009-06-30 18:49:05170 if (succeed) {
171 result = OK;
[email protected]2ab05b52009-07-01 23:57:58172 set_socket(new MockClientSocket());
173 socket()->Connect(NULL);
[email protected]ab838892009-06-30 18:49:05174 }
[email protected]2ab05b52009-07-01 23:57:58175
176 if (was_async)
177 delegate()->OnConnectJobComplete(result, this);
[email protected]ab838892009-06-30 18:49:05178 return result;
179 }
180
181 const JobType job_type_;
[email protected]ab838892009-06-30 18:49:05182 ClientSocketFactory* const client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05183 ScopedRunnableMethodFactory<TestConnectJob> method_factory_;
184
185 DISALLOW_COPY_AND_ASSIGN(TestConnectJob);
186};
187
188class TestConnectJobFactory : public ClientSocketPoolBase::ConnectJobFactory {
189 public:
190 explicit TestConnectJobFactory(ClientSocketFactory* client_socket_factory)
191 : job_type_(TestConnectJob::kMockJob),
192 client_socket_factory_(client_socket_factory) {}
193
194 virtual ~TestConnectJobFactory() {}
195
196 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; }
197
198 // ConnectJobFactory methods:
199
200 virtual ConnectJob* NewConnectJob(
201 const std::string& group_name,
202 const ClientSocketPoolBase::Request& request,
203 ConnectJob::Delegate* delegate) const {
204 return new TestConnectJob(job_type_,
205 group_name,
206 request,
207 delegate,
208 client_socket_factory_);
209 }
210
211 private:
212 TestConnectJob::JobType job_type_;
213 ClientSocketFactory* const client_socket_factory_;
214
215 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory);
216};
217
218class TestClientSocketPool : public ClientSocketPool {
219 public:
220 TestClientSocketPool(
221 int max_sockets_per_group,
222 ClientSocketPoolBase::ConnectJobFactory* connect_job_factory)
223 : base_(new ClientSocketPoolBase(
[email protected]c9d6a1d2009-07-14 16:15:20224 max_sockets_per_group, connect_job_factory)) {}
[email protected]ab838892009-06-30 18:49:05225
226 virtual int RequestSocket(
227 const std::string& group_name,
228 const HostResolver::RequestInfo& resolve_info,
229 int priority,
230 ClientSocketHandle* handle,
231 CompletionCallback* callback) {
232 return base_->RequestSocket(
233 group_name, resolve_info, priority, handle, callback);
234 }
235
236 virtual void CancelRequest(
237 const std::string& group_name,
238 const ClientSocketHandle* handle) {
239 base_->CancelRequest(group_name, handle);
240 }
241
242 virtual void ReleaseSocket(
243 const std::string& group_name,
244 ClientSocket* socket) {
245 base_->ReleaseSocket(group_name, socket);
246 }
247
248 virtual void CloseIdleSockets() {
249 base_->CloseIdleSockets();
250 }
251
252 virtual int IdleSocketCount() const { return base_->idle_socket_count(); }
253
254 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
255 return base_->IdleSocketCountInGroup(group_name);
256 }
257
258 virtual LoadState GetLoadState(const std::string& group_name,
259 const ClientSocketHandle* handle) const {
260 return base_->GetLoadState(group_name, handle);
261 }
262
[email protected]c9d6a1d2009-07-14 16:15:20263 int MaxSocketsPerGroup() const {
264 return base_->max_sockets_per_group();
265 }
266
[email protected]ab838892009-06-30 18:49:05267 private:
268 const scoped_refptr<ClientSocketPoolBase> base_;
269
270 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool);
271};
272
273class ClientSocketPoolBaseTest : public testing::Test {
[email protected]f6d1d6eb2009-06-24 20:16:09274 protected:
[email protected]ab838892009-06-30 18:49:05275 ClientSocketPoolBaseTest()
276 : ignored_request_info_("ignored", 80),
277 connect_job_factory_(
[email protected]c9d6a1d2009-07-14 16:15:20278 new TestConnectJobFactory(&client_socket_factory_)) {}
279
280 void CreatePool(int max_sockets_per_group) {
281 DCHECK(!pool_.get());
282 pool_ = new TestClientSocketPool(max_sockets_per_group,
283 connect_job_factory_);
284 }
[email protected]f6d1d6eb2009-06-24 20:16:09285
286 virtual void SetUp() {
[email protected]f6d1d6eb2009-06-24 20:16:09287 TestSocketRequest::completion_count = 0;
288 }
289
290 virtual void TearDown() {
291 // The tests often call Reset() on handles at the end which may post
292 // DoReleaseSocket() tasks.
293 MessageLoop::current()->RunAllPending();
294 }
295
[email protected]c9d6a1d2009-07-14 16:15:20296 int StartRequest(const std::string& group_name, int priority) {
297 DCHECK(pool_.get());
298 TestSocketRequest* request = new TestSocketRequest(pool_.get(),
299 &request_order_);
300 requests_.push_back(request);
301 int rv = request->handle.Init(group_name, ignored_request_info_, priority,
302 request);
303 if (rv != ERR_IO_PENDING)
304 request_order_.push_back(request);
305 return rv;
306 }
[email protected]0b7648c2009-07-06 20:14:01307
[email protected]c9d6a1d2009-07-14 16:15:20308 static const int kIndexOutOfBounds;
309 static const int kRequestNotFound;
[email protected]0b7648c2009-07-06 20:14:01310
[email protected]c9d6a1d2009-07-14 16:15:20311 int GetOrderOfRequest(size_t index) {
312 index--;
313 if (index >= requests_.size())
314 return kIndexOutOfBounds;
315
316 for (size_t i = 0; i < request_order_.size(); i++)
317 if (requests_[index] == request_order_[i])
318 return i + 1;
319
320 return kRequestNotFound;
[email protected]0b7648c2009-07-06 20:14:01321 }
322
323 enum KeepAlive {
324 KEEP_ALIVE,
325 NO_KEEP_ALIVE,
326 };
327
[email protected]c9d6a1d2009-07-14 16:15:20328 void ReleaseAllConnections(KeepAlive keep_alive) {
[email protected]0b7648c2009-07-06 20:14:01329 bool released_one;
330 do {
331 released_one = false;
[email protected]c9d6a1d2009-07-14 16:15:20332 ScopedVector<TestSocketRequest>::iterator i;
333 for (i = requests_.begin(); i != requests_.end(); ++i) {
334 if ((*i)->handle.is_initialized()) {
[email protected]0b7648c2009-07-06 20:14:01335 if (keep_alive == NO_KEEP_ALIVE)
[email protected]c9d6a1d2009-07-14 16:15:20336 (*i)->handle.socket()->Disconnect();
337 (*i)->handle.Reset();
[email protected]0b7648c2009-07-06 20:14:01338 MessageLoop::current()->RunAllPending();
339 released_one = true;
340 }
341 }
342 } while (released_one);
343 }
344
[email protected]ab838892009-06-30 18:49:05345 HostResolver::RequestInfo ignored_request_info_;
[email protected]f6d1d6eb2009-06-24 20:16:09346 MockClientSocketFactory client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05347 TestConnectJobFactory* const connect_job_factory_;
[email protected]c9d6a1d2009-07-14 16:15:20348 scoped_refptr<TestClientSocketPool> pool_;
349 ScopedVector<TestSocketRequest> requests_;
[email protected]f6d1d6eb2009-06-24 20:16:09350 std::vector<TestSocketRequest*> request_order_;
351};
352
[email protected]c9d6a1d2009-07-14 16:15:20353// static
354const int ClientSocketPoolBaseTest::kIndexOutOfBounds = -1;
355
356// static
357const int ClientSocketPoolBaseTest::kRequestNotFound = -2;
358
[email protected]ab838892009-06-30 18:49:05359TEST_F(ClientSocketPoolBaseTest, Basic) {
[email protected]c9d6a1d2009-07-14 16:15:20360 CreatePool(kDefaultMaxSocketsPerGroup);
361
[email protected]f6d1d6eb2009-06-24 20:16:09362 TestCompletionCallback callback;
363 ClientSocketHandle handle(pool_.get());
[email protected]0b7648c2009-07-06 20:14:01364 EXPECT_EQ(OK, handle.Init("a", ignored_request_info_, kDefaultPriority,
365 &callback));
[email protected]f6d1d6eb2009-06-24 20:16:09366 EXPECT_TRUE(handle.is_initialized());
367 EXPECT_TRUE(handle.socket());
[email protected]f6d1d6eb2009-06-24 20:16:09368 handle.Reset();
369}
370
[email protected]ab838892009-06-30 18:49:05371TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) {
[email protected]c9d6a1d2009-07-14 16:15:20372 CreatePool(kDefaultMaxSocketsPerGroup);
373
[email protected]ab838892009-06-30 18:49:05374 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09375 TestSocketRequest req(pool_.get(), &request_order_);
[email protected]3ae82302009-06-26 06:01:21376 EXPECT_EQ(ERR_CONNECTION_FAILED,
[email protected]0b7648c2009-07-06 20:14:01377 req.handle.Init("a", ignored_request_info_,
378 kDefaultPriority, &req));
[email protected]f6d1d6eb2009-06-24 20:16:09379}
380
[email protected]ab838892009-06-30 18:49:05381TEST_F(ClientSocketPoolBaseTest, PendingRequests) {
[email protected]c9d6a1d2009-07-14 16:15:20382 CreatePool(kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09383
[email protected]c9d6a1d2009-07-14 16:15:20384 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
385 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
386 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
387 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
388 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
389 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
390 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
[email protected]f6d1d6eb2009-06-24 20:16:09391
[email protected]c9d6a1d2009-07-14 16:15:20392 ReleaseAllConnections(KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09393
[email protected]c9d6a1d2009-07-14 16:15:20394 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
395 client_socket_factory_.allocation_count());
396 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
397 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09398
[email protected]c9d6a1d2009-07-14 16:15:20399 EXPECT_EQ(1, GetOrderOfRequest(1));
400 EXPECT_EQ(2, GetOrderOfRequest(2));
401 EXPECT_EQ(6, GetOrderOfRequest(3));
402 EXPECT_EQ(4, GetOrderOfRequest(4));
403 EXPECT_EQ(3, GetOrderOfRequest(5));
404 EXPECT_EQ(5, GetOrderOfRequest(6));
405 EXPECT_EQ(7, GetOrderOfRequest(7));
[email protected]f6d1d6eb2009-06-24 20:16:09406}
407
[email protected]ab838892009-06-30 18:49:05408TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) {
[email protected]c9d6a1d2009-07-14 16:15:20409 CreatePool(kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09410
[email protected]c9d6a1d2009-07-14 16:15:20411 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
412 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
413 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
414 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
415 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
416 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
417 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
[email protected]f6d1d6eb2009-06-24 20:16:09418
[email protected]c9d6a1d2009-07-14 16:15:20419 ReleaseAllConnections(NO_KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09420
[email protected]c9d6a1d2009-07-14 16:15:20421 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i)
422 EXPECT_EQ(OK, requests_[i]->WaitForResult());
423
424 EXPECT_EQ(static_cast<int>(requests_.size()),
425 client_socket_factory_.allocation_count());
426 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
427 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09428}
429
430// This test will start up a RequestSocket() and then immediately Cancel() it.
[email protected]ab838892009-06-30 18:49:05431// The pending connect job will be cancelled and should not call back into
432// ClientSocketPoolBase.
433TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) {
[email protected]c9d6a1d2009-07-14 16:15:20434 CreatePool(kDefaultMaxSocketsPerGroup);
435
[email protected]ab838892009-06-30 18:49:05436 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09437 TestSocketRequest req(pool_.get(), &request_order_);
[email protected]ab838892009-06-30 18:49:05438 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01439 req.handle.Init("a", ignored_request_info_,
440 kDefaultPriority, &req));
[email protected]f6d1d6eb2009-06-24 20:16:09441 req.handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09442}
443
[email protected]ab838892009-06-30 18:49:05444TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) {
[email protected]c9d6a1d2009-07-14 16:15:20445 CreatePool(kDefaultMaxSocketsPerGroup);
446
[email protected]ab838892009-06-30 18:49:05447 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09448 TestSocketRequest req(pool_.get(), &request_order_);
449 TestSocketRequest req2(pool_.get(), &request_order_);
450
[email protected]ab838892009-06-30 18:49:05451 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01452 req.handle.Init("a", ignored_request_info_,
453 kDefaultPriority, &req));
[email protected]ab838892009-06-30 18:49:05454 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01455 req2.handle.Init("a", ignored_request_info_,
456 kDefaultPriority, &req2));
[email protected]f6d1d6eb2009-06-24 20:16:09457
458 req.handle.Reset();
459
460 EXPECT_EQ(OK, req2.WaitForResult());
461 req2.handle.Reset();
462}
463
[email protected]ab838892009-06-30 18:49:05464TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) {
[email protected]c9d6a1d2009-07-14 16:15:20465 CreatePool(kDefaultMaxSocketsPerGroup);
466
[email protected]ab838892009-06-30 18:49:05467 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09468 ClientSocketHandle handle(pool_.get());
469 TestCompletionCallback callback;
470 TestSocketRequest req(pool_.get(), &request_order_);
471
[email protected]ab838892009-06-30 18:49:05472 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01473 handle.Init("a", ignored_request_info_,
474 kDefaultPriority, &callback));
[email protected]f6d1d6eb2009-06-24 20:16:09475
476 handle.Reset();
477
478 TestCompletionCallback callback2;
[email protected]ab838892009-06-30 18:49:05479 EXPECT_EQ(ERR_IO_PENDING,
[email protected]0b7648c2009-07-06 20:14:01480 handle.Init("a", ignored_request_info_,
481 kDefaultPriority, &callback2));
[email protected]f6d1d6eb2009-06-24 20:16:09482
483 EXPECT_EQ(OK, callback2.WaitForResult());
484 EXPECT_FALSE(callback.have_result());
485
486 handle.Reset();
487}
488
[email protected]ab838892009-06-30 18:49:05489TEST_F(ClientSocketPoolBaseTest, CancelRequest) {
[email protected]c9d6a1d2009-07-14 16:15:20490 CreatePool(kDefaultMaxSocketsPerGroup);
[email protected]f6d1d6eb2009-06-24 20:16:09491
[email protected]c9d6a1d2009-07-14 16:15:20492 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
493 EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
494 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
495 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
496 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
497 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
498 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
[email protected]f6d1d6eb2009-06-24 20:16:09499
500 // Cancel a request.
[email protected]c9d6a1d2009-07-14 16:15:20501 size_t index_to_cancel = kDefaultMaxSocketsPerGroup + 2;
502 EXPECT_FALSE(requests_[index_to_cancel]->handle.is_initialized());
503 requests_[index_to_cancel]->handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09504
[email protected]c9d6a1d2009-07-14 16:15:20505 ReleaseAllConnections(KEEP_ALIVE);
[email protected]f6d1d6eb2009-06-24 20:16:09506
[email protected]c9d6a1d2009-07-14 16:15:20507 EXPECT_EQ(kDefaultMaxSocketsPerGroup,
508 client_socket_factory_.allocation_count());
509 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup - 1,
510 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09511
[email protected]c9d6a1d2009-07-14 16:15:20512 EXPECT_EQ(1, GetOrderOfRequest(1));
513 EXPECT_EQ(2, GetOrderOfRequest(2));
514 EXPECT_EQ(5, GetOrderOfRequest(3));
515 EXPECT_EQ(3, GetOrderOfRequest(4));
516 EXPECT_EQ(kRequestNotFound, GetOrderOfRequest(5)); // Canceled request.
517 EXPECT_EQ(4, GetOrderOfRequest(6));
518 EXPECT_EQ(6, GetOrderOfRequest(7));
[email protected]f6d1d6eb2009-06-24 20:16:09519}
520
521class RequestSocketCallback : public CallbackRunner< Tuple1<int> > {
522 public:
[email protected]2ab05b52009-07-01 23:57:58523 RequestSocketCallback(ClientSocketHandle* handle,
524 TestConnectJobFactory* test_connect_job_factory,
525 TestConnectJob::JobType next_job_type)
[email protected]f6d1d6eb2009-06-24 20:16:09526 : handle_(handle),
[email protected]2ab05b52009-07-01 23:57:58527 within_callback_(false),
528 test_connect_job_factory_(test_connect_job_factory),
529 next_job_type_(next_job_type) {}
[email protected]f6d1d6eb2009-06-24 20:16:09530
531 virtual void RunWithParams(const Tuple1<int>& params) {
532 callback_.RunWithParams(params);
533 ASSERT_EQ(OK, params.a);
534
535 if (!within_callback_) {
[email protected]2ab05b52009-07-01 23:57:58536 test_connect_job_factory_->set_job_type(next_job_type_);
[email protected]f6d1d6eb2009-06-24 20:16:09537 handle_->Reset();
538 within_callback_ = true;
539 int rv = handle_->Init(
[email protected]0b7648c2009-07-06 20:14:01540 "a", HostResolver::RequestInfo("www.google.com", 80),
541 kDefaultPriority, this);
[email protected]2ab05b52009-07-01 23:57:58542 switch (next_job_type_) {
543 case TestConnectJob::kMockJob:
544 EXPECT_EQ(OK, rv);
545 break;
546 case TestConnectJob::kMockPendingJob:
547 EXPECT_EQ(ERR_IO_PENDING, rv);
548 break;
549 default:
550 FAIL() << "Unexpected job type: " << next_job_type_;
551 break;
552 }
[email protected]f6d1d6eb2009-06-24 20:16:09553 }
554 }
555
556 int WaitForResult() {
557 return callback_.WaitForResult();
558 }
559
560 private:
561 ClientSocketHandle* const handle_;
562 bool within_callback_;
[email protected]2ab05b52009-07-01 23:57:58563 TestConnectJobFactory* const test_connect_job_factory_;
564 TestConnectJob::JobType next_job_type_;
[email protected]f6d1d6eb2009-06-24 20:16:09565 TestCompletionCallback callback_;
566};
567
[email protected]2ab05b52009-07-01 23:57:58568TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) {
[email protected]c9d6a1d2009-07-14 16:15:20569 CreatePool(kDefaultMaxSocketsPerGroup);
570
[email protected]0b7648c2009-07-06 20:14:01571 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09572 ClientSocketHandle handle(pool_.get());
[email protected]2ab05b52009-07-01 23:57:58573 RequestSocketCallback callback(
574 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09575 int rv = handle.Init(
[email protected]0b7648c2009-07-06 20:14:01576 "a", ignored_request_info_, kDefaultPriority, &callback);
[email protected]f6d1d6eb2009-06-24 20:16:09577 ASSERT_EQ(ERR_IO_PENDING, rv);
578
579 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ab05b52009-07-01 23:57:58580 handle.Reset();
581}
[email protected]f6d1d6eb2009-06-24 20:16:09582
[email protected]2ab05b52009-07-01 23:57:58583TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) {
[email protected]c9d6a1d2009-07-14 16:15:20584 CreatePool(kDefaultMaxSocketsPerGroup);
585
[email protected]0b7648c2009-07-06 20:14:01586 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]2ab05b52009-07-01 23:57:58587 ClientSocketHandle handle(pool_.get());
588 RequestSocketCallback callback(
589 &handle, connect_job_factory_, TestConnectJob::kMockJob);
590 int rv = handle.Init(
[email protected]0b7648c2009-07-06 20:14:01591 "a", ignored_request_info_, kDefaultPriority, &callback);
[email protected]2ab05b52009-07-01 23:57:58592 ASSERT_EQ(ERR_IO_PENDING, rv);
593
594 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]f6d1d6eb2009-06-24 20:16:09595 handle.Reset();
596}
597
598// Make sure that pending requests get serviced after active requests get
599// cancelled.
[email protected]ab838892009-06-30 18:49:05600TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) {
[email protected]c9d6a1d2009-07-14 16:15:20601 CreatePool(kDefaultMaxSocketsPerGroup);
602
[email protected]0b7648c2009-07-06 20:14:01603 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09604
[email protected]c9d6a1d2009-07-14 16:15:20605 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
606 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
607 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
608 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
609 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
610 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
611 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
[email protected]f6d1d6eb2009-06-24 20:16:09612
[email protected]c9d6a1d2009-07-14 16:15:20613 // Now, kDefaultMaxSocketsPerGroup requests should be active.
614 // Let's cancel them.
615 for (int i = 0; i < kDefaultMaxSocketsPerGroup; ++i) {
616 ASSERT_FALSE(requests_[i]->handle.is_initialized());
617 requests_[i]->handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09618 }
619
[email protected]f6d1d6eb2009-06-24 20:16:09620 // Let's wait for the rest to complete now.
[email protected]c9d6a1d2009-07-14 16:15:20621 for (size_t i = kDefaultMaxSocketsPerGroup; i < requests_.size(); ++i) {
622 EXPECT_EQ(OK, requests_[i]->WaitForResult());
623 requests_[i]->handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09624 }
625
[email protected]c9d6a1d2009-07-14 16:15:20626 EXPECT_EQ(requests_.size() - kDefaultMaxSocketsPerGroup,
627 TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09628}
629
630// Make sure that pending requests get serviced after active requests fail.
[email protected]ab838892009-06-30 18:49:05631TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) {
[email protected]c9d6a1d2009-07-14 16:15:20632 CreatePool(kDefaultMaxSocketsPerGroup);
633
[email protected]0b7648c2009-07-06 20:14:01634 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09635
[email protected]c9d6a1d2009-07-14 16:15:20636 scoped_ptr<TestSocketRequest> reqs[kDefaultMaxSocketsPerGroup * 2 + 1];
[email protected]f6d1d6eb2009-06-24 20:16:09637
638 // Queue up all the requests
[email protected]f6d1d6eb2009-06-24 20:16:09639 for (size_t i = 0; i < arraysize(reqs); ++i) {
640 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
[email protected]0b7648c2009-07-06 20:14:01641 int rv = reqs[i]->handle.Init("a", ignored_request_info_,
642 kDefaultPriority, reqs[i].get());
[email protected]f6d1d6eb2009-06-24 20:16:09643 EXPECT_EQ(ERR_IO_PENDING, rv);
644 }
645
646 for (size_t i = 0; i < arraysize(reqs); ++i)
647 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult());
648}
649
[email protected]2ab05b52009-07-01 23:57:58650// A pending asynchronous job completes, which will free up a socket slot. The
651// next job finishes synchronously. The callback for the asynchronous job
652// should be first though.
653TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) {
[email protected]c9d6a1d2009-07-14 16:15:20654 CreatePool(kDefaultMaxSocketsPerGroup);
655
[email protected]2ab05b52009-07-01 23:57:58656 // First two jobs are async.
[email protected]0b7648c2009-07-06 20:14:01657 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]2ab05b52009-07-01 23:57:58658
659 // Start job 1 (async error).
660 TestSocketRequest req1(pool_.get(), &request_order_);
[email protected]0b7648c2009-07-06 20:14:01661 int rv = req1.handle.Init("a", ignored_request_info_,
662 kDefaultPriority, &req1);
[email protected]2ab05b52009-07-01 23:57:58663 EXPECT_EQ(ERR_IO_PENDING, rv);
664
665 // Start job 2 (async error).
666 TestSocketRequest req2(pool_.get(), &request_order_);
[email protected]0b7648c2009-07-06 20:14:01667 rv = req2.handle.Init("a", ignored_request_info_, kDefaultPriority, &req2);
[email protected]2ab05b52009-07-01 23:57:58668 EXPECT_EQ(ERR_IO_PENDING, rv);
669
670 // The pending job is sync.
[email protected]0b7648c2009-07-06 20:14:01671 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
[email protected]2ab05b52009-07-01 23:57:58672
673 // Request 3 does not have a ConnectJob yet. It's just pending.
674 TestSocketRequest req3(pool_.get(), &request_order_);
[email protected]0b7648c2009-07-06 20:14:01675 rv = req3.handle.Init("a", ignored_request_info_, kDefaultPriority, &req3);
[email protected]2ab05b52009-07-01 23:57:58676 EXPECT_EQ(ERR_IO_PENDING, rv);
677
678 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult());
679 EXPECT_EQ(ERR_CONNECTION_FAILED, req2.WaitForResult());
680 EXPECT_EQ(OK, req3.WaitForResult());
681
682 ASSERT_EQ(3U, request_order_.size());
683
684 // After job 1 finishes unsuccessfully, it will try to process the pending
685 // requests queue, so it starts up job 3 for request 3. This job
686 // synchronously succeeds, so the request order is 1, 3, 2.
687 EXPECT_EQ(&req1, request_order_[0]);
688 EXPECT_EQ(&req2, request_order_[2]);
689 EXPECT_EQ(&req3, request_order_[1]);
690}
691
[email protected]f6d1d6eb2009-06-24 20:16:09692} // namespace
693
694} // namespace net