Chromium Code Reviews| 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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 ~TestSocketParams() {} | 109 ~TestSocketParams() {} |
| 110 | 110 |
| 111 const bool ignore_limits_; | 111 const bool ignore_limits_; |
| 112 }; | 112 }; |
| 113 typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase; | 113 typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase; |
| 114 | 114 |
| 115 class MockClientSocket : public StreamSocket { | 115 class MockClientSocket : public StreamSocket { |
| 116 public: | 116 public: |
| 117 explicit MockClientSocket(net::NetLog* net_log) | 117 explicit MockClientSocket(net::NetLog* net_log) |
| 118 : connected_(false), | 118 : connected_(false), |
| 119 idle_(true), | |
| 119 net_log_(BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), | 120 net_log_(BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), |
| 120 was_used_to_convey_data_(false) { | 121 was_used_to_convey_data_(false) { |
| 121 } | 122 } |
| 122 | 123 |
| 124 void set_idle(bool idle) { idle_ = idle; } | |
|
mmenke
2014/03/18 15:16:55
Think it's worth a comment just what this does (Le
davidben
2014/03/25 19:50:18
Done.
| |
| 125 | |
| 123 // Socket implementation. | 126 // Socket implementation. |
| 124 virtual int Read( | 127 virtual int Read( |
| 125 IOBuffer* /* buf */, int len, | 128 IOBuffer* /* buf */, int len, |
| 126 const CompletionCallback& /* callback */) OVERRIDE { | 129 const CompletionCallback& /* callback */) OVERRIDE { |
| 130 if (!idle_ && len > 0) { | |
| 131 idle_ = true; | |
| 132 was_used_to_convey_data_ = true; | |
| 133 return 1; | |
| 134 } | |
| 127 return ERR_UNEXPECTED; | 135 return ERR_UNEXPECTED; |
| 128 } | 136 } |
| 129 | 137 |
| 130 virtual int Write( | 138 virtual int Write( |
| 131 IOBuffer* /* buf */, int len, | 139 IOBuffer* /* buf */, int len, |
| 132 const CompletionCallback& /* callback */) OVERRIDE { | 140 const CompletionCallback& /* callback */) OVERRIDE { |
| 133 was_used_to_convey_data_ = true; | 141 was_used_to_convey_data_ = true; |
| 134 return len; | 142 return len; |
| 135 } | 143 } |
| 136 virtual bool SetReceiveBufferSize(int32 size) OVERRIDE { return true; } | 144 virtual bool SetReceiveBufferSize(int32 size) OVERRIDE { return true; } |
| 137 virtual bool SetSendBufferSize(int32 size) OVERRIDE { return true; } | 145 virtual bool SetSendBufferSize(int32 size) OVERRIDE { return true; } |
| 138 | 146 |
| 139 // StreamSocket implementation. | 147 // StreamSocket implementation. |
| 140 virtual int Connect(const CompletionCallback& callback) OVERRIDE { | 148 virtual int Connect(const CompletionCallback& callback) OVERRIDE { |
| 141 connected_ = true; | 149 connected_ = true; |
| 142 return OK; | 150 return OK; |
| 143 } | 151 } |
| 144 | 152 |
| 145 virtual void Disconnect() OVERRIDE { connected_ = false; } | 153 virtual void Disconnect() OVERRIDE { connected_ = false; } |
| 146 virtual bool IsConnected() const OVERRIDE { return connected_; } | 154 virtual bool IsConnected() const OVERRIDE { return connected_; } |
| 147 virtual bool IsConnectedAndIdle() const OVERRIDE { return connected_; } | 155 virtual bool IsConnectedAndIdle() const OVERRIDE { |
| 156 return connected_ && idle_; | |
| 157 } | |
| 148 | 158 |
| 149 virtual int GetPeerAddress(IPEndPoint* /* address */) const OVERRIDE { | 159 virtual int GetPeerAddress(IPEndPoint* /* address */) const OVERRIDE { |
| 150 return ERR_UNEXPECTED; | 160 return ERR_UNEXPECTED; |
| 151 } | 161 } |
| 152 | 162 |
| 153 virtual int GetLocalAddress(IPEndPoint* /* address */) const OVERRIDE { | 163 virtual int GetLocalAddress(IPEndPoint* /* address */) const OVERRIDE { |
| 154 return ERR_UNEXPECTED; | 164 return ERR_UNEXPECTED; |
| 155 } | 165 } |
| 156 | 166 |
| 157 virtual const BoundNetLog& NetLog() const OVERRIDE { | 167 virtual const BoundNetLog& NetLog() const OVERRIDE { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 169 } | 179 } |
| 170 virtual NextProto GetNegotiatedProtocol() const OVERRIDE { | 180 virtual NextProto GetNegotiatedProtocol() const OVERRIDE { |
| 171 return kProtoUnknown; | 181 return kProtoUnknown; |
| 172 } | 182 } |
| 173 virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE { | 183 virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE { |
| 174 return false; | 184 return false; |
| 175 } | 185 } |
| 176 | 186 |
| 177 private: | 187 private: |
| 178 bool connected_; | 188 bool connected_; |
| 189 bool idle_; | |
| 179 BoundNetLog net_log_; | 190 BoundNetLog net_log_; |
| 180 bool was_used_to_convey_data_; | 191 bool was_used_to_convey_data_; |
| 181 | 192 |
| 182 DISALLOW_COPY_AND_ASSIGN(MockClientSocket); | 193 DISALLOW_COPY_AND_ASSIGN(MockClientSocket); |
| 183 }; | 194 }; |
| 184 | 195 |
| 185 class TestConnectJob; | 196 class TestConnectJob; |
| 186 | 197 |
| 187 class MockClientSocketFactory : public ClientSocketFactory { | 198 class MockClientSocketFactory : public ClientSocketFactory { |
| 188 public: | 199 public: |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 enum JobType { | 249 enum JobType { |
| 239 kMockJob, | 250 kMockJob, |
| 240 kMockFailingJob, | 251 kMockFailingJob, |
| 241 kMockPendingJob, | 252 kMockPendingJob, |
| 242 kMockPendingFailingJob, | 253 kMockPendingFailingJob, |
| 243 kMockWaitingJob, | 254 kMockWaitingJob, |
| 244 kMockRecoverableJob, | 255 kMockRecoverableJob, |
| 245 kMockPendingRecoverableJob, | 256 kMockPendingRecoverableJob, |
| 246 kMockAdditionalErrorStateJob, | 257 kMockAdditionalErrorStateJob, |
| 247 kMockPendingAdditionalErrorStateJob, | 258 kMockPendingAdditionalErrorStateJob, |
| 259 kMockUnreadDataJob, | |
| 248 }; | 260 }; |
| 249 | 261 |
| 250 // The kMockPendingJob uses a slight delay before allowing the connect | 262 // The kMockPendingJob uses a slight delay before allowing the connect |
| 251 // to complete. | 263 // to complete. |
| 252 static const int kPendingConnectDelay = 2; | 264 static const int kPendingConnectDelay = 2; |
| 253 | 265 |
| 254 TestConnectJob(JobType job_type, | 266 TestConnectJob(JobType job_type, |
| 255 const std::string& group_name, | 267 const std::string& group_name, |
| 256 const TestClientSocketPoolBase::Request& request, | 268 const TestClientSocketPoolBase::Request& request, |
| 257 base::TimeDelta timeout_duration, | 269 base::TimeDelta timeout_duration, |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 365 store_additional_error_state_ = true; | 377 store_additional_error_state_ = true; |
| 366 base::MessageLoop::current()->PostDelayedTask( | 378 base::MessageLoop::current()->PostDelayedTask( |
| 367 FROM_HERE, | 379 FROM_HERE, |
| 368 base::Bind(base::IgnoreResult(&TestConnectJob::DoConnect), | 380 base::Bind(base::IgnoreResult(&TestConnectJob::DoConnect), |
| 369 weak_factory_.GetWeakPtr(), | 381 weak_factory_.GetWeakPtr(), |
| 370 false /* error */, | 382 false /* error */, |
| 371 true /* async */, | 383 true /* async */, |
| 372 false /* recoverable */), | 384 false /* recoverable */), |
| 373 base::TimeDelta::FromMilliseconds(2)); | 385 base::TimeDelta::FromMilliseconds(2)); |
| 374 return ERR_IO_PENDING; | 386 return ERR_IO_PENDING; |
| 387 case kMockUnreadDataJob: { | |
| 388 int ret = DoConnect(true /* successful */, false /* sync */, | |
| 389 false /* recoverable */); | |
| 390 static_cast<MockClientSocket*>(socket())->set_idle(false); | |
|
mmenke
2014/03/18 15:16:55
Can we just store the socket as a local and avoid
| |
| 391 return ret; | |
| 392 } | |
| 375 default: | 393 default: |
| 376 NOTREACHED(); | 394 NOTREACHED(); |
| 377 SetSocket(scoped_ptr<StreamSocket>()); | 395 SetSocket(scoped_ptr<StreamSocket>()); |
| 378 return ERR_FAILED; | 396 return ERR_FAILED; |
| 379 } | 397 } |
| 380 } | 398 } |
| 381 | 399 |
| 382 int DoConnect(bool succeed, bool was_async, bool recoverable) { | 400 int DoConnect(bool succeed, bool was_async, bool recoverable) { |
| 383 int result = OK; | 401 int result = OK; |
| 384 if (succeed) { | 402 if (succeed) { |
| (...skipping 3149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3534 callback1.callback(), | 3552 callback1.callback(), |
| 3535 pool_.get(), | 3553 pool_.get(), |
| 3536 BoundNetLog())); | 3554 BoundNetLog())); |
| 3537 | 3555 |
| 3538 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | 3556 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); |
| 3539 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | 3557 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); |
| 3540 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | 3558 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); |
| 3541 | 3559 |
| 3542 ASSERT_EQ(OK, callback1.WaitForResult()); | 3560 ASSERT_EQ(OK, callback1.WaitForResult()); |
| 3543 | 3561 |
| 3544 // Make sure if a preconneced socket is not fully connected when a request | 3562 // Make sure if a preconnected socket is not fully connected when a request |
| 3545 // starts, it has a connect start time. | 3563 // starts, it has a connect start time. |
| 3546 TestLoadTimingInfoConnectedNotReused(handle1); | 3564 TestLoadTimingInfoConnectedNotReused(handle1); |
| 3547 handle1.Reset(); | 3565 handle1.Reset(); |
| 3548 | 3566 |
| 3549 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | 3567 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); |
| 3550 } | 3568 } |
| 3551 | 3569 |
| 3552 // Checks that fully connected preconnect jobs have no connect times, and are | 3570 // Checks that fully connected preconnect jobs have no connect times, and are |
| 3553 // marked as reused. | 3571 // marked as reused. |
| 3554 TEST_F(ClientSocketPoolBaseTest, ConnectedPreconnectJobsHaveNoConnectTimes) { | 3572 TEST_F(ClientSocketPoolBaseTest, ConnectedPreconnectJobsHaveNoConnectTimes) { |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3713 ASSERT_EQ(OK, callback.WaitForResult()); | 3731 ASSERT_EQ(OK, callback.WaitForResult()); |
| 3714 | 3732 |
| 3715 // The hung connect job should still be there, but everything else should be | 3733 // The hung connect job should still be there, but everything else should be |
| 3716 // complete. | 3734 // complete. |
| 3717 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | 3735 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); |
| 3718 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | 3736 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); |
| 3719 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | 3737 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); |
| 3720 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); | 3738 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); |
| 3721 } | 3739 } |
| 3722 | 3740 |
| 3741 // Tests that a preconnect that starts out with unread data can still be used. | |
| 3742 // http://crbug.com/334467 | |
|
mmenke
2014/03/18 15:16:55
Suggest a test where a reused socket with unread d
| |
| 3743 TEST_F(ClientSocketPoolBaseTest, PreconnectWithUnreadData) { | |
| 3744 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
| 3745 connect_job_factory_->set_job_type(TestConnectJob::kMockUnreadDataJob); | |
| 3746 | |
| 3747 pool_->RequestSockets("a", ¶ms_, 1, BoundNetLog()); | |
| 3748 | |
| 3749 ASSERT_TRUE(pool_->HasGroup("a")); | |
| 3750 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
| 3751 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
| 3752 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | |
| 3753 | |
| 3754 // Fail future jobs to be sure that handle receives the preconnected socket | |
| 3755 // rather than closing it and making a new one. | |
| 3756 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob); | |
| 3757 ClientSocketHandle handle; | |
| 3758 TestCompletionCallback callback; | |
| 3759 EXPECT_EQ(OK, handle.Init("a", | |
| 3760 params_, | |
| 3761 DEFAULT_PRIORITY, | |
| 3762 callback.callback(), | |
| 3763 pool_.get(), | |
| 3764 BoundNetLog())); | |
| 3765 | |
| 3766 ASSERT_TRUE(pool_->HasGroup("a")); | |
| 3767 EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a")); | |
| 3768 EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a")); | |
| 3769 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | |
| 3770 | |
| 3771 // Drain the pending read. | |
| 3772 EXPECT_EQ(1, handle.socket()->Read(NULL, 1, CompletionCallback())); | |
| 3773 | |
| 3774 TestLoadTimingInfoConnectedReused(handle); | |
| 3775 handle.Reset(); | |
| 3776 | |
| 3777 // The socket should be usable now that it's idle again. | |
| 3778 EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a")); | |
| 3779 } | |
| 3780 | |
| 3723 class MockLayeredPool : public HigherLayeredPool { | 3781 class MockLayeredPool : public HigherLayeredPool { |
| 3724 public: | 3782 public: |
| 3725 MockLayeredPool(TestClientSocketPool* pool, | 3783 MockLayeredPool(TestClientSocketPool* pool, |
| 3726 const std::string& group_name) | 3784 const std::string& group_name) |
| 3727 : pool_(pool), | 3785 : pool_(pool), |
| 3728 group_name_(group_name), | 3786 group_name_(group_name), |
| 3729 can_release_connection_(true) { | 3787 can_release_connection_(true) { |
| 3730 pool_->AddHigherLayeredPool(this); | 3788 pool_->AddHigherLayeredPool(this); |
| 3731 } | 3789 } |
| 3732 | 3790 |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4058 request(1)->handle()->Reset(); | 4116 request(1)->handle()->Reset(); |
| 4059 ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a")); | 4117 ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a")); |
| 4060 | 4118 |
| 4061 EXPECT_EQ(OK, request(2)->WaitForResult()); | 4119 EXPECT_EQ(OK, request(2)->WaitForResult()); |
| 4062 EXPECT_FALSE(request(1)->have_result()); | 4120 EXPECT_FALSE(request(1)->have_result()); |
| 4063 } | 4121 } |
| 4064 | 4122 |
| 4065 } // namespace | 4123 } // namespace |
| 4066 | 4124 |
| 4067 } // namespace net | 4125 } // namespace net |
| OLD | NEW |