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

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

Issue 160499: Add timeouts for ConnectJobs. Limit ConnectJobs per group to number of Requests per group + 1. (Closed)
Patch Set: Revert the revert. Fix tests. Created 11 years, 4 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
« no previous file with comments | « net/socket/client_socket_pool_base.cc ('k') | net/socket/tcp_client_socket_pool.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/platform_thread.h"
9 #include "base/scoped_vector.h" 10 #include "base/scoped_vector.h"
10 #include "net/base/net_errors.h" 11 #include "net/base/net_errors.h"
11 #include "net/base/test_completion_callback.h" 12 #include "net/base/test_completion_callback.h"
12 #include "net/socket/client_socket.h" 13 #include "net/socket/client_socket.h"
13 #include "net/socket/client_socket_factory.h" 14 #include "net/socket/client_socket_factory.h"
14 #include "net/socket/client_socket_handle.h" 15 #include "net/socket/client_socket_handle.h"
15 #include "net/socket/socket_test_util.h" 16 #include "net/socket/socket_test_util.h"
16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
17 18
18 namespace net { 19 namespace net {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 kMockFailingJob, 101 kMockFailingJob,
101 kMockPendingJob, 102 kMockPendingJob,
102 kMockPendingFailingJob, 103 kMockPendingFailingJob,
103 kMockWaitingJob, 104 kMockWaitingJob,
104 kMockAdvancingLoadStateJob, 105 kMockAdvancingLoadStateJob,
105 }; 106 };
106 107
107 TestConnectJob(JobType job_type, 108 TestConnectJob(JobType job_type,
108 const std::string& group_name, 109 const std::string& group_name,
109 const ClientSocketPoolBase::Request& request, 110 const ClientSocketPoolBase::Request& request,
111 base::TimeDelta timeout_duration,
110 ConnectJob::Delegate* delegate, 112 ConnectJob::Delegate* delegate,
111 MockClientSocketFactory* client_socket_factory) 113 MockClientSocketFactory* client_socket_factory)
112 : ConnectJob(group_name, request.handle, delegate), 114 : ConnectJob(group_name, request.handle, timeout_duration, delegate),
113 job_type_(job_type), 115 job_type_(job_type),
114 client_socket_factory_(client_socket_factory), 116 client_socket_factory_(client_socket_factory),
115 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} 117 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
116 118
119 void Signal() {
120 DoConnect(waiting_success_, true /* async */);
121 }
122
123 private:
117 // ConnectJob methods: 124 // ConnectJob methods:
118 125
119 virtual int Connect() { 126 virtual int ConnectInternal() {
120 AddressList ignored; 127 AddressList ignored;
121 client_socket_factory_->CreateTCPClientSocket(ignored); 128 client_socket_factory_->CreateTCPClientSocket(ignored);
122 switch (job_type_) { 129 switch (job_type_) {
123 case kMockJob: 130 case kMockJob:
124 return DoConnect(true /* successful */, false /* sync */); 131 return DoConnect(true /* successful */, false /* sync */);
125 case kMockFailingJob: 132 case kMockFailingJob:
126 return DoConnect(false /* error */, false /* sync */); 133 return DoConnect(false /* error */, false /* sync */);
127 case kMockPendingJob: 134 case kMockPendingJob:
128 set_load_state(LOAD_STATE_CONNECTING); 135 set_load_state(LOAD_STATE_CONNECTING);
129 MessageLoop::current()->PostTask( 136 MessageLoop::current()->PostTask(
(...skipping 21 matching lines...) Expand all
151 FROM_HERE, 158 FROM_HERE,
152 method_factory_.NewRunnableMethod( 159 method_factory_.NewRunnableMethod(
153 &TestConnectJob::AdvanceLoadState, load_state())); 160 &TestConnectJob::AdvanceLoadState, load_state()));
154 return ERR_IO_PENDING; 161 return ERR_IO_PENDING;
155 default: 162 default:
156 NOTREACHED(); 163 NOTREACHED();
157 return ERR_FAILED; 164 return ERR_FAILED;
158 } 165 }
159 } 166 }
160 167
161 void Signal() {
162 DoConnect(waiting_success_, true /* async */);
163 }
164
165 private:
166 int DoConnect(bool succeed, bool was_async) { 168 int DoConnect(bool succeed, bool was_async) {
167 int result = ERR_CONNECTION_FAILED; 169 int result = ERR_CONNECTION_FAILED;
168 if (succeed) { 170 if (succeed) {
169 result = OK; 171 result = OK;
170 set_socket(new MockClientSocket()); 172 set_socket(new MockClientSocket());
171 socket()->Connect(NULL); 173 socket()->Connect(NULL);
172 } 174 }
173 175
174 if (was_async) 176 if (was_async)
175 delegate()->OnConnectJobComplete(result, this); 177 delegate()->OnConnectJobComplete(result, this);
(...skipping 24 matching lines...) Expand all
200 class TestConnectJobFactory : public ClientSocketPoolBase::ConnectJobFactory { 202 class TestConnectJobFactory : public ClientSocketPoolBase::ConnectJobFactory {
201 public: 203 public:
202 explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory) 204 explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory)
203 : job_type_(TestConnectJob::kMockJob), 205 : job_type_(TestConnectJob::kMockJob),
204 client_socket_factory_(client_socket_factory) {} 206 client_socket_factory_(client_socket_factory) {}
205 207
206 virtual ~TestConnectJobFactory() {} 208 virtual ~TestConnectJobFactory() {}
207 209
208 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; } 210 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; }
209 211
212 void set_timeout_duration(base::TimeDelta timeout_duration) {
213 timeout_duration_ = timeout_duration;
214 }
215
210 // ConnectJobFactory methods: 216 // ConnectJobFactory methods:
211 217
212 virtual ConnectJob* NewConnectJob( 218 virtual ConnectJob* NewConnectJob(
213 const std::string& group_name, 219 const std::string& group_name,
214 const ClientSocketPoolBase::Request& request, 220 const ClientSocketPoolBase::Request& request,
215 ConnectJob::Delegate* delegate) const { 221 ConnectJob::Delegate* delegate) const {
216 return new TestConnectJob(job_type_, 222 return new TestConnectJob(job_type_,
217 group_name, 223 group_name,
218 request, 224 request,
225 timeout_duration_,
219 delegate, 226 delegate,
220 client_socket_factory_); 227 client_socket_factory_);
221 } 228 }
222 229
223 private: 230 private:
224 TestConnectJob::JobType job_type_; 231 TestConnectJob::JobType job_type_;
232 base::TimeDelta timeout_duration_;
225 MockClientSocketFactory* const client_socket_factory_; 233 MockClientSocketFactory* const client_socket_factory_;
226 234
227 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory); 235 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory);
228 }; 236 };
229 237
230 class TestClientSocketPool : public ClientSocketPool { 238 class TestClientSocketPool : public ClientSocketPool {
231 public: 239 public:
232 TestClientSocketPool( 240 TestClientSocketPool(
233 int max_sockets, 241 int max_sockets,
234 int max_sockets_per_group, 242 int max_sockets_per_group,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 return base_->IdleSocketCountInGroup(group_name); 276 return base_->IdleSocketCountInGroup(group_name);
269 } 277 }
270 278
271 virtual LoadState GetLoadState(const std::string& group_name, 279 virtual LoadState GetLoadState(const std::string& group_name,
272 const ClientSocketHandle* handle) const { 280 const ClientSocketHandle* handle) const {
273 return base_->GetLoadState(group_name, handle); 281 return base_->GetLoadState(group_name, handle);
274 } 282 }
275 283
276 const ClientSocketPoolBase* base() const { return base_.get(); } 284 const ClientSocketPoolBase* base() const { return base_.get(); }
277 285
286 int NumConnectJobsInGroup(const std::string& group_name) const {
287 return base_->NumConnectJobsInGroup(group_name);
288 }
289
278 private: 290 private:
279 const scoped_refptr<ClientSocketPoolBase> base_; 291 const scoped_refptr<ClientSocketPoolBase> base_;
280 292
281 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool); 293 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool);
282 }; 294 };
283 295
284 void MockClientSocketFactory::SignalJobs() { 296 void MockClientSocketFactory::SignalJobs() {
285 for (std::vector<TestConnectJob*>::iterator it = waiting_jobs_.begin(); 297 for (std::vector<TestConnectJob*>::iterator it = waiting_jobs_.begin();
286 it != waiting_jobs_.end(); ++it) { 298 it != waiting_jobs_.end(); ++it) {
287 (*it)->Signal(); 299 (*it)->Signal();
288 } 300 }
289 waiting_jobs_.clear(); 301 waiting_jobs_.clear();
290 } 302 }
291 303
304 class TestConnectJobDelegate : public ConnectJob::Delegate {
305 public:
306 TestConnectJobDelegate()
307 : have_result_(false), waiting_for_result_(false), result_(OK) {}
308 virtual ~TestConnectJobDelegate() {}
309
310 virtual void OnConnectJobComplete(int result, ConnectJob* job) {
311 result_ = result;
312 delete job;
313 have_result_ = true;
314 if (waiting_for_result_)
315 MessageLoop::current()->Quit();
316 }
317
318 int WaitForResult() {
319 DCHECK(!waiting_for_result_);
320 while (!have_result_) {
321 waiting_for_result_ = true;
322 MessageLoop::current()->Run();
323 waiting_for_result_ = false;
324 }
325 have_result_ = false; // auto-reset for next callback
326 return result_;
327 }
328
329 private:
330 bool have_result_;
331 bool waiting_for_result_;
332 int result_;
333 };
334
292 class ClientSocketPoolBaseTest : public ClientSocketPoolTest { 335 class ClientSocketPoolBaseTest : public ClientSocketPoolTest {
293 protected: 336 protected:
294 ClientSocketPoolBaseTest() 337 ClientSocketPoolBaseTest()
295 : connect_job_factory_( 338 : connect_job_factory_(
296 new TestConnectJobFactory(&client_socket_factory_)) {} 339 new TestConnectJobFactory(&client_socket_factory_)) {}
297 340
298 void CreatePool(int max_sockets, int max_sockets_per_group) { 341 void CreatePool(int max_sockets, int max_sockets_per_group) {
299 DCHECK(!pool_.get()); 342 DCHECK(!pool_.get());
300 pool_ = new TestClientSocketPool(max_sockets, 343 pool_ = new TestClientSocketPool(max_sockets,
301 max_sockets_per_group, 344 max_sockets_per_group,
(...skipping 15 matching lines...) Expand all
317 ClientSocketPoolBase::EnableLateBindingOfSockets(false); 360 ClientSocketPoolBase::EnableLateBindingOfSockets(false);
318 361
319 ClientSocketPoolTest::TearDown(); 362 ClientSocketPoolTest::TearDown();
320 } 363 }
321 364
322 MockClientSocketFactory client_socket_factory_; 365 MockClientSocketFactory client_socket_factory_;
323 TestConnectJobFactory* const connect_job_factory_; 366 TestConnectJobFactory* const connect_job_factory_;
324 scoped_refptr<TestClientSocketPool> pool_; 367 scoped_refptr<TestClientSocketPool> pool_;
325 }; 368 };
326 369
370 // Even though a timeout is specified, it doesn't time out on a synchronous
371 // completion.
372 TEST_F(ClientSocketPoolBaseTest, ConnectJob_NoTimeoutOnSynchronousCompletion) {
373 TestConnectJobDelegate delegate;
374 ClientSocketPoolBase::Request request;
375 ClientSocketHandle ignored(pool_.get());
376 request.handle = &ignored;
377 scoped_ptr<TestConnectJob> job(
378 new TestConnectJob(TestConnectJob::kMockJob,
379 "a",
380 request,
381 base::TimeDelta::FromMicroseconds(1),
382 &delegate,
383 &client_socket_factory_));
384 EXPECT_EQ(OK, job->Connect());
385 }
386
387 TEST_F(ClientSocketPoolBaseTest, ConnectJob_TimedOut) {
388 TestConnectJobDelegate delegate;
389 ClientSocketPoolBase::Request request;
390 ClientSocketHandle ignored(pool_.get());
391 request.handle = &ignored;
392 // Deleted by TestConnectJobDelegate.
393 TestConnectJob* job =
394 new TestConnectJob(TestConnectJob::kMockPendingJob,
395 "a",
396 request,
397 base::TimeDelta::FromMicroseconds(1),
398 &delegate,
399 &client_socket_factory_);
400 ASSERT_EQ(ERR_IO_PENDING, job->Connect());
401 PlatformThread::Sleep(1);
402 EXPECT_EQ(ERR_TIMED_OUT, delegate.WaitForResult());
403 }
404
327 TEST_F(ClientSocketPoolBaseTest, BasicSynchronous) { 405 TEST_F(ClientSocketPoolBaseTest, BasicSynchronous) {
328 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); 406 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
329 407
330 TestCompletionCallback callback; 408 TestCompletionCallback callback;
331 ClientSocketHandle handle(pool_.get()); 409 ClientSocketHandle handle(pool_.get());
332 EXPECT_EQ(OK, handle.Init("a", ignored_request_info_, kDefaultPriority, 410 EXPECT_EQ(OK, handle.Init("a", ignored_request_info_, kDefaultPriority,
333 &callback)); 411 &callback));
334 EXPECT_TRUE(handle.is_initialized()); 412 EXPECT_TRUE(handle.is_initialized());
335 EXPECT_TRUE(handle.socket()); 413 EXPECT_TRUE(handle.socket());
336 handle.Reset(); 414 handle.Reset();
(...skipping 866 matching lines...) Expand 10 before | Expand all | Expand 10 after
1203 EXPECT_EQ(5, GetOrderOfRequest(3)); 1281 EXPECT_EQ(5, GetOrderOfRequest(3));
1204 EXPECT_EQ(3, GetOrderOfRequest(4)); 1282 EXPECT_EQ(3, GetOrderOfRequest(4));
1205 EXPECT_EQ(kRequestNotFound, GetOrderOfRequest(5)); // Canceled request. 1283 EXPECT_EQ(kRequestNotFound, GetOrderOfRequest(5)); // Canceled request.
1206 EXPECT_EQ(4, GetOrderOfRequest(6)); 1284 EXPECT_EQ(4, GetOrderOfRequest(6));
1207 EXPECT_EQ(6, GetOrderOfRequest(7)); 1285 EXPECT_EQ(6, GetOrderOfRequest(7));
1208 1286
1209 // Make sure we test order of all requests made. 1287 // Make sure we test order of all requests made.
1210 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8)); 1288 EXPECT_EQ(kIndexOutOfBounds, GetOrderOfRequest(8));
1211 } 1289 }
1212 1290
1291 TEST_F(ClientSocketPoolBaseTest_LateBinding, CancelRequestLimitsJobs) {
1292 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1293
1294 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
1295
1296 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 1));
1297 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 2));
1298 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 3));
1299 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", 4));
1300
1301 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a"));
1302 requests_[2]->handle()->Reset();
1303 requests_[3]->handle()->Reset();
1304 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a"));
1305
1306 requests_[1]->handle()->Reset();
1307 EXPECT_EQ(kDefaultMaxSocketsPerGroup, pool_->NumConnectJobsInGroup("a"));
1308
1309 requests_[0]->handle()->Reset();
1310 EXPECT_EQ(kDefaultMaxSocketsPerGroup - 1, pool_->NumConnectJobsInGroup("a"));
1311 }
1312
1213 TEST_F(ClientSocketPoolBaseTest_LateBinding, RequestPendingJobTwice) { 1313 TEST_F(ClientSocketPoolBaseTest_LateBinding, RequestPendingJobTwice) {
1214 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); 1314 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
1215 1315
1216 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); 1316 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
1217 ClientSocketHandle handle(pool_.get()); 1317 ClientSocketHandle handle(pool_.get());
1218 RequestSocketCallback callback( 1318 RequestSocketCallback callback(
1219 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob); 1319 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob);
1220 int rv = handle.Init( 1320 int rv = handle.Init(
1221 "a", ignored_request_info_, kDefaultPriority, &callback); 1321 "a", ignored_request_info_, kDefaultPriority, &callback);
1222 ASSERT_EQ(ERR_IO_PENDING, rv); 1322 ASSERT_EQ(ERR_IO_PENDING, rv);
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1443 // Closing idle sockets should not get us into trouble, but in the bug 1543 // Closing idle sockets should not get us into trouble, but in the bug
1444 // we were hitting a CHECK here. 1544 // we were hitting a CHECK here.
1445 EXPECT_EQ(2, pool_->IdleSocketCountInGroup("a")); 1545 EXPECT_EQ(2, pool_->IdleSocketCountInGroup("a"));
1446 pool_->CloseIdleSockets(); 1546 pool_->CloseIdleSockets();
1447 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); 1547 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
1448 } 1548 }
1449 1549
1450 } // namespace 1550 } // namespace
1451 1551
1452 } // namespace net 1552 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/client_socket_pool_base.cc ('k') | net/socket/tcp_client_socket_pool.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698