OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 3398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3409 EXPECT_EQ(0, pool_->NumActiveSocketsInGroup("a")); | 3409 EXPECT_EQ(0, pool_->NumActiveSocketsInGroup("a")); |
3410 ASSERT_EQ(OK, callback.WaitForResult()); | 3410 ASSERT_EQ(OK, callback.WaitForResult()); |
3411 | 3411 |
3412 // The hung connect job should still be there, but everything else should be | 3412 // The hung connect job should still be there, but everything else should be |
3413 // complete. | 3413 // complete. |
3414 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | 3414 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); |
3415 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | 3415 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); |
3416 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); | 3416 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); |
3417 } | 3417 } |
3418 | 3418 |
| 3419 class MockLayeredPool : public LayeredPool { |
| 3420 public: |
| 3421 MockLayeredPool(TestClientSocketPool* pool, |
| 3422 const std::string& group_name) |
| 3423 : pool_(pool), |
| 3424 params_(new TestSocketParams), |
| 3425 group_name_(group_name), |
| 3426 can_release_connection_(true) { |
| 3427 pool_->AddLayeredPool(this); |
| 3428 } |
| 3429 |
| 3430 ~MockLayeredPool() { |
| 3431 pool_->RemoveLayeredPool(this); |
| 3432 } |
| 3433 |
| 3434 int RequestSocket(TestClientSocketPool* pool) { |
| 3435 return handle_.Init(group_name_, params_, kDefaultPriority, |
| 3436 callback_.callback(), pool, BoundNetLog()); |
| 3437 } |
| 3438 |
| 3439 int RequestSocketWithoutLimits(TestClientSocketPool* pool) { |
| 3440 params_->set_ignore_limits(true); |
| 3441 return handle_.Init(group_name_, params_, kDefaultPriority, |
| 3442 callback_.callback(), pool, BoundNetLog()); |
| 3443 } |
| 3444 |
| 3445 bool ReleaseOneConnection() { |
| 3446 if (!handle_.is_initialized() || !can_release_connection_) { |
| 3447 return false; |
| 3448 } |
| 3449 handle_.socket()->Disconnect(); |
| 3450 handle_.Reset(); |
| 3451 return true; |
| 3452 } |
| 3453 |
| 3454 void set_can_release_connection(bool can_release_connection) { |
| 3455 can_release_connection_ = can_release_connection; |
| 3456 } |
| 3457 |
| 3458 MOCK_METHOD0(CloseOneIdleConnection, bool()); |
| 3459 |
| 3460 private: |
| 3461 TestClientSocketPool* const pool_; |
| 3462 scoped_refptr<TestSocketParams> params_; |
| 3463 ClientSocketHandle handle_; |
| 3464 TestCompletionCallback callback_; |
| 3465 const std::string group_name_; |
| 3466 bool can_release_connection_; |
| 3467 }; |
| 3468 |
| 3469 TEST_F(ClientSocketPoolBaseTest, FailToCloseIdleSocketsNotHeldByLayeredPool) { |
| 3470 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
| 3471 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
| 3472 |
| 3473 MockLayeredPool mock_layered_pool(pool_.get(), "foo"); |
| 3474 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); |
| 3475 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) |
| 3476 .WillOnce(Return(false)); |
| 3477 EXPECT_FALSE(pool_->CloseOneIdleConnectionInLayeredPool()); |
| 3478 } |
| 3479 |
| 3480 TEST_F(ClientSocketPoolBaseTest, ForciblyCloseIdleSocketsHeldByLayeredPool) { |
| 3481 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
| 3482 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
| 3483 |
| 3484 MockLayeredPool mock_layered_pool(pool_.get(), "foo"); |
| 3485 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); |
| 3486 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) |
| 3487 .WillOnce(Invoke(&mock_layered_pool, |
| 3488 &MockLayeredPool::ReleaseOneConnection)); |
| 3489 EXPECT_TRUE(pool_->CloseOneIdleConnectionInLayeredPool()); |
| 3490 } |
| 3491 |
| 3492 // This test exercises the codepath which caused http://crbug.com/109876 |
| 3493 TEST_F(ClientSocketPoolBaseTest, |
| 3494 CloseIdleSocketsHeldByLayeredPoolInSameGroupWhenNeeded) { |
| 3495 CreatePool(2, 2); |
| 3496 std::list<TestConnectJob::JobType> job_types; |
| 3497 job_types.push_back(TestConnectJob::kMockJob); |
| 3498 job_types.push_back(TestConnectJob::kMockJob); |
| 3499 job_types.push_back(TestConnectJob::kMockFailingJob); |
| 3500 job_types.push_back(TestConnectJob::kMockJob); |
| 3501 connect_job_factory_->set_job_types(&job_types); |
| 3502 |
| 3503 ClientSocketHandle handle1; |
| 3504 TestCompletionCallback callback1; |
| 3505 EXPECT_EQ(OK, handle1.Init("group1", |
| 3506 params_, |
| 3507 kDefaultPriority, |
| 3508 callback1.callback(), |
| 3509 pool_.get(), |
| 3510 BoundNetLog())); |
| 3511 |
| 3512 MockLayeredPool mock_layered_pool(pool_.get(), "group2"); |
| 3513 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); |
| 3514 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) |
| 3515 .WillRepeatedly(Invoke(&mock_layered_pool, |
| 3516 &MockLayeredPool::ReleaseOneConnection)); |
| 3517 mock_layered_pool.set_can_release_connection(false); |
| 3518 |
| 3519 // This connection attempt will fail when the next request causes the |
| 3520 // MockLayeredPool to delete the socket it's holding. This request is |
| 3521 // needed to trigger the destruction of the "group2" Group. |
| 3522 ClientSocketHandle handle3; |
| 3523 TestCompletionCallback callback3; |
| 3524 EXPECT_EQ(ERR_IO_PENDING, handle3.Init("group2", |
| 3525 params_, |
| 3526 kDefaultPriority, |
| 3527 callback3.callback(), |
| 3528 pool_.get(), |
| 3529 BoundNetLog())); |
| 3530 |
| 3531 mock_layered_pool.set_can_release_connection(true); |
| 3532 ClientSocketHandle handle4; |
| 3533 TestCompletionCallback callback4; |
| 3534 EXPECT_EQ(OK, handle4.Init("group2", |
| 3535 params_, |
| 3536 kDefaultPriority, |
| 3537 callback4.callback(), |
| 3538 pool_.get(), |
| 3539 BoundNetLog())); |
| 3540 } |
| 3541 |
| 3542 TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketsHeldByLayeredPoolWhenNeeded) { |
| 3543 CreatePool(1, 1); |
| 3544 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
| 3545 |
| 3546 MockLayeredPool mock_layered_pool(pool_.get(), "foo"); |
| 3547 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); |
| 3548 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) |
| 3549 .WillOnce(Invoke(&mock_layered_pool, |
| 3550 &MockLayeredPool::ReleaseOneConnection)); |
| 3551 ClientSocketHandle handle; |
| 3552 TestCompletionCallback callback; |
| 3553 EXPECT_EQ(OK, handle.Init("a", |
| 3554 params_, |
| 3555 kDefaultPriority, |
| 3556 callback.callback(), |
| 3557 pool_.get(), |
| 3558 BoundNetLog())); |
| 3559 } |
| 3560 |
| 3561 TEST_F(ClientSocketPoolBaseTest, |
| 3562 CloseMultipleIdleSocketsHeldByLayeredPoolWhenNeeded) { |
| 3563 CreatePool(1, 1); |
| 3564 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
| 3565 |
| 3566 MockLayeredPool mock_layered_pool1(pool_.get(), "foo"); |
| 3567 EXPECT_EQ(OK, mock_layered_pool1.RequestSocket(pool_.get())); |
| 3568 EXPECT_CALL(mock_layered_pool1, CloseOneIdleConnection()) |
| 3569 .WillRepeatedly(Invoke(&mock_layered_pool1, |
| 3570 &MockLayeredPool::ReleaseOneConnection)); |
| 3571 MockLayeredPool mock_layered_pool2(pool_.get(), "bar"); |
| 3572 EXPECT_EQ(OK, mock_layered_pool2.RequestSocketWithoutLimits(pool_.get())); |
| 3573 EXPECT_CALL(mock_layered_pool2, CloseOneIdleConnection()) |
| 3574 .WillRepeatedly(Invoke(&mock_layered_pool2, |
| 3575 &MockLayeredPool::ReleaseOneConnection)); |
| 3576 ClientSocketHandle handle; |
| 3577 TestCompletionCallback callback; |
| 3578 EXPECT_EQ(OK, handle.Init("a", |
| 3579 params_, |
| 3580 kDefaultPriority, |
| 3581 callback.callback(), |
| 3582 pool_.get(), |
| 3583 BoundNetLog())); |
| 3584 } |
| 3585 |
3419 } // namespace | 3586 } // namespace |
3420 | 3587 |
3421 } // namespace net | 3588 } // namespace net |
OLD | NEW |