Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: net/socket/client_socket_pool_base_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698