OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/socket/client_socket_pool_base.h" | 5 #include "net/socket/client_socket_pool_base.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "net/base/host_resolver_unittest.h" | 9 #include "net/base/host_resolver_unittest.h" |
10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
23 // Note that the first and the last are the same, the first should be handled | 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. | 24 // before the last, since it was inserted first. |
25 const int kPriorities[] = { 1, 3, 4, 2, 1 }; | 25 const int kPriorities[] = { 1, 3, 4, 2, 1 }; |
26 | 26 |
27 // This is the number of extra requests beyond the first few that use up all | 27 // This is the number of extra requests beyond the first few that use up all |
28 // available sockets in the socket group. | 28 // available sockets in the socket group. |
29 const int kNumPendingRequests = arraysize(kPriorities); | 29 const int kNumPendingRequests = arraysize(kPriorities); |
30 | 30 |
31 const int kNumRequests = kMaxSocketsPerGroup + kNumPendingRequests; | 31 const int kNumRequests = kMaxSocketsPerGroup + kNumPendingRequests; |
32 | 32 |
33 const int kDefaultPriority = 5; | |
34 | |
33 class MockClientSocket : public ClientSocket { | 35 class MockClientSocket : public ClientSocket { |
34 public: | 36 public: |
35 MockClientSocket() : connected_(false) {} | 37 MockClientSocket() : connected_(false) {} |
36 | 38 |
37 // Socket methods: | 39 // Socket methods: |
38 virtual int Read( | 40 virtual int Read( |
39 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) { | 41 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) { |
40 return ERR_UNEXPECTED; | 42 return ERR_UNEXPECTED; |
41 } | 43 } |
42 | 44 |
43 virtual int Write( | 45 virtual int Write( |
44 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) { | 46 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) { |
45 return ERR_UNEXPECTED; | 47 return ERR_UNEXPECTED; |
46 } | 48 } |
47 | 49 |
48 // ClientSocket methods: | 50 // ClientSocket methods: |
49 | 51 |
50 virtual int Connect(CompletionCallback* callback) { | 52 virtual int Connect(CompletionCallback* callback) { |
51 connected_ = true; | 53 connected_ = true; |
52 return OK; | 54 return OK; |
53 } | 55 } |
54 | 56 |
55 virtual void Disconnect() { connected_ = false; } | 57 virtual void Disconnect() { connected_ = false; } |
56 virtual bool IsConnected() const { return connected_; } | 58 virtual bool IsConnected() const { return connected_; } |
57 virtual bool IsConnectedAndIdle() const { return connected_; } | 59 virtual bool IsConnectedAndIdle() const { return connected_; } |
58 | 60 |
59 #if defined(OS_LINUX) | 61 #if defined(OS_LINUX) |
60 virtual int GetPeerName(struct sockaddr* /* name */, | 62 virtual int GetPeerName(struct sockaddr* /* name */, |
61 socklen_t* /* namelen */) { | 63 socklen_t* /* namelen */) { |
62 return 0; | 64 return 0; |
63 } | 65 } |
64 #endif | 66 #endif |
65 | 67 |
66 private: | 68 private: |
67 bool connected_; | 69 bool connected_; |
68 | 70 |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 virtual void SetUp() { | 287 virtual void SetUp() { |
286 TestSocketRequest::completion_count = 0; | 288 TestSocketRequest::completion_count = 0; |
287 } | 289 } |
288 | 290 |
289 virtual void TearDown() { | 291 virtual void TearDown() { |
290 // The tests often call Reset() on handles at the end which may post | 292 // The tests often call Reset() on handles at the end which may post |
291 // DoReleaseSocket() tasks. | 293 // DoReleaseSocket() tasks. |
292 MessageLoop::current()->RunAllPending(); | 294 MessageLoop::current()->RunAllPending(); |
293 } | 295 } |
294 | 296 |
297 void CreateConnections(scoped_ptr<TestSocketRequest>* reqs, size_t count) { | |
willchan no longer on Chromium
2009/07/06 17:11:03
It strikes me as odd that you have |count| as a va
| |
298 for (size_t i = 0; i < count; ++i) | |
299 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | |
300 | |
301 // Create connections or queue up requests. | |
302 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | |
303 int rv = reqs[i]->handle.Init("a", ignored_request_info_, | |
304 kDefaultPriority, reqs[i].get()); | |
305 EXPECT_EQ(OK, rv); | |
306 request_order_.push_back(reqs[i].get()); | |
307 } | |
308 | |
309 // The rest are pending since we've used all active sockets. | |
310 for (int i = 0; i < kNumPendingRequests; ++i) { | |
311 int rv = reqs[kMaxSocketsPerGroup + i]->handle.Init( | |
312 "a", ignored_request_info_, kPriorities[i], | |
313 reqs[kMaxSocketsPerGroup + i].get()); | |
314 EXPECT_EQ(ERR_IO_PENDING, rv); | |
315 } | |
316 } | |
317 | |
318 enum KeepAlive { | |
319 KEEP_ALIVE, | |
320 NO_KEEP_ALIVE, | |
321 }; | |
322 | |
323 void ReleaseAllConnections(scoped_ptr<TestSocketRequest>* reqs, | |
324 size_t count, KeepAlive keep_alive) { | |
325 bool released_one; | |
326 do { | |
327 released_one = false; | |
328 for (size_t i = 0; i < count; ++i) { | |
329 if (reqs[i]->handle.is_initialized()) { | |
330 if (keep_alive == NO_KEEP_ALIVE) | |
331 reqs[i]->handle.socket()->Disconnect(); | |
332 reqs[i]->handle.Reset(); | |
333 MessageLoop::current()->RunAllPending(); | |
334 released_one = true; | |
335 } | |
336 } | |
337 } while (released_one); | |
338 } | |
339 | |
295 HostResolver::RequestInfo ignored_request_info_; | 340 HostResolver::RequestInfo ignored_request_info_; |
296 MockClientSocketFactory client_socket_factory_; | 341 MockClientSocketFactory client_socket_factory_; |
297 TestConnectJobFactory* const connect_job_factory_; | 342 TestConnectJobFactory* const connect_job_factory_; |
298 scoped_refptr<ClientSocketPool> pool_; | 343 scoped_refptr<ClientSocketPool> pool_; |
299 std::vector<TestSocketRequest*> request_order_; | 344 std::vector<TestSocketRequest*> request_order_; |
300 }; | 345 }; |
301 | 346 |
302 TEST_F(ClientSocketPoolBaseTest, Basic) { | 347 TEST_F(ClientSocketPoolBaseTest, Basic) { |
303 TestCompletionCallback callback; | 348 TestCompletionCallback callback; |
304 ClientSocketHandle handle(pool_.get()); | 349 ClientSocketHandle handle(pool_.get()); |
305 int rv = handle.Init("a", ignored_request_info_, 0, &callback); | 350 EXPECT_EQ(OK, handle.Init("a", ignored_request_info_, kDefaultPriority, |
306 EXPECT_EQ(OK, rv); | 351 &callback)); |
307 EXPECT_TRUE(handle.is_initialized()); | 352 EXPECT_TRUE(handle.is_initialized()); |
308 EXPECT_TRUE(handle.socket()); | 353 EXPECT_TRUE(handle.socket()); |
309 handle.Reset(); | 354 handle.Reset(); |
310 } | 355 } |
311 | 356 |
312 TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) { | 357 TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) { |
313 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob); | 358 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob); |
314 TestSocketRequest req(pool_.get(), &request_order_); | 359 TestSocketRequest req(pool_.get(), &request_order_); |
315 EXPECT_EQ(ERR_CONNECTION_FAILED, | 360 EXPECT_EQ(ERR_CONNECTION_FAILED, |
316 req.handle.Init("a", ignored_request_info_, 5, &req)); | 361 req.handle.Init("a", ignored_request_info_, |
362 kDefaultPriority, &req)); | |
317 } | 363 } |
318 | 364 |
319 TEST_F(ClientSocketPoolBaseTest, PendingRequests) { | 365 TEST_F(ClientSocketPoolBaseTest, PendingRequests) { |
320 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 366 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
321 | 367 |
322 for (size_t i = 0; i < arraysize(reqs); ++i) | 368 CreateConnections(reqs, arraysize(reqs)); |
323 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | 369 ReleaseAllConnections(reqs, arraysize(reqs), KEEP_ALIVE); |
324 | |
325 // Create connections or queue up requests. | |
326 | |
327 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | |
328 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); | |
329 EXPECT_EQ(OK, rv); | |
330 request_order_.push_back(reqs[i].get()); | |
331 } | |
332 | |
333 // The rest are pending since we've used all active sockets. | |
334 for (int i = 0; i < kNumPendingRequests; ++i) { | |
335 int rv = reqs[kMaxSocketsPerGroup + i]->handle.Init( | |
336 "a", ignored_request_info_, kPriorities[i], | |
337 reqs[kMaxSocketsPerGroup + i].get()); | |
338 EXPECT_EQ(ERR_IO_PENDING, rv); | |
339 } | |
340 | |
341 // Release any connections until we have no connections. | |
342 bool released_one; | |
343 do { | |
344 released_one = false; | |
345 for (size_t i = 0; i < arraysize(reqs); ++i) { | |
346 if (reqs[i]->handle.is_initialized()) { | |
347 reqs[i]->handle.Reset(); | |
348 MessageLoop::current()->RunAllPending(); | |
349 released_one = true; | |
350 } | |
351 } | |
352 } while (released_one); | |
353 | 370 |
354 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); | 371 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); |
355 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); | 372 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); |
356 | 373 |
357 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | 374 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { |
358 EXPECT_EQ(request_order_[i], reqs[i].get()) << | 375 EXPECT_EQ(request_order_[i], reqs[i].get()) << |
359 "Request " << i << " was not in order."; | 376 "Request " << i << " was not in order."; |
360 } | 377 } |
361 | 378 |
362 for (int i = 0; i < kNumPendingRequests - 1; ++i) { | 379 for (int i = 0; i < kNumPendingRequests - 1; ++i) { |
363 int index_in_queue = (kNumPendingRequests - 1) - kPriorities[i]; | 380 int index_in_queue = (kNumPendingRequests - 1) - kPriorities[i]; |
364 EXPECT_EQ(request_order_[kMaxSocketsPerGroup + index_in_queue], | 381 EXPECT_EQ(request_order_[kMaxSocketsPerGroup + index_in_queue], |
365 reqs[kMaxSocketsPerGroup + i].get()) << | 382 reqs[kMaxSocketsPerGroup + i].get()) << |
366 "Request " << kMaxSocketsPerGroup + i << " was not in order."; | 383 "Request " << kMaxSocketsPerGroup + i << " was not in order."; |
367 } | 384 } |
368 | 385 |
369 EXPECT_EQ(request_order_[arraysize(reqs) - 1], | 386 EXPECT_EQ(request_order_[arraysize(reqs) - 1], |
370 reqs[arraysize(reqs) - 1].get()) << | 387 reqs[arraysize(reqs) - 1].get()) << |
371 "The last request with priority 1 should not have been inserted " | 388 "The last request with priority 1 should not have been inserted " |
372 "earlier into the queue."; | 389 "earlier into the queue."; |
373 } | 390 } |
374 | 391 |
375 TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) { | 392 TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) { |
376 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 393 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
377 for (size_t i = 0; i < arraysize(reqs); ++i) | |
378 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | |
379 | 394 |
380 // Create connections or queue up requests. | 395 CreateConnections(reqs, arraysize(reqs)); |
381 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | 396 ReleaseAllConnections(reqs, arraysize(reqs), NO_KEEP_ALIVE); |
382 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); | |
383 EXPECT_EQ(OK, rv); | |
384 request_order_.push_back(reqs[i].get()); | |
385 } | |
386 | |
387 // The rest are pending since we've used all active sockets. | |
388 for (int i = 0; i < kNumPendingRequests; ++i) { | |
389 int rv = reqs[kMaxSocketsPerGroup + i]->handle.Init( | |
390 "a", ignored_request_info_, kPriorities[i], | |
391 reqs[kMaxSocketsPerGroup + i].get()); | |
392 EXPECT_EQ(ERR_IO_PENDING, rv); | |
393 } | |
394 | |
395 // Release any connections until we have no connections. | |
396 bool released_one; | |
397 do { | |
398 released_one = false; | |
399 for (size_t i = 0; i < arraysize(reqs); ++i) { | |
400 if (reqs[i]->handle.is_initialized()) { | |
401 reqs[i]->handle.socket()->Disconnect(); // No keep alive. | |
402 reqs[i]->handle.Reset(); | |
403 MessageLoop::current()->RunAllPending(); | |
404 released_one = true; | |
405 } | |
406 } | |
407 } while (released_one); | |
408 | 397 |
409 for (int i = kMaxSocketsPerGroup; i < kNumRequests; ++i) | 398 for (int i = kMaxSocketsPerGroup; i < kNumRequests; ++i) |
410 EXPECT_EQ(OK, reqs[i]->WaitForResult()); | 399 EXPECT_EQ(OK, reqs[i]->WaitForResult()); |
411 | 400 |
412 EXPECT_EQ(kNumRequests, client_socket_factory_.allocation_count()); | 401 EXPECT_EQ(kNumRequests, client_socket_factory_.allocation_count()); |
413 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); | 402 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); |
414 } | 403 } |
415 | 404 |
416 // This test will start up a RequestSocket() and then immediately Cancel() it. | 405 // This test will start up a RequestSocket() and then immediately Cancel() it. |
417 // The pending connect job will be cancelled and should not call back into | 406 // The pending connect job will be cancelled and should not call back into |
418 // ClientSocketPoolBase. | 407 // ClientSocketPoolBase. |
419 TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) { | 408 TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) { |
420 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 409 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
421 TestSocketRequest req(pool_.get(), &request_order_); | 410 TestSocketRequest req(pool_.get(), &request_order_); |
422 EXPECT_EQ(ERR_IO_PENDING, | 411 EXPECT_EQ(ERR_IO_PENDING, |
423 req.handle.Init("a", ignored_request_info_, 5, &req)); | 412 req.handle.Init("a", ignored_request_info_, |
413 kDefaultPriority, &req)); | |
424 req.handle.Reset(); | 414 req.handle.Reset(); |
425 } | 415 } |
426 | 416 |
427 TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) { | 417 TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) { |
428 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 418 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
429 TestSocketRequest req(pool_.get(), &request_order_); | 419 TestSocketRequest req(pool_.get(), &request_order_); |
430 TestSocketRequest req2(pool_.get(), &request_order_); | 420 TestSocketRequest req2(pool_.get(), &request_order_); |
431 | 421 |
432 EXPECT_EQ(ERR_IO_PENDING, | 422 EXPECT_EQ(ERR_IO_PENDING, |
433 req.handle.Init("a", ignored_request_info_, 5, &req)); | 423 req.handle.Init("a", ignored_request_info_, |
424 kDefaultPriority, &req)); | |
434 EXPECT_EQ(ERR_IO_PENDING, | 425 EXPECT_EQ(ERR_IO_PENDING, |
435 req2.handle.Init("a", ignored_request_info_, 5, &req2)); | 426 req2.handle.Init("a", ignored_request_info_, |
427 kDefaultPriority, &req2)); | |
436 | 428 |
437 req.handle.Reset(); | 429 req.handle.Reset(); |
438 | 430 |
439 EXPECT_EQ(OK, req2.WaitForResult()); | 431 EXPECT_EQ(OK, req2.WaitForResult()); |
440 req2.handle.Reset(); | 432 req2.handle.Reset(); |
441 } | 433 } |
442 | 434 |
443 TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) { | 435 TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) { |
444 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 436 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
445 ClientSocketHandle handle(pool_.get()); | 437 ClientSocketHandle handle(pool_.get()); |
446 TestCompletionCallback callback; | 438 TestCompletionCallback callback; |
447 TestSocketRequest req(pool_.get(), &request_order_); | 439 TestSocketRequest req(pool_.get(), &request_order_); |
448 | 440 |
449 EXPECT_EQ(ERR_IO_PENDING, | 441 EXPECT_EQ(ERR_IO_PENDING, |
450 handle.Init("a", ignored_request_info_, 5, &callback)); | 442 handle.Init("a", ignored_request_info_, |
443 kDefaultPriority, &callback)); | |
451 | 444 |
452 handle.Reset(); | 445 handle.Reset(); |
453 | 446 |
454 TestCompletionCallback callback2; | 447 TestCompletionCallback callback2; |
455 EXPECT_EQ(ERR_IO_PENDING, | 448 EXPECT_EQ(ERR_IO_PENDING, |
456 handle.Init("a", ignored_request_info_, 5, &callback2)); | 449 handle.Init("a", ignored_request_info_, |
450 kDefaultPriority, &callback2)); | |
457 | 451 |
458 EXPECT_EQ(OK, callback2.WaitForResult()); | 452 EXPECT_EQ(OK, callback2.WaitForResult()); |
459 EXPECT_FALSE(callback.have_result()); | 453 EXPECT_FALSE(callback.have_result()); |
460 | 454 |
461 handle.Reset(); | 455 handle.Reset(); |
462 } | 456 } |
463 | 457 |
464 TEST_F(ClientSocketPoolBaseTest, CancelRequest) { | 458 TEST_F(ClientSocketPoolBaseTest, CancelRequest) { |
465 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 459 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
466 | 460 |
467 for (size_t i = 0; i < arraysize(reqs); ++i) | 461 CreateConnections(reqs, arraysize(reqs)); |
468 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | |
469 | |
470 // Create connections or queue up requests. | |
471 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | |
472 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); | |
473 EXPECT_EQ(OK, rv); | |
474 request_order_.push_back(reqs[i].get()); | |
475 } | |
476 | |
477 // The rest are pending since we've used all active sockets. | |
478 for (int i = 0; i < kNumPendingRequests; ++i) { | |
479 EXPECT_EQ(ERR_IO_PENDING, reqs[kMaxSocketsPerGroup + i]->handle.Init( | |
480 "a", ignored_request_info_, kPriorities[i], | |
481 reqs[kMaxSocketsPerGroup + i].get())); | |
482 } | |
483 | 462 |
484 // Cancel a request. | 463 // Cancel a request. |
485 size_t index_to_cancel = kMaxSocketsPerGroup + 2; | 464 size_t index_to_cancel = kMaxSocketsPerGroup + 2; |
486 EXPECT_TRUE(!reqs[index_to_cancel]->handle.is_initialized()); | 465 EXPECT_TRUE(!reqs[index_to_cancel]->handle.is_initialized()); |
487 reqs[index_to_cancel]->handle.Reset(); | 466 reqs[index_to_cancel]->handle.Reset(); |
488 | 467 |
489 // Release any connections until we have no connections. | 468 ReleaseAllConnections(reqs, arraysize(reqs), KEEP_ALIVE); |
490 bool released_one; | |
491 do { | |
492 released_one = false; | |
493 for (size_t i = 0; i < arraysize(reqs); ++i) { | |
494 if (reqs[i]->handle.is_initialized()) { | |
495 reqs[i]->handle.Reset(); | |
496 MessageLoop::current()->RunAllPending(); | |
497 released_one = true; | |
498 } | |
499 } | |
500 } while (released_one); | |
501 | 469 |
502 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); | 470 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); |
503 EXPECT_EQ(kNumPendingRequests - 1, TestSocketRequest::completion_count); | 471 EXPECT_EQ(kNumPendingRequests - 1, TestSocketRequest::completion_count); |
504 | 472 |
505 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | 473 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { |
506 EXPECT_EQ(request_order_[i], reqs[i].get()) << | 474 EXPECT_EQ(request_order_[i], reqs[i].get()) << |
507 "Request " << i << " was not in order."; | 475 "Request " << i << " was not in order."; |
508 } | 476 } |
509 | 477 |
510 for (int i = 0; i < kNumPendingRequests - 1; ++i) { | 478 for (int i = 0; i < kNumPendingRequests - 1; ++i) { |
(...skipping 24 matching lines...) Expand all Loading... | |
535 | 503 |
536 virtual void RunWithParams(const Tuple1<int>& params) { | 504 virtual void RunWithParams(const Tuple1<int>& params) { |
537 callback_.RunWithParams(params); | 505 callback_.RunWithParams(params); |
538 ASSERT_EQ(OK, params.a); | 506 ASSERT_EQ(OK, params.a); |
539 | 507 |
540 if (!within_callback_) { | 508 if (!within_callback_) { |
541 test_connect_job_factory_->set_job_type(next_job_type_); | 509 test_connect_job_factory_->set_job_type(next_job_type_); |
542 handle_->Reset(); | 510 handle_->Reset(); |
543 within_callback_ = true; | 511 within_callback_ = true; |
544 int rv = handle_->Init( | 512 int rv = handle_->Init( |
545 "a", HostResolver::RequestInfo("www.google.com", 80), 0, this); | 513 "a", HostResolver::RequestInfo("www.google.com", 80), |
514 kDefaultPriority, this); | |
546 switch (next_job_type_) { | 515 switch (next_job_type_) { |
547 case TestConnectJob::kMockJob: | 516 case TestConnectJob::kMockJob: |
548 EXPECT_EQ(OK, rv); | 517 EXPECT_EQ(OK, rv); |
549 break; | 518 break; |
550 case TestConnectJob::kMockPendingJob: | 519 case TestConnectJob::kMockPendingJob: |
551 EXPECT_EQ(ERR_IO_PENDING, rv); | 520 EXPECT_EQ(ERR_IO_PENDING, rv); |
552 break; | 521 break; |
553 default: | 522 default: |
554 FAIL() << "Unexpected job type: " << next_job_type_; | 523 FAIL() << "Unexpected job type: " << next_job_type_; |
555 break; | 524 break; |
556 } | 525 } |
557 } | 526 } |
558 } | 527 } |
559 | 528 |
560 int WaitForResult() { | 529 int WaitForResult() { |
561 return callback_.WaitForResult(); | 530 return callback_.WaitForResult(); |
562 } | 531 } |
563 | 532 |
564 private: | 533 private: |
565 ClientSocketHandle* const handle_; | 534 ClientSocketHandle* const handle_; |
566 bool within_callback_; | 535 bool within_callback_; |
567 TestConnectJobFactory* const test_connect_job_factory_; | 536 TestConnectJobFactory* const test_connect_job_factory_; |
568 TestConnectJob::JobType next_job_type_; | 537 TestConnectJob::JobType next_job_type_; |
569 TestCompletionCallback callback_; | 538 TestCompletionCallback callback_; |
570 }; | 539 }; |
571 | 540 |
572 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { | 541 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { |
573 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 542 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
574 ClientSocketHandle handle(pool_.get()); | 543 ClientSocketHandle handle(pool_.get()); |
575 RequestSocketCallback callback( | 544 RequestSocketCallback callback( |
576 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob); | 545 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob); |
577 int rv = handle.Init( | 546 int rv = handle.Init( |
578 "a", ignored_request_info_, 0, &callback); | 547 "a", ignored_request_info_, kDefaultPriority, &callback); |
579 ASSERT_EQ(ERR_IO_PENDING, rv); | 548 ASSERT_EQ(ERR_IO_PENDING, rv); |
580 | 549 |
581 EXPECT_EQ(OK, callback.WaitForResult()); | 550 EXPECT_EQ(OK, callback.WaitForResult()); |
582 handle.Reset(); | 551 handle.Reset(); |
583 } | 552 } |
584 | 553 |
585 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { | 554 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { |
586 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 555 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
587 ClientSocketHandle handle(pool_.get()); | 556 ClientSocketHandle handle(pool_.get()); |
588 RequestSocketCallback callback( | 557 RequestSocketCallback callback( |
589 &handle, connect_job_factory_, TestConnectJob::kMockJob); | 558 &handle, connect_job_factory_, TestConnectJob::kMockJob); |
590 int rv = handle.Init( | 559 int rv = handle.Init( |
591 "a", ignored_request_info_, 0, &callback); | 560 "a", ignored_request_info_, kDefaultPriority, &callback); |
592 ASSERT_EQ(ERR_IO_PENDING, rv); | 561 ASSERT_EQ(ERR_IO_PENDING, rv); |
593 | 562 |
594 EXPECT_EQ(OK, callback.WaitForResult()); | 563 EXPECT_EQ(OK, callback.WaitForResult()); |
595 handle.Reset(); | 564 handle.Reset(); |
596 } | 565 } |
597 | 566 |
598 // Make sure that pending requests get serviced after active requests get | 567 // Make sure that pending requests get serviced after active requests get |
599 // cancelled. | 568 // cancelled. |
600 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) { | 569 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) { |
601 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 570 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
602 | 571 |
603 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 572 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
604 | 573 |
605 // Queue up all the requests | 574 // Queue up all the requests |
606 for (size_t i = 0; i < arraysize(reqs); ++i) { | 575 for (size_t i = 0; i < arraysize(reqs); ++i) { |
607 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | 576 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); |
608 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); | 577 int rv = reqs[i]->handle.Init("a", ignored_request_info_, |
578 kDefaultPriority, reqs[i].get()); | |
609 EXPECT_EQ(ERR_IO_PENDING, rv); | 579 EXPECT_EQ(ERR_IO_PENDING, rv); |
610 } | 580 } |
611 | 581 |
612 // Now, kMaxSocketsPerGroup requests should be active. Let's cancel them. | 582 // Now, kMaxSocketsPerGroup requests should be active. Let's cancel them. |
613 for (int i = 0; i < kMaxSocketsPerGroup; ++i) | 583 for (int i = 0; i < kMaxSocketsPerGroup; ++i) |
614 reqs[i]->handle.Reset(); | 584 reqs[i]->handle.Reset(); |
615 | 585 |
616 // Let's wait for the rest to complete now. | 586 // Let's wait for the rest to complete now. |
617 | |
618 for (size_t i = kMaxSocketsPerGroup; i < arraysize(reqs); ++i) { | 587 for (size_t i = kMaxSocketsPerGroup; i < arraysize(reqs); ++i) { |
619 EXPECT_EQ(OK, reqs[i]->WaitForResult()); | 588 EXPECT_EQ(OK, reqs[i]->WaitForResult()); |
620 reqs[i]->handle.Reset(); | 589 reqs[i]->handle.Reset(); |
621 } | 590 } |
622 | 591 |
623 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); | 592 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); |
624 } | 593 } |
625 | 594 |
626 // Make sure that pending requests get serviced after active requests fail. | 595 // Make sure that pending requests get serviced after active requests fail. |
627 TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) { | 596 TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) { |
628 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); | 597 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); |
629 | 598 |
630 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup * 2 + 1]; | 599 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup * 2 + 1]; |
631 | 600 |
632 // Queue up all the requests | 601 // Queue up all the requests |
633 for (size_t i = 0; i < arraysize(reqs); ++i) { | 602 for (size_t i = 0; i < arraysize(reqs); ++i) { |
634 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | 603 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); |
635 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); | 604 int rv = reqs[i]->handle.Init("a", ignored_request_info_, |
605 kDefaultPriority, reqs[i].get()); | |
636 EXPECT_EQ(ERR_IO_PENDING, rv); | 606 EXPECT_EQ(ERR_IO_PENDING, rv); |
637 } | 607 } |
638 | 608 |
639 for (size_t i = 0; i < arraysize(reqs); ++i) | 609 for (size_t i = 0; i < arraysize(reqs); ++i) |
640 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult()); | 610 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult()); |
641 } | 611 } |
642 | 612 |
643 // A pending asynchronous job completes, which will free up a socket slot. The | 613 // A pending asynchronous job completes, which will free up a socket slot. The |
644 // next job finishes synchronously. The callback for the asynchronous job | 614 // next job finishes synchronously. The callback for the asynchronous job |
645 // should be first though. | 615 // should be first though. |
646 TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) { | 616 TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) { |
647 // First two jobs are async. | 617 // First two jobs are async. |
648 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); | 618 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); |
649 | 619 |
650 // Start job 1 (async error). | 620 // Start job 1 (async error). |
651 TestSocketRequest req1(pool_.get(), &request_order_); | 621 TestSocketRequest req1(pool_.get(), &request_order_); |
652 int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1); | 622 int rv = req1.handle.Init("a", ignored_request_info_, |
623 kDefaultPriority, &req1); | |
653 EXPECT_EQ(ERR_IO_PENDING, rv); | 624 EXPECT_EQ(ERR_IO_PENDING, rv); |
654 | 625 |
655 // Start job 2 (async error). | 626 // Start job 2 (async error). |
656 TestSocketRequest req2(pool_.get(), &request_order_); | 627 TestSocketRequest req2(pool_.get(), &request_order_); |
657 rv = req2.handle.Init("a", ignored_request_info_, 5, &req2); | 628 rv = req2.handle.Init("a", ignored_request_info_, kDefaultPriority, &req2); |
658 EXPECT_EQ(ERR_IO_PENDING, rv); | 629 EXPECT_EQ(ERR_IO_PENDING, rv); |
659 | 630 |
660 // The pending job is sync. | 631 // The pending job is sync. |
661 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | 632 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
662 | 633 |
663 // Request 3 does not have a ConnectJob yet. It's just pending. | 634 // Request 3 does not have a ConnectJob yet. It's just pending. |
664 TestSocketRequest req3(pool_.get(), &request_order_); | 635 TestSocketRequest req3(pool_.get(), &request_order_); |
665 rv = req3.handle.Init("a", ignored_request_info_, 5, &req3); | 636 rv = req3.handle.Init("a", ignored_request_info_, kDefaultPriority, &req3); |
666 EXPECT_EQ(ERR_IO_PENDING, rv); | 637 EXPECT_EQ(ERR_IO_PENDING, rv); |
667 | 638 |
668 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult()); | 639 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult()); |
669 EXPECT_EQ(ERR_CONNECTION_FAILED, req2.WaitForResult()); | 640 EXPECT_EQ(ERR_CONNECTION_FAILED, req2.WaitForResult()); |
670 EXPECT_EQ(OK, req3.WaitForResult()); | 641 EXPECT_EQ(OK, req3.WaitForResult()); |
671 | 642 |
672 ASSERT_EQ(3U, request_order_.size()); | 643 ASSERT_EQ(3U, request_order_.size()); |
673 | 644 |
674 // After job 1 finishes unsuccessfully, it will try to process the pending | 645 // After job 1 finishes unsuccessfully, it will try to process the pending |
675 // requests queue, so it starts up job 3 for request 3. This job | 646 // requests queue, so it starts up job 3 for request 3. This job |
676 // synchronously succeeds, so the request order is 1, 3, 2. | 647 // synchronously succeeds, so the request order is 1, 3, 2. |
677 EXPECT_EQ(&req1, request_order_[0]); | 648 EXPECT_EQ(&req1, request_order_[0]); |
678 EXPECT_EQ(&req2, request_order_[2]); | 649 EXPECT_EQ(&req2, request_order_[2]); |
679 EXPECT_EQ(&req3, request_order_[1]); | 650 EXPECT_EQ(&req3, request_order_[1]); |
680 } | 651 } |
681 | 652 |
682 } // namespace | 653 } // namespace |
683 | 654 |
684 } // namespace net | 655 } // namespace net |
OLD | NEW |