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 | |
3586 } // namespace | 3419 } // namespace |
3587 | 3420 |
3588 } // namespace net | 3421 } // namespace net |
OLD | NEW |