blob: ef9f15f882746433f1afac88e13491b55507a764 [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"
9#include "net/base/host_resolver_unittest.h"
10#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]ab838892009-06-30 18:49:0521const int kMaxSocketsPerGroup = 2;
[email protected]f6d1d6eb2009-06-24 20:16:0922
23// Note that the first and the last are the same, the first should be handled
24// before the last, since it was inserted first.
[email protected]ab838892009-06-30 18:49:0525const int kPriorities[] = { 1, 3, 4, 2, 1 };
[email protected]f6d1d6eb2009-06-24 20:16:0926
27// This is the number of extra requests beyond the first few that use up all
28// available sockets in the socket group.
29const int kNumPendingRequests = arraysize(kPriorities);
30
31const int kNumRequests = kMaxSocketsPerGroup + kNumPendingRequests;
32
33class MockClientSocket : public ClientSocket {
34 public:
35 MockClientSocket() : connected_(false) {}
36
[email protected]ab838892009-06-30 18:49:0537 // Socket methods:
38 virtual int Read(
39 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) {
40 return ERR_UNEXPECTED;
41 }
42
43 virtual int Write(
44 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) {
45 return ERR_UNEXPECTED;
46 }
47
[email protected]f6d1d6eb2009-06-24 20:16:0948 // ClientSocket methods:
[email protected]ab838892009-06-30 18:49:0549
[email protected]f6d1d6eb2009-06-24 20:16:0950 virtual int Connect(CompletionCallback* callback) {
51 connected_ = true;
52 return OK;
53 }
[email protected]f6d1d6eb2009-06-24 20:16:0954
[email protected]ab838892009-06-30 18:49:0555 virtual void Disconnect() { connected_ = false; }
56 virtual bool IsConnected() const { return connected_; }
57 virtual bool IsConnectedAndIdle() const { return connected_; }
58
59#if defined(OS_LINUX)
60 virtual int GetPeerName(struct sockaddr* /* name */,
61 socklen_t* /* namelen */) {
62 return 0;
[email protected]f6d1d6eb2009-06-24 20:16:0963 }
[email protected]ab838892009-06-30 18:49:0564#endif
[email protected]f6d1d6eb2009-06-24 20:16:0965
66 private:
67 bool connected_;
[email protected]f6d1d6eb2009-06-24 20:16:0968
[email protected]ab838892009-06-30 18:49:0569 DISALLOW_COPY_AND_ASSIGN(MockClientSocket);
[email protected]f6d1d6eb2009-06-24 20:16:0970};
71
72class MockClientSocketFactory : public ClientSocketFactory {
73 public:
[email protected]ab838892009-06-30 18:49:0574 MockClientSocketFactory() : allocation_count_(0) {}
[email protected]f6d1d6eb2009-06-24 20:16:0975
76 virtual ClientSocket* CreateTCPClientSocket(const AddressList& addresses) {
77 allocation_count_++;
[email protected]ab838892009-06-30 18:49:0578 return NULL;
[email protected]f6d1d6eb2009-06-24 20:16:0979 }
80
81 virtual SSLClientSocket* CreateSSLClientSocket(
82 ClientSocket* transport_socket,
83 const std::string& hostname,
84 const SSLConfig& ssl_config) {
85 NOTIMPLEMENTED();
86 return NULL;
87 }
88
89 int allocation_count() const { return allocation_count_; }
90
[email protected]f6d1d6eb2009-06-24 20:16:0991 private:
92 int allocation_count_;
[email protected]f6d1d6eb2009-06-24 20:16:0993};
94
95class TestSocketRequest : public CallbackRunner< Tuple1<int> > {
96 public:
97 TestSocketRequest(
98 ClientSocketPool* pool,
99 std::vector<TestSocketRequest*>* request_order)
100 : handle(pool), request_order_(request_order) {}
101
102 ClientSocketHandle handle;
103
104 int WaitForResult() {
105 return callback_.WaitForResult();
106 }
107
108 virtual void RunWithParams(const Tuple1<int>& params) {
109 callback_.RunWithParams(params);
110 completion_count++;
111 request_order_->push_back(this);
112 }
113
114 static int completion_count;
115
116 private:
117 std::vector<TestSocketRequest*>* request_order_;
118 TestCompletionCallback callback_;
119};
120
121int TestSocketRequest::completion_count = 0;
122
[email protected]ab838892009-06-30 18:49:05123class TestConnectJob : public ConnectJob {
124 public:
125 enum JobType {
126 kMockJob,
127 kMockFailingJob,
128 kMockPendingJob,
129 kMockPendingFailingJob,
130 };
131
132 TestConnectJob(JobType job_type,
133 const std::string& group_name,
134 const ClientSocketPoolBase::Request& request,
135 ConnectJob::Delegate* delegate,
136 ClientSocketFactory* client_socket_factory)
137 : job_type_(job_type),
138 group_name_(group_name),
139 handle_(request.handle),
140 client_socket_factory_(client_socket_factory),
141 delegate_(delegate),
142 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
143
144 // ConnectJob methods:
145
146 virtual int Connect() {
147 AddressList ignored;
148 client_socket_factory_->CreateTCPClientSocket(ignored);
149 switch (job_type_) {
150 case kMockJob:
151 return DoConnect(true /* successful */, false /* sync */);
152 case kMockFailingJob:
153 return DoConnect(false /* error */, false /* sync */);
154 case kMockPendingJob:
155 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:
163 MessageLoop::current()->PostTask(
164 FROM_HERE,
165 method_factory_.NewRunnableMethod(
166 &TestConnectJob::DoConnect,
167 false /* error */,
168 true /* async */));
169 return ERR_IO_PENDING;
170 default:
171 NOTREACHED();
172 return ERR_FAILED;
173 }
174 }
175
176 private:
177 int DoConnect(bool succeed, bool was_async) {
178 int result = ERR_CONNECTION_FAILED;
179 ClientSocket* socket = NULL;
180 if (succeed) {
181 result = OK;
182 socket = new MockClientSocket();
183 socket->Connect(NULL);
184 }
185 delegate_->OnConnectJobComplete(
186 group_name_, handle_, socket, result, was_async);
187 return result;
188 }
189
190 const JobType job_type_;
191 const std::string group_name_;
192 const ClientSocketHandle* handle_;
193 ClientSocketFactory* const client_socket_factory_;
194 Delegate* const delegate_;
195 ScopedRunnableMethodFactory<TestConnectJob> method_factory_;
196
197 DISALLOW_COPY_AND_ASSIGN(TestConnectJob);
198};
199
200class TestConnectJobFactory : public ClientSocketPoolBase::ConnectJobFactory {
201 public:
202 explicit TestConnectJobFactory(ClientSocketFactory* client_socket_factory)
203 : job_type_(TestConnectJob::kMockJob),
204 client_socket_factory_(client_socket_factory) {}
205
206 virtual ~TestConnectJobFactory() {}
207
208 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; }
209
210 // ConnectJobFactory methods:
211
212 virtual ConnectJob* NewConnectJob(
213 const std::string& group_name,
214 const ClientSocketPoolBase::Request& request,
215 ConnectJob::Delegate* delegate) const {
216 return new TestConnectJob(job_type_,
217 group_name,
218 request,
219 delegate,
220 client_socket_factory_);
221 }
222
223 private:
224 TestConnectJob::JobType job_type_;
225 ClientSocketFactory* const client_socket_factory_;
226
227 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory);
228};
229
230class TestClientSocketPool : public ClientSocketPool {
231 public:
232 TestClientSocketPool(
233 int max_sockets_per_group,
234 ClientSocketPoolBase::ConnectJobFactory* connect_job_factory)
235 : base_(new ClientSocketPoolBase(
236 kMaxSocketsPerGroup, connect_job_factory)) {}
237
238 virtual int RequestSocket(
239 const std::string& group_name,
240 const HostResolver::RequestInfo& resolve_info,
241 int priority,
242 ClientSocketHandle* handle,
243 CompletionCallback* callback) {
244 return base_->RequestSocket(
245 group_name, resolve_info, priority, handle, callback);
246 }
247
248 virtual void CancelRequest(
249 const std::string& group_name,
250 const ClientSocketHandle* handle) {
251 base_->CancelRequest(group_name, handle);
252 }
253
254 virtual void ReleaseSocket(
255 const std::string& group_name,
256 ClientSocket* socket) {
257 base_->ReleaseSocket(group_name, socket);
258 }
259
260 virtual void CloseIdleSockets() {
261 base_->CloseIdleSockets();
262 }
263
264 virtual int IdleSocketCount() const { return base_->idle_socket_count(); }
265
266 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
267 return base_->IdleSocketCountInGroup(group_name);
268 }
269
270 virtual LoadState GetLoadState(const std::string& group_name,
271 const ClientSocketHandle* handle) const {
272 return base_->GetLoadState(group_name, handle);
273 }
274
275 private:
276 const scoped_refptr<ClientSocketPoolBase> base_;
277
278 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool);
279};
280
281class ClientSocketPoolBaseTest : public testing::Test {
[email protected]f6d1d6eb2009-06-24 20:16:09282 protected:
[email protected]ab838892009-06-30 18:49:05283 ClientSocketPoolBaseTest()
284 : ignored_request_info_("ignored", 80),
285 connect_job_factory_(
286 new TestConnectJobFactory(&client_socket_factory_)),
287 pool_(new TestClientSocketPool(kMaxSocketsPerGroup,
288 connect_job_factory_)) {}
[email protected]f6d1d6eb2009-06-24 20:16:09289
290 virtual void SetUp() {
[email protected]f6d1d6eb2009-06-24 20:16:09291 TestSocketRequest::completion_count = 0;
292 }
293
294 virtual void TearDown() {
295 // The tests often call Reset() on handles at the end which may post
296 // DoReleaseSocket() tasks.
297 MessageLoop::current()->RunAllPending();
298 }
299
[email protected]ab838892009-06-30 18:49:05300 HostResolver::RequestInfo ignored_request_info_;
[email protected]f6d1d6eb2009-06-24 20:16:09301 MockClientSocketFactory client_socket_factory_;
[email protected]ab838892009-06-30 18:49:05302 TestConnectJobFactory* const connect_job_factory_;
[email protected]f6d1d6eb2009-06-24 20:16:09303 scoped_refptr<ClientSocketPool> pool_;
304 std::vector<TestSocketRequest*> request_order_;
305};
306
[email protected]ab838892009-06-30 18:49:05307TEST_F(ClientSocketPoolBaseTest, Basic) {
[email protected]f6d1d6eb2009-06-24 20:16:09308 TestCompletionCallback callback;
309 ClientSocketHandle handle(pool_.get());
[email protected]ab838892009-06-30 18:49:05310 int rv = handle.Init("a", ignored_request_info_, 0, &callback);
311 EXPECT_EQ(OK, rv);
[email protected]f6d1d6eb2009-06-24 20:16:09312 EXPECT_TRUE(handle.is_initialized());
313 EXPECT_TRUE(handle.socket());
[email protected]f6d1d6eb2009-06-24 20:16:09314 handle.Reset();
315}
316
[email protected]ab838892009-06-30 18:49:05317TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) {
318 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09319 TestSocketRequest req(pool_.get(), &request_order_);
[email protected]3ae82302009-06-26 06:01:21320 EXPECT_EQ(ERR_CONNECTION_FAILED,
[email protected]ab838892009-06-30 18:49:05321 req.handle.Init("a", ignored_request_info_, 5, &req));
[email protected]f6d1d6eb2009-06-24 20:16:09322}
323
[email protected]ab838892009-06-30 18:49:05324TEST_F(ClientSocketPoolBaseTest, PendingRequests) {
[email protected]f6d1d6eb2009-06-24 20:16:09325 scoped_ptr<TestSocketRequest> reqs[kNumRequests];
326
327 for (size_t i = 0; i < arraysize(reqs); ++i)
328 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
329
330 // Create connections or queue up requests.
331
[email protected]ab838892009-06-30 18:49:05332 for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
333 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get());
[email protected]f6d1d6eb2009-06-24 20:16:09334 EXPECT_EQ(OK, rv);
335 request_order_.push_back(reqs[i].get());
336 }
337
338 // The rest are pending since we've used all active sockets.
339 for (int i = 0; i < kNumPendingRequests; ++i) {
[email protected]ab838892009-06-30 18:49:05340 int rv = reqs[kMaxSocketsPerGroup + i]->handle.Init(
341 "a", ignored_request_info_, kPriorities[i],
342 reqs[kMaxSocketsPerGroup + i].get());
[email protected]f6d1d6eb2009-06-24 20:16:09343 EXPECT_EQ(ERR_IO_PENDING, rv);
344 }
345
346 // Release any connections until we have no connections.
347 bool released_one;
348 do {
349 released_one = false;
350 for (size_t i = 0; i < arraysize(reqs); ++i) {
351 if (reqs[i]->handle.is_initialized()) {
352 reqs[i]->handle.Reset();
353 MessageLoop::current()->RunAllPending();
354 released_one = true;
355 }
356 }
357 } while (released_one);
358
359 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count());
[email protected]ab838892009-06-30 18:49:05360 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09361
362 for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
363 EXPECT_EQ(request_order_[i], reqs[i].get()) <<
364 "Request " << i << " was not in order.";
365 }
366
367 for (int i = 0; i < kNumPendingRequests - 1; ++i) {
368 int index_in_queue = (kNumPendingRequests - 1) - kPriorities[i];
369 EXPECT_EQ(request_order_[kMaxSocketsPerGroup + index_in_queue],
370 reqs[kMaxSocketsPerGroup + i].get()) <<
371 "Request " << kMaxSocketsPerGroup + i << " was not in order.";
372 }
373
374 EXPECT_EQ(request_order_[arraysize(reqs) - 1],
375 reqs[arraysize(reqs) - 1].get()) <<
376 "The last request with priority 1 should not have been inserted "
377 "earlier into the queue.";
378}
379
[email protected]ab838892009-06-30 18:49:05380TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) {
[email protected]f6d1d6eb2009-06-24 20:16:09381 scoped_ptr<TestSocketRequest> reqs[kNumRequests];
382 for (size_t i = 0; i < arraysize(reqs); ++i)
383 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
384
385 // Create connections or queue up requests.
[email protected]ab838892009-06-30 18:49:05386 for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
387 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get());
[email protected]f6d1d6eb2009-06-24 20:16:09388 EXPECT_EQ(OK, rv);
389 request_order_.push_back(reqs[i].get());
390 }
391
392 // The rest are pending since we've used all active sockets.
393 for (int i = 0; i < kNumPendingRequests; ++i) {
[email protected]ab838892009-06-30 18:49:05394 int rv = reqs[kMaxSocketsPerGroup + i]->handle.Init(
395 "a", ignored_request_info_, kPriorities[i],
396 reqs[kMaxSocketsPerGroup + i].get());
397 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f6d1d6eb2009-06-24 20:16:09398 }
399
400 // Release any connections until we have no connections.
401 bool released_one;
402 do {
403 released_one = false;
404 for (size_t i = 0; i < arraysize(reqs); ++i) {
405 if (reqs[i]->handle.is_initialized()) {
406 reqs[i]->handle.socket()->Disconnect(); // No keep alive.
407 reqs[i]->handle.Reset();
408 MessageLoop::current()->RunAllPending();
409 released_one = true;
410 }
411 }
412 } while (released_one);
413
414 for (int i = kMaxSocketsPerGroup; i < kNumRequests; ++i)
415 EXPECT_EQ(OK, reqs[i]->WaitForResult());
416
417 EXPECT_EQ(kNumRequests, client_socket_factory_.allocation_count());
[email protected]ab838892009-06-30 18:49:05418 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09419}
420
421// This test will start up a RequestSocket() and then immediately Cancel() it.
[email protected]ab838892009-06-30 18:49:05422// The pending connect job will be cancelled and should not call back into
423// ClientSocketPoolBase.
424TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) {
425 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09426 TestSocketRequest req(pool_.get(), &request_order_);
[email protected]ab838892009-06-30 18:49:05427 EXPECT_EQ(ERR_IO_PENDING,
428 req.handle.Init("a", ignored_request_info_, 5, &req));
[email protected]f6d1d6eb2009-06-24 20:16:09429 req.handle.Reset();
[email protected]f6d1d6eb2009-06-24 20:16:09430}
431
[email protected]ab838892009-06-30 18:49:05432TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) {
433 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09434 TestSocketRequest req(pool_.get(), &request_order_);
435 TestSocketRequest req2(pool_.get(), &request_order_);
436
[email protected]ab838892009-06-30 18:49:05437 EXPECT_EQ(ERR_IO_PENDING,
438 req.handle.Init("a", ignored_request_info_, 5, &req));
439 EXPECT_EQ(ERR_IO_PENDING,
440 req2.handle.Init("a", ignored_request_info_, 5, &req2));
[email protected]f6d1d6eb2009-06-24 20:16:09441
442 req.handle.Reset();
443
444 EXPECT_EQ(OK, req2.WaitForResult());
445 req2.handle.Reset();
446}
447
[email protected]ab838892009-06-30 18:49:05448TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) {
449 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09450 ClientSocketHandle handle(pool_.get());
451 TestCompletionCallback callback;
452 TestSocketRequest req(pool_.get(), &request_order_);
453
[email protected]ab838892009-06-30 18:49:05454 EXPECT_EQ(ERR_IO_PENDING,
455 handle.Init("a", ignored_request_info_, 5, &callback));
[email protected]f6d1d6eb2009-06-24 20:16:09456
457 handle.Reset();
458
459 TestCompletionCallback callback2;
[email protected]ab838892009-06-30 18:49:05460 EXPECT_EQ(ERR_IO_PENDING,
461 handle.Init("a", ignored_request_info_, 5, &callback2));
[email protected]f6d1d6eb2009-06-24 20:16:09462
463 EXPECT_EQ(OK, callback2.WaitForResult());
464 EXPECT_FALSE(callback.have_result());
465
466 handle.Reset();
467}
468
[email protected]ab838892009-06-30 18:49:05469TEST_F(ClientSocketPoolBaseTest, CancelRequest) {
[email protected]f6d1d6eb2009-06-24 20:16:09470 scoped_ptr<TestSocketRequest> reqs[kNumRequests];
471
472 for (size_t i = 0; i < arraysize(reqs); ++i)
473 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
474
475 // Create connections or queue up requests.
[email protected]ab838892009-06-30 18:49:05476 for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
477 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get());
[email protected]f6d1d6eb2009-06-24 20:16:09478 EXPECT_EQ(OK, rv);
479 request_order_.push_back(reqs[i].get());
480 }
481
482 // The rest are pending since we've used all active sockets.
483 for (int i = 0; i < kNumPendingRequests; ++i) {
484 EXPECT_EQ(ERR_IO_PENDING, reqs[kMaxSocketsPerGroup + i]->handle.Init(
[email protected]ab838892009-06-30 18:49:05485 "a", ignored_request_info_, kPriorities[i],
486 reqs[kMaxSocketsPerGroup + i].get()));
[email protected]f6d1d6eb2009-06-24 20:16:09487 }
488
489 // Cancel a request.
490 size_t index_to_cancel = kMaxSocketsPerGroup + 2;
491 EXPECT_TRUE(!reqs[index_to_cancel]->handle.is_initialized());
492 reqs[index_to_cancel]->handle.Reset();
493
494 // Release any connections until we have no connections.
495 bool released_one;
496 do {
497 released_one = false;
498 for (size_t i = 0; i < arraysize(reqs); ++i) {
499 if (reqs[i]->handle.is_initialized()) {
500 reqs[i]->handle.Reset();
501 MessageLoop::current()->RunAllPending();
502 released_one = true;
503 }
504 }
505 } while (released_one);
506
507 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count());
[email protected]ab838892009-06-30 18:49:05508 EXPECT_EQ(kNumPendingRequests - 1, TestSocketRequest::completion_count);
[email protected]f6d1d6eb2009-06-24 20:16:09509
510 for (int i = 0; i < kMaxSocketsPerGroup; ++i) {
511 EXPECT_EQ(request_order_[i], reqs[i].get()) <<
512 "Request " << i << " was not in order.";
513 }
514
515 for (int i = 0; i < kNumPendingRequests - 1; ++i) {
516 if (i == 2) continue;
517 int index_in_queue = (kNumPendingRequests - 1) - kPriorities[i];
518 if (kPriorities[i] < kPriorities[index_to_cancel - kMaxSocketsPerGroup])
519 index_in_queue--;
520 EXPECT_EQ(request_order_[kMaxSocketsPerGroup + index_in_queue],
521 reqs[kMaxSocketsPerGroup + i].get()) <<
522 "Request " << kMaxSocketsPerGroup + i << " was not in order.";
523 }
524
525 EXPECT_EQ(request_order_[arraysize(reqs) - 2],
526 reqs[arraysize(reqs) - 1].get()) <<
527 "The last request with priority 1 should not have been inserted "
528 "earlier into the queue.";
529}
530
531class RequestSocketCallback : public CallbackRunner< Tuple1<int> > {
532 public:
533 RequestSocketCallback(ClientSocketHandle* handle)
534 : handle_(handle),
535 within_callback_(false) {}
536
537 virtual void RunWithParams(const Tuple1<int>& params) {
538 callback_.RunWithParams(params);
539 ASSERT_EQ(OK, params.a);
540
541 if (!within_callback_) {
542 handle_->Reset();
543 within_callback_ = true;
544 int rv = handle_->Init(
545 "a", HostResolver::RequestInfo("www.google.com", 80), 0, this);
[email protected]ab838892009-06-30 18:49:05546 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f6d1d6eb2009-06-24 20:16:09547 }
548 }
549
550 int WaitForResult() {
551 return callback_.WaitForResult();
552 }
553
554 private:
555 ClientSocketHandle* const handle_;
556 bool within_callback_;
557 TestCompletionCallback callback_;
558};
559
[email protected]ab838892009-06-30 18:49:05560TEST_F(ClientSocketPoolBaseTest, RequestTwice) {
561 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09562 ClientSocketHandle handle(pool_.get());
563 RequestSocketCallback callback(&handle);
564 int rv = handle.Init(
[email protected]ab838892009-06-30 18:49:05565 "a", ignored_request_info_, 0, &callback);
[email protected]f6d1d6eb2009-06-24 20:16:09566 ASSERT_EQ(ERR_IO_PENDING, rv);
567
568 EXPECT_EQ(OK, callback.WaitForResult());
569
570 handle.Reset();
571}
572
573// Make sure that pending requests get serviced after active requests get
574// cancelled.
[email protected]ab838892009-06-30 18:49:05575TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) {
576 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09577
578 scoped_ptr<TestSocketRequest> reqs[kNumRequests];
579
580 // Queue up all the requests
[email protected]f6d1d6eb2009-06-24 20:16:09581 for (size_t i = 0; i < arraysize(reqs); ++i) {
582 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
[email protected]ab838892009-06-30 18:49:05583 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get());
[email protected]f6d1d6eb2009-06-24 20:16:09584 EXPECT_EQ(ERR_IO_PENDING, rv);
585 }
586
587 // Now, kMaxSocketsPerGroup requests should be active. Let's cancel them.
588 for (int i = 0; i < kMaxSocketsPerGroup; ++i)
589 reqs[i]->handle.Reset();
590
591 // Let's wait for the rest to complete now.
592
593 for (size_t i = kMaxSocketsPerGroup; i < arraysize(reqs); ++i) {
594 EXPECT_EQ(OK, reqs[i]->WaitForResult());
595 reqs[i]->handle.Reset();
596 }
597
598 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count);
599}
600
601// Make sure that pending requests get serviced after active requests fail.
[email protected]ab838892009-06-30 18:49:05602TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) {
603 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
[email protected]f6d1d6eb2009-06-24 20:16:09604
605 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup * 2 + 1];
606
607 // Queue up all the requests
[email protected]f6d1d6eb2009-06-24 20:16:09608 for (size_t i = 0; i < arraysize(reqs); ++i) {
609 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_));
[email protected]ab838892009-06-30 18:49:05610 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get());
[email protected]f6d1d6eb2009-06-24 20:16:09611 EXPECT_EQ(ERR_IO_PENDING, rv);
612 }
613
614 for (size_t i = 0; i < arraysize(reqs); ++i)
615 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult());
616}
617
618} // namespace
619
620} // namespace net