diff options
author | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-26 23:10:10 +0000 |
---|---|---|
committer | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-26 23:10:10 +0000 |
commit | f8f951d1535968dbfe3a558b0857dde0b5de8850 (patch) | |
tree | b8629d6ad3219e57011ae0340ef725e9f8005447 /net/socket/client_socket_pool_base_unittest.cc | |
parent | abed3c4500a80450285a7b61038e54cc5badf75e (diff) | |
download | chromium_src-f8f951d1535968dbfe3a558b0857dde0b5de8850.zip chromium_src-f8f951d1535968dbfe3a558b0857dde0b5de8850.tar.gz chromium_src-f8f951d1535968dbfe3a558b0857dde0b5de8850.tar.bz2 |
Reverting this feature, once again. *sigh*
Revert 127893 -Revert 127730 - Revert 127717 - Revert 118788 - Revert 113405 - Revert 113305 - Revert 113300 - Revert 112134 - Revert 112130 - Close idle connections / SPDY sessions when needed
Due to the idle connection state being held by different socket pools, it's possible for one socket pool to hold an idle socket in a lower layer socket pool. From the lower level socket pool's perspective, the socket is being "actively" used. From the higher socket pool's (including SpdySession, which is more of a connection manager) perspective, the connection is idle and can be closed if we have hit a limit.
Normally this isn't a big deal, except when we have a lot of idle SPDY connections and are connecting via a proxy, so we have low connection limits through the proxy server. We address this problem by allowing lower-level socket pools to tell higher level socket pools to close a socket.
Fixed ASAN test failures by removing .Times(1) and .Times(2) from CloseMultipleIdleSocketsHeldByLayeredPoolWhenNeeded unittest (this removes the tests relying on the order of std::set in CloseOneIdleConnectionInLayeredPool). ASAN is prob
ably causing the memory allocator to allocate the pools differently. The std::set is ordered by LayeredPool* which is the address of the LayeredPool (willchan).
Added NET_EXPORT for layered_pool class defintion to fix windows shared compile.
BUG=62364, 92244, 109876, 110368, 119847
TEST=
Review URL: http://codereview.chromium.org/9809033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@129034 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket/client_socket_pool_base_unittest.cc')
-rw-r--r-- | net/socket/client_socket_pool_base_unittest.cc | 223 |
1 files changed, 4 insertions, 219 deletions
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc index 6c692fe..b1c1a99 100644 --- a/net/socket/client_socket_pool_base_unittest.cc +++ b/net/socket/client_socket_pool_base_unittest.cc @@ -4,8 +4,6 @@ #include "net/socket/client_socket_pool_base.h" -#include <vector> - #include "base/bind.h" #include "base/bind_helpers.h" #include "base/callback.h" @@ -30,12 +28,8 @@ #include "net/socket/socket_test_util.h" #include "net/socket/ssl_host_info.h" #include "net/socket/stream_socket.h" -#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using ::testing::Invoke; -using ::testing::Return; - namespace net { namespace { @@ -46,18 +40,10 @@ const net::RequestPriority kDefaultPriority = MEDIUM; class TestSocketParams : public base::RefCounted<TestSocketParams> { public: - TestSocketParams() : ignore_limits_(false) {} - - void set_ignore_limits(bool ignore_limits) { - ignore_limits_ = ignore_limits; - } - bool ignore_limits() { return ignore_limits_; } - + bool ignore_limits() { return false; } private: friend class base::RefCounted<TestSocketParams>; ~TestSocketParams() {} - - bool ignore_limits_; }; typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase; @@ -369,18 +355,12 @@ class TestConnectJobFactory public: explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory) : job_type_(TestConnectJob::kMockJob), - job_types_(NULL), client_socket_factory_(client_socket_factory) {} virtual ~TestConnectJobFactory() {} void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; } - void set_job_types(std::list<TestConnectJob::JobType>* job_types) { - job_types_ = job_types; - CHECK(!job_types_->empty()); - } - void set_timeout_duration(base::TimeDelta timeout_duration) { timeout_duration_ = timeout_duration; } @@ -391,13 +371,7 @@ class TestConnectJobFactory const std::string& group_name, const TestClientSocketPoolBase::Request& request, ConnectJob::Delegate* delegate) const { - EXPECT_TRUE(!job_types_ || !job_types_->empty()); - TestConnectJob::JobType job_type = job_type_; - if (job_types_ && !job_types_->empty()) { - job_type = job_types_->front(); - job_types_->pop_front(); - } - return new TestConnectJob(job_type, + return new TestConnectJob(job_type_, group_name, request, timeout_duration_, @@ -412,7 +386,6 @@ class TestConnectJobFactory private: TestConnectJob::JobType job_type_; - std::list<TestConnectJob::JobType>* job_types_; base::TimeDelta timeout_duration_; MockClientSocketFactory* const client_socket_factory_; @@ -474,10 +447,6 @@ class TestClientSocketPool : public ClientSocketPool { base_.Flush(); } - virtual bool IsStalled() const OVERRIDE { - return base_.IsStalled(); - } - virtual void CloseIdleSockets() OVERRIDE { base_.CloseIdleSockets(); } @@ -497,14 +466,6 @@ class TestClientSocketPool : public ClientSocketPool { return base_.GetLoadState(group_name, handle); } - virtual void AddLayeredPool(LayeredPool* pool) OVERRIDE { - base_.AddLayeredPool(pool); - } - - virtual void RemoveLayeredPool(LayeredPool* pool) OVERRIDE { - base_.RemoveLayeredPool(pool); - } - virtual DictionaryValue* GetInfoAsValue( const std::string& name, const std::string& type, @@ -538,10 +499,6 @@ class TestClientSocketPool : public ClientSocketPool { void EnableConnectBackupJobs() { base_.EnableConnectBackupJobs(); } - bool CloseOneIdleConnectionInLayeredPool() { - return base_.CloseOneIdleConnectionInLayeredPool(); - } - private: TestClientSocketPoolBase base_; @@ -1207,7 +1164,6 @@ TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) { ClientSocketHandle stalled_handle; TestCompletionCallback callback; { - EXPECT_FALSE(pool_->IsStalled()); ClientSocketHandle handles[kDefaultMaxSockets]; for (int i = 0; i < kDefaultMaxSockets; ++i) { TestCompletionCallback callback; @@ -1222,7 +1178,6 @@ TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) { EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); EXPECT_EQ(0, pool_->IdleSocketCount()); - EXPECT_FALSE(pool_->IsStalled()); // Now we will hit the socket limit. EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo", @@ -1231,7 +1186,6 @@ TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) { callback.callback(), pool_.get(), BoundNetLog())); - EXPECT_TRUE(pool_->IsStalled()); // Dropping out of scope will close all handles and return them to idle. } @@ -2051,9 +2005,9 @@ TEST_F(ClientSocketPoolBaseTest, DisableCleanupTimer) { EXPECT_EQ(1, handle2.socket()->Write(NULL, 1, CompletionCallback())); handle2.Reset(); - // The idle socket timeout value was set to 10 milliseconds. Wait 100 + // The idle socket timeout value was set to 10 milliseconds. Wait 20 // milliseconds so the sockets timeout. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20)); MessageLoop::current()->RunAllPending(); ASSERT_EQ(2, pool_->IdleSocketCount()); @@ -3085,7 +3039,6 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsHitMaxSocketLimit) { ASSERT_TRUE(pool_->HasGroup("a")); EXPECT_EQ(kDefaultMaxSockets - 1, pool_->NumConnectJobsInGroup("a")); - EXPECT_FALSE(pool_->IsStalled()); ASSERT_FALSE(pool_->HasGroup("b")); @@ -3094,7 +3047,6 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsHitMaxSocketLimit) { ASSERT_TRUE(pool_->HasGroup("b")); EXPECT_EQ(1, pool_->NumConnectJobsInGroup("b")); - EXPECT_FALSE(pool_->IsStalled()); } TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountIdleSockets) { @@ -3413,173 +3365,6 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectWithBackupJob) { EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); } -class MockLayeredPool : public LayeredPool { - public: - MockLayeredPool(TestClientSocketPool* pool, - const std::string& group_name) - : pool_(pool), - params_(new TestSocketParams), - group_name_(group_name), - can_release_connection_(true) { - pool_->AddLayeredPool(this); - } - - ~MockLayeredPool() { - pool_->RemoveLayeredPool(this); - } - - int RequestSocket(TestClientSocketPool* pool) { - return handle_.Init(group_name_, params_, kDefaultPriority, - callback_.callback(), pool, BoundNetLog()); - } - - int RequestSocketWithoutLimits(TestClientSocketPool* pool) { - params_->set_ignore_limits(true); - return handle_.Init(group_name_, params_, kDefaultPriority, - callback_.callback(), pool, BoundNetLog()); - } - - bool ReleaseOneConnection() { - if (!handle_.is_initialized() || !can_release_connection_) { - return false; - } - handle_.socket()->Disconnect(); - handle_.Reset(); - return true; - } - - void set_can_release_connection(bool can_release_connection) { - can_release_connection_ = can_release_connection; - } - - MOCK_METHOD0(CloseOneIdleConnection, bool()); - - private: - TestClientSocketPool* const pool_; - scoped_refptr<TestSocketParams> params_; - ClientSocketHandle handle_; - TestCompletionCallback callback_; - const std::string group_name_; - bool can_release_connection_; -}; - -TEST_F(ClientSocketPoolBaseTest, FailToCloseIdleSocketsNotHeldByLayeredPool) { - CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); - connect_job_factory_->set_job_type(TestConnectJob::kMockJob); - - MockLayeredPool mock_layered_pool(pool_.get(), "foo"); - EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); - EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) - .WillOnce(Return(false)); - EXPECT_FALSE(pool_->CloseOneIdleConnectionInLayeredPool()); -} - -TEST_F(ClientSocketPoolBaseTest, ForciblyCloseIdleSocketsHeldByLayeredPool) { - CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); - connect_job_factory_->set_job_type(TestConnectJob::kMockJob); - - MockLayeredPool mock_layered_pool(pool_.get(), "foo"); - EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); - EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) - .WillOnce(Invoke(&mock_layered_pool, - &MockLayeredPool::ReleaseOneConnection)); - EXPECT_TRUE(pool_->CloseOneIdleConnectionInLayeredPool()); -} - -// This test exercises the codepath which caused http://crbug.com/109876 -TEST_F(ClientSocketPoolBaseTest, - CloseIdleSocketsHeldByLayeredPoolInSameGroupWhenNeeded) { - CreatePool(2, 2); - std::list<TestConnectJob::JobType> job_types; - job_types.push_back(TestConnectJob::kMockJob); - job_types.push_back(TestConnectJob::kMockJob); - job_types.push_back(TestConnectJob::kMockFailingJob); - job_types.push_back(TestConnectJob::kMockJob); - connect_job_factory_->set_job_types(&job_types); - - ClientSocketHandle handle1; - TestCompletionCallback callback1; - EXPECT_EQ(OK, handle1.Init("group1", - params_, - kDefaultPriority, - callback1.callback(), - pool_.get(), - BoundNetLog())); - - MockLayeredPool mock_layered_pool(pool_.get(), "group2"); - EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); - EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) - .WillRepeatedly(Invoke(&mock_layered_pool, - &MockLayeredPool::ReleaseOneConnection)); - mock_layered_pool.set_can_release_connection(false); - - // This connection attempt will fail when the next request causes the - // MockLayeredPool to delete the socket it's holding. This request is - // needed to trigger the destruction of the "group2" Group. - ClientSocketHandle handle3; - TestCompletionCallback callback3; - EXPECT_EQ(ERR_IO_PENDING, handle3.Init("group2", - params_, - kDefaultPriority, - callback3.callback(), - pool_.get(), - BoundNetLog())); - - mock_layered_pool.set_can_release_connection(true); - ClientSocketHandle handle4; - TestCompletionCallback callback4; - EXPECT_EQ(OK, handle4.Init("group2", - params_, - kDefaultPriority, - callback4.callback(), - pool_.get(), - BoundNetLog())); -} - -TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketsHeldByLayeredPoolWhenNeeded) { - CreatePool(1, 1); - connect_job_factory_->set_job_type(TestConnectJob::kMockJob); - - MockLayeredPool mock_layered_pool(pool_.get(), "foo"); - EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); - EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) - .WillOnce(Invoke(&mock_layered_pool, - &MockLayeredPool::ReleaseOneConnection)); - ClientSocketHandle handle; - TestCompletionCallback callback; - EXPECT_EQ(OK, handle.Init("a", - params_, - kDefaultPriority, - callback.callback(), - pool_.get(), - BoundNetLog())); -} - -TEST_F(ClientSocketPoolBaseTest, - CloseMultipleIdleSocketsHeldByLayeredPoolWhenNeeded) { - CreatePool(1, 1); - connect_job_factory_->set_job_type(TestConnectJob::kMockJob); - - MockLayeredPool mock_layered_pool1(pool_.get(), "foo"); - EXPECT_EQ(OK, mock_layered_pool1.RequestSocket(pool_.get())); - EXPECT_CALL(mock_layered_pool1, CloseOneIdleConnection()) - .WillRepeatedly(Invoke(&mock_layered_pool1, - &MockLayeredPool::ReleaseOneConnection)); - MockLayeredPool mock_layered_pool2(pool_.get(), "bar"); - EXPECT_EQ(OK, mock_layered_pool2.RequestSocketWithoutLimits(pool_.get())); - EXPECT_CALL(mock_layered_pool2, CloseOneIdleConnection()) - .WillRepeatedly(Invoke(&mock_layered_pool2, - &MockLayeredPool::ReleaseOneConnection)); - ClientSocketHandle handle; - TestCompletionCallback callback; - EXPECT_EQ(OK, handle.Init("a", - params_, - kDefaultPriority, - callback.callback(), - pool_.get(), - BoundNetLog())); -} - } // namespace } // namespace net |