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> | |
8 | |
9 #include "base/bind.h" | 7 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
11 #include "base/callback.h" | 9 #include "base/callback.h" |
12 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
13 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
14 #include "base/memory/scoped_vector.h" | 12 #include "base/memory/scoped_vector.h" |
15 #include "base/memory/weak_ptr.h" | 13 #include "base/memory/weak_ptr.h" |
16 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
17 #include "base/stringprintf.h" | 15 #include "base/stringprintf.h" |
18 #include "base/string_number_conversions.h" | 16 #include "base/string_number_conversions.h" |
19 #include "base/threading/platform_thread.h" | 17 #include "base/threading/platform_thread.h" |
20 #include "base/values.h" | 18 #include "base/values.h" |
21 #include "net/base/net_errors.h" | 19 #include "net/base/net_errors.h" |
22 #include "net/base/net_log.h" | 20 #include "net/base/net_log.h" |
23 #include "net/base/net_log_unittest.h" | 21 #include "net/base/net_log_unittest.h" |
24 #include "net/base/request_priority.h" | 22 #include "net/base/request_priority.h" |
25 #include "net/base/test_completion_callback.h" | 23 #include "net/base/test_completion_callback.h" |
26 #include "net/http/http_response_headers.h" | 24 #include "net/http/http_response_headers.h" |
27 #include "net/socket/client_socket_factory.h" | 25 #include "net/socket/client_socket_factory.h" |
28 #include "net/socket/client_socket_handle.h" | 26 #include "net/socket/client_socket_handle.h" |
29 #include "net/socket/client_socket_pool_histograms.h" | 27 #include "net/socket/client_socket_pool_histograms.h" |
30 #include "net/socket/socket_test_util.h" | 28 #include "net/socket/socket_test_util.h" |
31 #include "net/socket/ssl_host_info.h" | 29 #include "net/socket/ssl_host_info.h" |
32 #include "net/socket/stream_socket.h" | 30 #include "net/socket/stream_socket.h" |
33 #include "testing/gmock/include/gmock/gmock.h" | |
34 #include "testing/gtest/include/gtest/gtest.h" | 31 #include "testing/gtest/include/gtest/gtest.h" |
35 | 32 |
36 using ::testing::Invoke; | |
37 using ::testing::Return; | |
38 | |
39 namespace net { | 33 namespace net { |
40 | 34 |
41 namespace { | 35 namespace { |
42 | 36 |
43 const int kDefaultMaxSockets = 4; | 37 const int kDefaultMaxSockets = 4; |
44 const int kDefaultMaxSocketsPerGroup = 2; | 38 const int kDefaultMaxSocketsPerGroup = 2; |
45 const net::RequestPriority kDefaultPriority = MEDIUM; | 39 const net::RequestPriority kDefaultPriority = MEDIUM; |
46 | 40 |
47 class TestSocketParams : public base::RefCounted<TestSocketParams> { | 41 class TestSocketParams : public base::RefCounted<TestSocketParams> { |
48 public: | 42 public: |
49 TestSocketParams() : ignore_limits_(false) {} | 43 bool ignore_limits() { return false; } |
50 | |
51 void set_ignore_limits(bool ignore_limits) { | |
52 ignore_limits_ = ignore_limits; | |
53 } | |
54 bool ignore_limits() { return ignore_limits_; } | |
55 | |
56 private: | 44 private: |
57 friend class base::RefCounted<TestSocketParams>; | 45 friend class base::RefCounted<TestSocketParams>; |
58 ~TestSocketParams() {} | 46 ~TestSocketParams() {} |
59 | |
60 bool ignore_limits_; | |
61 }; | 47 }; |
62 typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase; | 48 typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase; |
63 | 49 |
64 class MockClientSocket : public StreamSocket { | 50 class MockClientSocket : public StreamSocket { |
65 public: | 51 public: |
66 MockClientSocket() : connected_(false), was_used_to_convey_data_(false), | 52 MockClientSocket() : connected_(false), was_used_to_convey_data_(false), |
67 num_bytes_read_(0) {} | 53 num_bytes_read_(0) {} |
68 | 54 |
69 // Socket implementation. | 55 // Socket implementation. |
70 virtual int Read( | 56 virtual int Read( |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 bool store_additional_error_state_; | 351 bool store_additional_error_state_; |
366 | 352 |
367 DISALLOW_COPY_AND_ASSIGN(TestConnectJob); | 353 DISALLOW_COPY_AND_ASSIGN(TestConnectJob); |
368 }; | 354 }; |
369 | 355 |
370 class TestConnectJobFactory | 356 class TestConnectJobFactory |
371 : public TestClientSocketPoolBase::ConnectJobFactory { | 357 : public TestClientSocketPoolBase::ConnectJobFactory { |
372 public: | 358 public: |
373 explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory) | 359 explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory) |
374 : job_type_(TestConnectJob::kMockJob), | 360 : job_type_(TestConnectJob::kMockJob), |
375 job_types_(NULL), | |
376 client_socket_factory_(client_socket_factory) {} | 361 client_socket_factory_(client_socket_factory) {} |
377 | 362 |
378 virtual ~TestConnectJobFactory() {} | 363 virtual ~TestConnectJobFactory() {} |
379 | 364 |
380 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; } | 365 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; } |
381 | 366 |
382 void set_job_types(std::list<TestConnectJob::JobType>* job_types) { | |
383 job_types_ = job_types; | |
384 CHECK(!job_types_->empty()); | |
385 } | |
386 | |
387 void set_timeout_duration(base::TimeDelta timeout_duration) { | 367 void set_timeout_duration(base::TimeDelta timeout_duration) { |
388 timeout_duration_ = timeout_duration; | 368 timeout_duration_ = timeout_duration; |
389 } | 369 } |
390 | 370 |
391 // ConnectJobFactory implementation. | 371 // ConnectJobFactory implementation. |
392 | 372 |
393 virtual ConnectJob* NewConnectJob( | 373 virtual ConnectJob* NewConnectJob( |
394 const std::string& group_name, | 374 const std::string& group_name, |
395 const TestClientSocketPoolBase::Request& request, | 375 const TestClientSocketPoolBase::Request& request, |
396 ConnectJob::Delegate* delegate) const { | 376 ConnectJob::Delegate* delegate) const { |
397 EXPECT_TRUE(!job_types_ || !job_types_->empty()); | 377 return new TestConnectJob(job_type_, |
398 TestConnectJob::JobType job_type = job_type_; | |
399 if (job_types_ && !job_types_->empty()) { | |
400 job_type = job_types_->front(); | |
401 job_types_->pop_front(); | |
402 } | |
403 return new TestConnectJob(job_type, | |
404 group_name, | 378 group_name, |
405 request, | 379 request, |
406 timeout_duration_, | 380 timeout_duration_, |
407 delegate, | 381 delegate, |
408 client_socket_factory_, | 382 client_socket_factory_, |
409 NULL); | 383 NULL); |
410 } | 384 } |
411 | 385 |
412 virtual base::TimeDelta ConnectionTimeout() const { | 386 virtual base::TimeDelta ConnectionTimeout() const { |
413 return timeout_duration_; | 387 return timeout_duration_; |
414 } | 388 } |
415 | 389 |
416 private: | 390 private: |
417 TestConnectJob::JobType job_type_; | 391 TestConnectJob::JobType job_type_; |
418 std::list<TestConnectJob::JobType>* job_types_; | |
419 base::TimeDelta timeout_duration_; | 392 base::TimeDelta timeout_duration_; |
420 MockClientSocketFactory* const client_socket_factory_; | 393 MockClientSocketFactory* const client_socket_factory_; |
421 | 394 |
422 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory); | 395 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory); |
423 }; | 396 }; |
424 | 397 |
425 class TestClientSocketPool : public ClientSocketPool { | 398 class TestClientSocketPool : public ClientSocketPool { |
426 public: | 399 public: |
427 TestClientSocketPool( | 400 TestClientSocketPool( |
428 int max_sockets, | 401 int max_sockets, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 const std::string& group_name, | 443 const std::string& group_name, |
471 StreamSocket* socket, | 444 StreamSocket* socket, |
472 int id) OVERRIDE { | 445 int id) OVERRIDE { |
473 base_.ReleaseSocket(group_name, socket, id); | 446 base_.ReleaseSocket(group_name, socket, id); |
474 } | 447 } |
475 | 448 |
476 virtual void Flush() OVERRIDE { | 449 virtual void Flush() OVERRIDE { |
477 base_.Flush(); | 450 base_.Flush(); |
478 } | 451 } |
479 | 452 |
480 virtual bool IsStalled() const OVERRIDE { | |
481 return base_.IsStalled(); | |
482 } | |
483 | |
484 virtual void CloseIdleSockets() OVERRIDE { | 453 virtual void CloseIdleSockets() OVERRIDE { |
485 base_.CloseIdleSockets(); | 454 base_.CloseIdleSockets(); |
486 } | 455 } |
487 | 456 |
488 virtual int IdleSocketCount() const OVERRIDE { | 457 virtual int IdleSocketCount() const OVERRIDE { |
489 return base_.idle_socket_count(); | 458 return base_.idle_socket_count(); |
490 } | 459 } |
491 | 460 |
492 virtual int IdleSocketCountInGroup( | 461 virtual int IdleSocketCountInGroup( |
493 const std::string& group_name) const OVERRIDE { | 462 const std::string& group_name) const OVERRIDE { |
494 return base_.IdleSocketCountInGroup(group_name); | 463 return base_.IdleSocketCountInGroup(group_name); |
495 } | 464 } |
496 | 465 |
497 virtual LoadState GetLoadState( | 466 virtual LoadState GetLoadState( |
498 const std::string& group_name, | 467 const std::string& group_name, |
499 const ClientSocketHandle* handle) const OVERRIDE { | 468 const ClientSocketHandle* handle) const OVERRIDE { |
500 return base_.GetLoadState(group_name, handle); | 469 return base_.GetLoadState(group_name, handle); |
501 } | 470 } |
502 | 471 |
503 virtual void AddLayeredPool(LayeredPool* pool) OVERRIDE { | |
504 base_.AddLayeredPool(pool); | |
505 } | |
506 | |
507 virtual void RemoveLayeredPool(LayeredPool* pool) OVERRIDE { | |
508 base_.RemoveLayeredPool(pool); | |
509 } | |
510 | |
511 virtual DictionaryValue* GetInfoAsValue( | 472 virtual DictionaryValue* GetInfoAsValue( |
512 const std::string& name, | 473 const std::string& name, |
513 const std::string& type, | 474 const std::string& type, |
514 bool include_nested_pools) const OVERRIDE { | 475 bool include_nested_pools) const OVERRIDE { |
515 return base_.GetInfoAsValue(name, type); | 476 return base_.GetInfoAsValue(name, type); |
516 } | 477 } |
517 | 478 |
518 virtual base::TimeDelta ConnectionTimeout() const OVERRIDE { | 479 virtual base::TimeDelta ConnectionTimeout() const OVERRIDE { |
519 return base_.ConnectionTimeout(); | 480 return base_.ConnectionTimeout(); |
520 } | 481 } |
(...skipping 13 matching lines...) Expand all Loading... |
534 } | 495 } |
535 | 496 |
536 bool HasGroup(const std::string& group_name) const { | 497 bool HasGroup(const std::string& group_name) const { |
537 return base_.HasGroup(group_name); | 498 return base_.HasGroup(group_name); |
538 } | 499 } |
539 | 500 |
540 void CleanupTimedOutIdleSockets() { base_.CleanupIdleSockets(false); } | 501 void CleanupTimedOutIdleSockets() { base_.CleanupIdleSockets(false); } |
541 | 502 |
542 void EnableConnectBackupJobs() { base_.EnableConnectBackupJobs(); } | 503 void EnableConnectBackupJobs() { base_.EnableConnectBackupJobs(); } |
543 | 504 |
544 bool CloseOneIdleConnectionInLayeredPool() { | |
545 return base_.CloseOneIdleConnectionInLayeredPool(); | |
546 } | |
547 | |
548 private: | 505 private: |
549 TestClientSocketPoolBase base_; | 506 TestClientSocketPoolBase base_; |
550 | 507 |
551 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool); | 508 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool); |
552 }; | 509 }; |
553 | 510 |
554 } // namespace | 511 } // namespace |
555 | 512 |
556 REGISTER_SOCKET_PARAMS_FOR_POOL(TestClientSocketPool, TestSocketParams); | 513 REGISTER_SOCKET_PARAMS_FOR_POOL(TestClientSocketPool, TestSocketParams); |
557 | 514 |
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1203 EXPECT_EQ(1, pool_->IdleSocketCount()); | 1160 EXPECT_EQ(1, pool_->IdleSocketCount()); |
1204 } | 1161 } |
1205 | 1162 |
1206 TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) { | 1163 TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) { |
1207 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | 1164 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
1208 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | 1165 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
1209 | 1166 |
1210 ClientSocketHandle stalled_handle; | 1167 ClientSocketHandle stalled_handle; |
1211 TestCompletionCallback callback; | 1168 TestCompletionCallback callback; |
1212 { | 1169 { |
1213 EXPECT_FALSE(pool_->IsStalled()); | |
1214 ClientSocketHandle handles[kDefaultMaxSockets]; | 1170 ClientSocketHandle handles[kDefaultMaxSockets]; |
1215 for (int i = 0; i < kDefaultMaxSockets; ++i) { | 1171 for (int i = 0; i < kDefaultMaxSockets; ++i) { |
1216 TestCompletionCallback callback; | 1172 TestCompletionCallback callback; |
1217 EXPECT_EQ(OK, handles[i].Init(base::StringPrintf( | 1173 EXPECT_EQ(OK, handles[i].Init(base::StringPrintf( |
1218 "Take 2: %d", i), | 1174 "Take 2: %d", i), |
1219 params_, | 1175 params_, |
1220 kDefaultPriority, | 1176 kDefaultPriority, |
1221 callback.callback(), | 1177 callback.callback(), |
1222 pool_.get(), | 1178 pool_.get(), |
1223 BoundNetLog())); | 1179 BoundNetLog())); |
1224 } | 1180 } |
1225 | 1181 |
1226 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); | 1182 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); |
1227 EXPECT_EQ(0, pool_->IdleSocketCount()); | 1183 EXPECT_EQ(0, pool_->IdleSocketCount()); |
1228 EXPECT_FALSE(pool_->IsStalled()); | |
1229 | 1184 |
1230 // Now we will hit the socket limit. | 1185 // Now we will hit the socket limit. |
1231 EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo", | 1186 EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo", |
1232 params_, | 1187 params_, |
1233 kDefaultPriority, | 1188 kDefaultPriority, |
1234 callback.callback(), | 1189 callback.callback(), |
1235 pool_.get(), | 1190 pool_.get(), |
1236 BoundNetLog())); | 1191 BoundNetLog())); |
1237 EXPECT_TRUE(pool_->IsStalled()); | |
1238 | 1192 |
1239 // Dropping out of scope will close all handles and return them to idle. | 1193 // Dropping out of scope will close all handles and return them to idle. |
1240 } | 1194 } |
1241 | 1195 |
1242 // But if we wait for it, the released idle sockets will be closed in | 1196 // But if we wait for it, the released idle sockets will be closed in |
1243 // preference of the waiting request. | 1197 // preference of the waiting request. |
1244 EXPECT_EQ(OK, callback.WaitForResult()); | 1198 EXPECT_EQ(OK, callback.WaitForResult()); |
1245 | 1199 |
1246 EXPECT_EQ(kDefaultMaxSockets + 1, client_socket_factory_.allocation_count()); | 1200 EXPECT_EQ(kDefaultMaxSockets + 1, client_socket_factory_.allocation_count()); |
1247 EXPECT_EQ(3, pool_->IdleSocketCount()); | 1201 EXPECT_EQ(3, pool_->IdleSocketCount()); |
(...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2047 // job. Release the socket. Run the loop again to make sure the second | 2001 // job. Release the socket. Run the loop again to make sure the second |
2048 // socket is sitting idle and the first one is released (since ReleaseSocket() | 2002 // socket is sitting idle and the first one is released (since ReleaseSocket() |
2049 // just posts a DoReleaseSocket() task). | 2003 // just posts a DoReleaseSocket() task). |
2050 | 2004 |
2051 handle.Reset(); | 2005 handle.Reset(); |
2052 EXPECT_EQ(OK, callback2.WaitForResult()); | 2006 EXPECT_EQ(OK, callback2.WaitForResult()); |
2053 // Use the socket. | 2007 // Use the socket. |
2054 EXPECT_EQ(1, handle2.socket()->Write(NULL, 1, CompletionCallback())); | 2008 EXPECT_EQ(1, handle2.socket()->Write(NULL, 1, CompletionCallback())); |
2055 handle2.Reset(); | 2009 handle2.Reset(); |
2056 | 2010 |
2057 // The idle socket timeout value was set to 10 milliseconds. Wait 100 | 2011 // The idle socket timeout value was set to 10 milliseconds. Wait 20 |
2058 // milliseconds so the sockets timeout. | 2012 // milliseconds so the sockets timeout. |
2059 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | 2013 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20)); |
2060 MessageLoop::current()->RunAllPending(); | 2014 MessageLoop::current()->RunAllPending(); |
2061 | 2015 |
2062 ASSERT_EQ(2, pool_->IdleSocketCount()); | 2016 ASSERT_EQ(2, pool_->IdleSocketCount()); |
2063 | 2017 |
2064 // Request a new socket. This should cleanup the unused and timed out ones. | 2018 // Request a new socket. This should cleanup the unused and timed out ones. |
2065 // A new socket will be created rather than reusing the idle one. | 2019 // A new socket will be created rather than reusing the idle one. |
2066 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); | 2020 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); |
2067 TestCompletionCallback callback3; | 2021 TestCompletionCallback callback3; |
2068 rv = handle.Init("a", | 2022 rv = handle.Init("a", |
2069 params_, | 2023 params_, |
(...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3081 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); | 3035 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); |
3082 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 3036 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
3083 | 3037 |
3084 ASSERT_FALSE(pool_->HasGroup("a")); | 3038 ASSERT_FALSE(pool_->HasGroup("a")); |
3085 | 3039 |
3086 pool_->RequestSockets("a", ¶ms_, kDefaultMaxSockets - 1, | 3040 pool_->RequestSockets("a", ¶ms_, kDefaultMaxSockets - 1, |
3087 BoundNetLog()); | 3041 BoundNetLog()); |
3088 | 3042 |
3089 ASSERT_TRUE(pool_->HasGroup("a")); | 3043 ASSERT_TRUE(pool_->HasGroup("a")); |
3090 EXPECT_EQ(kDefaultMaxSockets - 1, pool_->NumConnectJobsInGroup("a")); | 3044 EXPECT_EQ(kDefaultMaxSockets - 1, pool_->NumConnectJobsInGroup("a")); |
3091 EXPECT_FALSE(pool_->IsStalled()); | |
3092 | 3045 |
3093 ASSERT_FALSE(pool_->HasGroup("b")); | 3046 ASSERT_FALSE(pool_->HasGroup("b")); |
3094 | 3047 |
3095 pool_->RequestSockets("b", ¶ms_, kDefaultMaxSockets, | 3048 pool_->RequestSockets("b", ¶ms_, kDefaultMaxSockets, |
3096 BoundNetLog()); | 3049 BoundNetLog()); |
3097 | 3050 |
3098 ASSERT_TRUE(pool_->HasGroup("b")); | 3051 ASSERT_TRUE(pool_->HasGroup("b")); |
3099 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("b")); | 3052 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("b")); |
3100 EXPECT_FALSE(pool_->IsStalled()); | |
3101 } | 3053 } |
3102 | 3054 |
3103 TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountIdleSockets) { | 3055 TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountIdleSockets) { |
3104 CreatePool(4, 4); | 3056 CreatePool(4, 4); |
3105 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 3057 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
3106 | 3058 |
3107 ClientSocketHandle handle1; | 3059 ClientSocketHandle handle1; |
3108 TestCompletionCallback callback1; | 3060 TestCompletionCallback callback1; |
3109 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", | 3061 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", |
3110 params_, | 3062 params_, |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3409 EXPECT_EQ(0, pool_->NumActiveSocketsInGroup("a")); | 3361 EXPECT_EQ(0, pool_->NumActiveSocketsInGroup("a")); |
3410 ASSERT_EQ(OK, callback.WaitForResult()); | 3362 ASSERT_EQ(OK, callback.WaitForResult()); |
3411 | 3363 |
3412 // The hung connect job should still be there, but everything else should be | 3364 // The hung connect job should still be there, but everything else should be |
3413 // complete. | 3365 // complete. |
3414 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | 3366 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); |
3415 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | 3367 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); |
3416 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); | 3368 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); |
3417 } | 3369 } |
3418 | 3370 |
3419 class MockLayeredPool : public LayeredPool { | |
3420 public: | |
3421 MockLayeredPool(TestClientSocketPool* pool, | |
3422 const std::string& group_name) | |
3423 : pool_(pool), | |
3424 params_(new TestSocketParams), | |
3425 group_name_(group_name), | |
3426 can_release_connection_(true) { | |
3427 pool_->AddLayeredPool(this); | |
3428 } | |
3429 | |
3430 ~MockLayeredPool() { | |
3431 pool_->RemoveLayeredPool(this); | |
3432 } | |
3433 | |
3434 int RequestSocket(TestClientSocketPool* pool) { | |
3435 return handle_.Init(group_name_, params_, kDefaultPriority, | |
3436 callback_.callback(), pool, BoundNetLog()); | |
3437 } | |
3438 | |
3439 int RequestSocketWithoutLimits(TestClientSocketPool* pool) { | |
3440 params_->set_ignore_limits(true); | |
3441 return handle_.Init(group_name_, params_, kDefaultPriority, | |
3442 callback_.callback(), pool, BoundNetLog()); | |
3443 } | |
3444 | |
3445 bool ReleaseOneConnection() { | |
3446 if (!handle_.is_initialized() || !can_release_connection_) { | |
3447 return false; | |
3448 } | |
3449 handle_.socket()->Disconnect(); | |
3450 handle_.Reset(); | |
3451 return true; | |
3452 } | |
3453 | |
3454 void set_can_release_connection(bool can_release_connection) { | |
3455 can_release_connection_ = can_release_connection; | |
3456 } | |
3457 | |
3458 MOCK_METHOD0(CloseOneIdleConnection, bool()); | |
3459 | |
3460 private: | |
3461 TestClientSocketPool* const pool_; | |
3462 scoped_refptr<TestSocketParams> params_; | |
3463 ClientSocketHandle handle_; | |
3464 TestCompletionCallback callback_; | |
3465 const std::string group_name_; | |
3466 bool can_release_connection_; | |
3467 }; | |
3468 | |
3469 TEST_F(ClientSocketPoolBaseTest, FailToCloseIdleSocketsNotHeldByLayeredPool) { | |
3470 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3471 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
3472 | |
3473 MockLayeredPool mock_layered_pool(pool_.get(), "foo"); | |
3474 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); | |
3475 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) | |
3476 .WillOnce(Return(false)); | |
3477 EXPECT_FALSE(pool_->CloseOneIdleConnectionInLayeredPool()); | |
3478 } | |
3479 | |
3480 TEST_F(ClientSocketPoolBaseTest, ForciblyCloseIdleSocketsHeldByLayeredPool) { | |
3481 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | |
3482 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
3483 | |
3484 MockLayeredPool mock_layered_pool(pool_.get(), "foo"); | |
3485 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); | |
3486 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) | |
3487 .WillOnce(Invoke(&mock_layered_pool, | |
3488 &MockLayeredPool::ReleaseOneConnection)); | |
3489 EXPECT_TRUE(pool_->CloseOneIdleConnectionInLayeredPool()); | |
3490 } | |
3491 | |
3492 // This test exercises the codepath which caused http://crbug.com/109876 | |
3493 TEST_F(ClientSocketPoolBaseTest, | |
3494 CloseIdleSocketsHeldByLayeredPoolInSameGroupWhenNeeded) { | |
3495 CreatePool(2, 2); | |
3496 std::list<TestConnectJob::JobType> job_types; | |
3497 job_types.push_back(TestConnectJob::kMockJob); | |
3498 job_types.push_back(TestConnectJob::kMockJob); | |
3499 job_types.push_back(TestConnectJob::kMockFailingJob); | |
3500 job_types.push_back(TestConnectJob::kMockJob); | |
3501 connect_job_factory_->set_job_types(&job_types); | |
3502 | |
3503 ClientSocketHandle handle1; | |
3504 TestCompletionCallback callback1; | |
3505 EXPECT_EQ(OK, handle1.Init("group1", | |
3506 params_, | |
3507 kDefaultPriority, | |
3508 callback1.callback(), | |
3509 pool_.get(), | |
3510 BoundNetLog())); | |
3511 | |
3512 MockLayeredPool mock_layered_pool(pool_.get(), "group2"); | |
3513 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); | |
3514 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) | |
3515 .WillRepeatedly(Invoke(&mock_layered_pool, | |
3516 &MockLayeredPool::ReleaseOneConnection)); | |
3517 mock_layered_pool.set_can_release_connection(false); | |
3518 | |
3519 // This connection attempt will fail when the next request causes the | |
3520 // MockLayeredPool to delete the socket it's holding. This request is | |
3521 // needed to trigger the destruction of the "group2" Group. | |
3522 ClientSocketHandle handle3; | |
3523 TestCompletionCallback callback3; | |
3524 EXPECT_EQ(ERR_IO_PENDING, handle3.Init("group2", | |
3525 params_, | |
3526 kDefaultPriority, | |
3527 callback3.callback(), | |
3528 pool_.get(), | |
3529 BoundNetLog())); | |
3530 | |
3531 mock_layered_pool.set_can_release_connection(true); | |
3532 ClientSocketHandle handle4; | |
3533 TestCompletionCallback callback4; | |
3534 EXPECT_EQ(OK, handle4.Init("group2", | |
3535 params_, | |
3536 kDefaultPriority, | |
3537 callback4.callback(), | |
3538 pool_.get(), | |
3539 BoundNetLog())); | |
3540 } | |
3541 | |
3542 TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketsHeldByLayeredPoolWhenNeeded) { | |
3543 CreatePool(1, 1); | |
3544 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
3545 | |
3546 MockLayeredPool mock_layered_pool(pool_.get(), "foo"); | |
3547 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get())); | |
3548 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection()) | |
3549 .WillOnce(Invoke(&mock_layered_pool, | |
3550 &MockLayeredPool::ReleaseOneConnection)); | |
3551 ClientSocketHandle handle; | |
3552 TestCompletionCallback callback; | |
3553 EXPECT_EQ(OK, handle.Init("a", | |
3554 params_, | |
3555 kDefaultPriority, | |
3556 callback.callback(), | |
3557 pool_.get(), | |
3558 BoundNetLog())); | |
3559 } | |
3560 | |
3561 TEST_F(ClientSocketPoolBaseTest, | |
3562 CloseMultipleIdleSocketsHeldByLayeredPoolWhenNeeded) { | |
3563 CreatePool(1, 1); | |
3564 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | |
3565 | |
3566 MockLayeredPool mock_layered_pool1(pool_.get(), "foo"); | |
3567 EXPECT_EQ(OK, mock_layered_pool1.RequestSocket(pool_.get())); | |
3568 EXPECT_CALL(mock_layered_pool1, CloseOneIdleConnection()) | |
3569 .WillRepeatedly(Invoke(&mock_layered_pool1, | |
3570 &MockLayeredPool::ReleaseOneConnection)); | |
3571 MockLayeredPool mock_layered_pool2(pool_.get(), "bar"); | |
3572 EXPECT_EQ(OK, mock_layered_pool2.RequestSocketWithoutLimits(pool_.get())); | |
3573 EXPECT_CALL(mock_layered_pool2, CloseOneIdleConnection()) | |
3574 .WillRepeatedly(Invoke(&mock_layered_pool2, | |
3575 &MockLayeredPool::ReleaseOneConnection)); | |
3576 ClientSocketHandle handle; | |
3577 TestCompletionCallback callback; | |
3578 EXPECT_EQ(OK, handle.Init("a", | |
3579 params_, | |
3580 kDefaultPriority, | |
3581 callback.callback(), | |
3582 pool_.get(), | |
3583 BoundNetLog())); | |
3584 } | |
3585 | |
3586 } // namespace | 3371 } // namespace |
3587 | 3372 |
3588 } // namespace net | 3373 } // namespace net |
OLD | NEW |