| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |