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

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

Issue 8340012: Close idle connections / SPDY sessions when needed. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: OVERRIDE Created 9 years, 1 month 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/callback.h" 7 #include "base/callback.h"
8 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/memory/ref_counted.h" 9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_vector.h" 10 #include "base/memory/scoped_vector.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
13 #include "base/string_number_conversions.h" 13 #include "base/string_number_conversions.h"
14 #include "base/threading/platform_thread.h" 14 #include "base/threading/platform_thread.h"
15 #include "base/values.h" 15 #include "base/values.h"
16 #include "net/base/net_errors.h" 16 #include "net/base/net_errors.h"
17 #include "net/base/net_log.h" 17 #include "net/base/net_log.h"
18 #include "net/base/net_log_unittest.h" 18 #include "net/base/net_log_unittest.h"
19 #include "net/base/request_priority.h" 19 #include "net/base/request_priority.h"
20 #include "net/base/test_completion_callback.h" 20 #include "net/base/test_completion_callback.h"
21 #include "net/http/http_response_headers.h" 21 #include "net/http/http_response_headers.h"
22 #include "net/socket/client_socket_factory.h" 22 #include "net/socket/client_socket_factory.h"
23 #include "net/socket/client_socket_handle.h" 23 #include "net/socket/client_socket_handle.h"
24 #include "net/socket/client_socket_pool_histograms.h" 24 #include "net/socket/client_socket_pool_histograms.h"
25 #include "net/socket/socket_test_util.h" 25 #include "net/socket/socket_test_util.h"
26 #include "net/socket/ssl_host_info.h" 26 #include "net/socket/ssl_host_info.h"
27 #include "net/socket/stream_socket.h" 27 #include "net/socket/stream_socket.h"
28 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h" 29 #include "testing/gtest/include/gtest/gtest.h"
29 30
31 using ::testing::Invoke;
32 using ::testing::Return;
33
30 namespace net { 34 namespace net {
31 35
32 namespace { 36 namespace {
33 37
34 const int kDefaultMaxSockets = 4; 38 const int kDefaultMaxSockets = 4;
35 const int kDefaultMaxSocketsPerGroup = 2; 39 const int kDefaultMaxSocketsPerGroup = 2;
36 const net::RequestPriority kDefaultPriority = MEDIUM; 40 const net::RequestPriority kDefaultPriority = MEDIUM;
37 41
38 class TestSocketParams : public base::RefCounted<TestSocketParams> { 42 class TestSocketParams : public base::RefCounted<TestSocketParams> {
39 public: 43 public:
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 ClientSocketPoolHistograms* histograms, 402 ClientSocketPoolHistograms* histograms,
399 base::TimeDelta unused_idle_socket_timeout, 403 base::TimeDelta unused_idle_socket_timeout,
400 base::TimeDelta used_idle_socket_timeout, 404 base::TimeDelta used_idle_socket_timeout,
401 TestClientSocketPoolBase::ConnectJobFactory* connect_job_factory) 405 TestClientSocketPoolBase::ConnectJobFactory* connect_job_factory)
402 : base_(max_sockets, max_sockets_per_group, histograms, 406 : base_(max_sockets, max_sockets_per_group, histograms,
403 unused_idle_socket_timeout, used_idle_socket_timeout, 407 unused_idle_socket_timeout, used_idle_socket_timeout,
404 connect_job_factory) {} 408 connect_job_factory) {}
405 409
406 virtual ~TestClientSocketPool() {} 410 virtual ~TestClientSocketPool() {}
407 411
412 void AddLayeredPool(LayeredPool* pool) {
413 base_.AddLayeredPool(pool);
414 }
415
416 void RemoveLayeredPool(LayeredPool* pool) {
417 base_.RemoveLayeredPool(pool);
418 }
419
408 virtual int RequestSocket( 420 virtual int RequestSocket(
409 const std::string& group_name, 421 const std::string& group_name,
410 const void* params, 422 const void* params,
411 net::RequestPriority priority, 423 net::RequestPriority priority,
412 ClientSocketHandle* handle, 424 ClientSocketHandle* handle,
413 OldCompletionCallback* callback, 425 OldCompletionCallback* callback,
414 const BoundNetLog& net_log) { 426 const BoundNetLog& net_log) {
415 const scoped_refptr<TestSocketParams>* casted_socket_params = 427 const scoped_refptr<TestSocketParams>* casted_socket_params =
416 static_cast<const scoped_refptr<TestSocketParams>*>(params); 428 static_cast<const scoped_refptr<TestSocketParams>*>(params);
417 return base_.RequestSocket(group_name, *casted_socket_params, priority, 429 return base_.RequestSocket(group_name, *casted_socket_params, priority,
418 handle, callback, net_log); 430 handle, callback, net_log);
419 } 431 }
420 432
421 virtual void RequestSockets(const std::string& group_name, 433 virtual void RequestSockets(const std::string& group_name,
422 const void* params, 434 const void* params,
423 int num_sockets, 435 int num_sockets,
424 const BoundNetLog& net_log) { 436 const BoundNetLog& net_log) OVERRIDE {
425 const scoped_refptr<TestSocketParams>* casted_params = 437 const scoped_refptr<TestSocketParams>* casted_params =
426 static_cast<const scoped_refptr<TestSocketParams>*>(params); 438 static_cast<const scoped_refptr<TestSocketParams>*>(params);
427 439
428 base_.RequestSockets(group_name, *casted_params, num_sockets, net_log); 440 base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
429 } 441 }
430 442
431 virtual void CancelRequest( 443 virtual void CancelRequest(
432 const std::string& group_name, 444 const std::string& group_name,
433 ClientSocketHandle* handle) { 445 ClientSocketHandle* handle) OVERRIDE {
434 base_.CancelRequest(group_name, handle); 446 base_.CancelRequest(group_name, handle);
435 } 447 }
436 448
437 virtual void ReleaseSocket( 449 virtual void ReleaseSocket(
438 const std::string& group_name, 450 const std::string& group_name,
439 StreamSocket* socket, 451 StreamSocket* socket,
440 int id) { 452 int id) OVERRIDE {
441 base_.ReleaseSocket(group_name, socket, id); 453 base_.ReleaseSocket(group_name, socket, id);
442 } 454 }
443 455
444 virtual void Flush() { 456 virtual void Flush() OVERRIDE {
445 base_.Flush(); 457 base_.Flush();
446 } 458 }
447 459
448 virtual void CloseIdleSockets() { 460 virtual bool IsStalled() const OVERRIDE {
461 return base_.IsStalled();
462 }
463
464 virtual void CloseIdleSockets() OVERRIDE {
449 base_.CloseIdleSockets(); 465 base_.CloseIdleSockets();
450 } 466 }
451 467
452 virtual int IdleSocketCount() const { return base_.idle_socket_count(); } 468 virtual int IdleSocketCount() const OVERRIDE {
469 return base_.idle_socket_count();
470 }
453 471
454 virtual int IdleSocketCountInGroup(const std::string& group_name) const { 472 virtual int IdleSocketCountInGroup(
473 const std::string& group_name) const OVERRIDE {
455 return base_.IdleSocketCountInGroup(group_name); 474 return base_.IdleSocketCountInGroup(group_name);
456 } 475 }
457 476
458 virtual LoadState GetLoadState(const std::string& group_name, 477 virtual LoadState GetLoadState(
459 const ClientSocketHandle* handle) const { 478 const std::string& group_name,
479 const ClientSocketHandle* handle) const OVERRIDE {
460 return base_.GetLoadState(group_name, handle); 480 return base_.GetLoadState(group_name, handle);
461 } 481 }
462 482
463 virtual DictionaryValue* GetInfoAsValue(const std::string& name, 483 virtual DictionaryValue* GetInfoAsValue(
464 const std::string& type, 484 const std::string& name,
465 bool include_nested_pools) const { 485 const std::string& type,
486 bool include_nested_pools) const OVERRIDE {
466 return base_.GetInfoAsValue(name, type); 487 return base_.GetInfoAsValue(name, type);
467 } 488 }
468 489
469 virtual base::TimeDelta ConnectionTimeout() const { 490 virtual base::TimeDelta ConnectionTimeout() const OVERRIDE {
470 return base_.ConnectionTimeout(); 491 return base_.ConnectionTimeout();
471 } 492 }
472 493
473 virtual ClientSocketPoolHistograms* histograms() const { 494 virtual ClientSocketPoolHistograms* histograms() const OVERRIDE {
474 return base_.histograms(); 495 return base_.histograms();
475 } 496 }
476 497
477 const TestClientSocketPoolBase* base() const { return &base_; } 498 const TestClientSocketPoolBase* base() const { return &base_; }
478 499
479 int NumConnectJobsInGroup(const std::string& group_name) const { 500 int NumConnectJobsInGroup(const std::string& group_name) const {
480 return base_.NumConnectJobsInGroup(group_name); 501 return base_.NumConnectJobsInGroup(group_name);
481 } 502 }
482 503
483 int NumActiveSocketsInGroup(const std::string& group_name) const { 504 int NumActiveSocketsInGroup(const std::string& group_name) const {
484 return base_.NumActiveSocketsInGroup(group_name); 505 return base_.NumActiveSocketsInGroup(group_name);
485 } 506 }
486 507
487 bool HasGroup(const std::string& group_name) const { 508 bool HasGroup(const std::string& group_name) const {
488 return base_.HasGroup(group_name); 509 return base_.HasGroup(group_name);
489 } 510 }
490 511
491 void CleanupTimedOutIdleSockets() { base_.CleanupIdleSockets(false); } 512 void CleanupTimedOutIdleSockets() { base_.CleanupIdleSockets(false); }
492 513
493 void EnableConnectBackupJobs() { base_.EnableConnectBackupJobs(); } 514 void EnableConnectBackupJobs() { base_.EnableConnectBackupJobs(); }
494 515
516 bool CloseOneIdleConnectionInLayeredPool() {
517 return base_.CloseOneIdleConnectionInLayeredPool();
518 }
519
495 private: 520 private:
496 TestClientSocketPoolBase base_; 521 TestClientSocketPoolBase base_;
497 522
498 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool); 523 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool);
499 }; 524 };
500 525
501 } // namespace 526 } // namespace
502 527
503 REGISTER_SOCKET_PARAMS_FOR_POOL(TestClientSocketPool, TestSocketParams); 528 REGISTER_SOCKET_PARAMS_FOR_POOL(TestClientSocketPool, TestSocketParams);
504 529
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
1145 EXPECT_EQ(1, pool_->IdleSocketCount()); 1170 EXPECT_EQ(1, pool_->IdleSocketCount());
1146 } 1171 }
1147 1172
1148 TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) { 1173 TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) {
1149 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); 1174 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
1150 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); 1175 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
1151 1176
1152 ClientSocketHandle stalled_handle; 1177 ClientSocketHandle stalled_handle;
1153 TestOldCompletionCallback callback; 1178 TestOldCompletionCallback callback;
1154 { 1179 {
1180 EXPECT_FALSE(pool_->IsStalled());
1155 ClientSocketHandle handles[kDefaultMaxSockets]; 1181 ClientSocketHandle handles[kDefaultMaxSockets];
1156 for (int i = 0; i < kDefaultMaxSockets; ++i) { 1182 for (int i = 0; i < kDefaultMaxSockets; ++i) {
1157 TestOldCompletionCallback callback; 1183 TestOldCompletionCallback callback;
1158 EXPECT_EQ(OK, handles[i].Init(base::StringPrintf( 1184 EXPECT_EQ(OK, handles[i].Init(base::StringPrintf(
1159 "Take 2: %d", i), 1185 "Take 2: %d", i),
1160 params_, 1186 params_,
1161 kDefaultPriority, 1187 kDefaultPriority,
1162 &callback, 1188 &callback,
1163 pool_.get(), 1189 pool_.get(),
1164 BoundNetLog())); 1190 BoundNetLog()));
1165 } 1191 }
1166 1192
1167 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); 1193 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
1168 EXPECT_EQ(0, pool_->IdleSocketCount()); 1194 EXPECT_EQ(0, pool_->IdleSocketCount());
1195 EXPECT_FALSE(pool_->IsStalled());
1169 1196
1170 // Now we will hit the socket limit. 1197 // Now we will hit the socket limit.
1171 EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo", 1198 EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo",
1172 params_, 1199 params_,
1173 kDefaultPriority, 1200 kDefaultPriority,
1174 &callback, 1201 &callback,
1175 pool_.get(), 1202 pool_.get(),
1176 BoundNetLog())); 1203 BoundNetLog()));
1204 EXPECT_TRUE(pool_->IsStalled());
1177 1205
1178 // Dropping out of scope will close all handles and return them to idle. 1206 // Dropping out of scope will close all handles and return them to idle.
1179 } 1207 }
1180 1208
1181 // But if we wait for it, the released idle sockets will be closed in 1209 // But if we wait for it, the released idle sockets will be closed in
1182 // preference of the waiting request. 1210 // preference of the waiting request.
1183 EXPECT_EQ(OK, callback.WaitForResult()); 1211 EXPECT_EQ(OK, callback.WaitForResult());
1184 1212
1185 EXPECT_EQ(kDefaultMaxSockets + 1, client_socket_factory_.allocation_count()); 1213 EXPECT_EQ(kDefaultMaxSockets + 1, client_socket_factory_.allocation_count());
1186 EXPECT_EQ(3, pool_->IdleSocketCount()); 1214 EXPECT_EQ(3, pool_->IdleSocketCount());
(...skipping 1750 matching lines...) Expand 10 before | Expand all | Expand 10 after
2937 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); 2965 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets);
2938 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); 2966 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
2939 2967
2940 ASSERT_FALSE(pool_->HasGroup("a")); 2968 ASSERT_FALSE(pool_->HasGroup("a"));
2941 2969
2942 pool_->RequestSockets("a", &params_, kDefaultMaxSockets - 1, 2970 pool_->RequestSockets("a", &params_, kDefaultMaxSockets - 1,
2943 BoundNetLog()); 2971 BoundNetLog());
2944 2972
2945 ASSERT_TRUE(pool_->HasGroup("a")); 2973 ASSERT_TRUE(pool_->HasGroup("a"));
2946 EXPECT_EQ(kDefaultMaxSockets - 1, pool_->NumConnectJobsInGroup("a")); 2974 EXPECT_EQ(kDefaultMaxSockets - 1, pool_->NumConnectJobsInGroup("a"));
2975 EXPECT_FALSE(pool_->IsStalled());
2947 2976
2948 ASSERT_FALSE(pool_->HasGroup("b")); 2977 ASSERT_FALSE(pool_->HasGroup("b"));
2949 2978
2950 pool_->RequestSockets("b", &params_, kDefaultMaxSockets, 2979 pool_->RequestSockets("b", &params_, kDefaultMaxSockets,
2951 BoundNetLog()); 2980 BoundNetLog());
2952 2981
2953 ASSERT_TRUE(pool_->HasGroup("b")); 2982 ASSERT_TRUE(pool_->HasGroup("b"));
2954 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("b")); 2983 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("b"));
2984 EXPECT_FALSE(pool_->IsStalled());
2955 } 2985 }
2956 2986
2957 TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountIdleSockets) { 2987 TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountIdleSockets) {
2958 CreatePool(4, 4); 2988 CreatePool(4, 4);
2959 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); 2989 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
2960 2990
2961 ClientSocketHandle handle1; 2991 ClientSocketHandle handle1;
2962 TestOldCompletionCallback callback1; 2992 TestOldCompletionCallback callback1;
2963 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", 2993 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
2964 params_, 2994 params_,
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
3263 EXPECT_EQ(0, pool_->NumActiveSocketsInGroup("a")); 3293 EXPECT_EQ(0, pool_->NumActiveSocketsInGroup("a"));
3264 ASSERT_EQ(OK, callback.WaitForResult()); 3294 ASSERT_EQ(OK, callback.WaitForResult());
3265 3295
3266 // The hung connect job should still be there, but everything else should be 3296 // The hung connect job should still be there, but everything else should be
3267 // complete. 3297 // complete.
3268 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); 3298 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a"));
3269 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); 3299 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
3270 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); 3300 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a"));
3271 } 3301 }
3272 3302
3303 class MockLayeredPool : public LayeredPool {
3304 public:
3305 MockLayeredPool(TestClientSocketPool* pool)
3306 : pool_(pool),
3307 params_(new TestSocketParams) {
3308 pool_->AddLayeredPool(this);
3309 }
3310
3311 ~MockLayeredPool() {
3312 pool_->RemoveLayeredPool(this);
3313 }
3314
3315 int RequestSocket(TestClientSocketPool* pool) {
3316 return handle_.Init("foo", params_, kDefaultPriority, &callback_,
3317 pool, BoundNetLog());
3318 }
3319
3320 bool ReleaseOneConnection() {
3321 if (!handle_.is_initialized()) {
3322 return false;
3323 }
3324 handle_.Reset();
3325 return true;
3326 }
3327
3328 MOCK_METHOD0(CloseOneIdleConnection, bool());
3329
3330 private:
3331 TestClientSocketPool* const pool_;
3332 scoped_refptr<TestSocketParams> params_;
3333 ClientSocketHandle handle_;
3334 TestOldCompletionCallback callback_;
3335 };
3336
3337 TEST_F(ClientSocketPoolBaseTest, FailToCloseIdleSocketsNotHeldByLayeredPool) {
3338 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
3339 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
3340
3341 MockLayeredPool mock_layered_pool(pool_.get());
3342 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection())
3343 .WillOnce(Return(false));
3344 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get()));
3345 EXPECT_FALSE(pool_->CloseOneIdleConnectionInLayeredPool());
3346 }
3347
3348 TEST_F(ClientSocketPoolBaseTest, ForciblyCloseIdleSocketsHeldByLayeredPool) {
3349 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
3350 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
3351
3352 MockLayeredPool mock_layered_pool(pool_.get());
3353 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get()));
mmenke 2011/10/27 18:52:37 Don't think you need to request a socket twice in
willchan no longer on Chromium 2011/11/08 22:26:13 Done.
3354 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection())
3355 .WillOnce(Invoke(&mock_layered_pool,
3356 &MockLayeredPool::ReleaseOneConnection));
3357 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get()));
3358 EXPECT_TRUE(pool_->CloseOneIdleConnectionInLayeredPool());
3359 }
3360
3361 TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketsHeldByLayeredPoolWhenNeeded) {
3362 CreatePool(1, 1);
3363 connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
3364
3365 MockLayeredPool mock_layered_pool(pool_.get());
3366 EXPECT_EQ(OK, mock_layered_pool.RequestSocket(pool_.get()));
3367 EXPECT_CALL(mock_layered_pool, CloseOneIdleConnection())
3368 .WillOnce(Invoke(&mock_layered_pool,
3369 &MockLayeredPool::ReleaseOneConnection));
3370 ClientSocketHandle handle;
3371 TestOldCompletionCallback callback;
3372 EXPECT_EQ(OK, handle.Init("a",
3373 params_,
3374 kDefaultPriority,
3375 &callback,
3376 pool_.get(),
3377 BoundNetLog()));
3378 }
3379
3273 } // namespace 3380 } // namespace
3274 3381
3275 } // namespace net 3382 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698