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 |
7 #include "base/bind.h" | 9 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
9 #include "base/callback.h" | 11 #include "base/callback.h" |
10 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
11 #include "base/memory/ref_counted.h" | 13 #include "base/memory/ref_counted.h" |
12 #include "base/memory/scoped_vector.h" | 14 #include "base/memory/scoped_vector.h" |
13 #include "base/memory/weak_ptr.h" | 15 #include "base/memory/weak_ptr.h" |
14 #include "base/message_loop.h" | 16 #include "base/message_loop.h" |
15 #include "base/stringprintf.h" | 17 #include "base/stringprintf.h" |
16 #include "base/string_number_conversions.h" | 18 #include "base/string_number_conversions.h" |
17 #include "base/threading/platform_thread.h" | 19 #include "base/threading/platform_thread.h" |
18 #include "base/values.h" | 20 #include "base/values.h" |
19 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
20 #include "net/base/net_log.h" | 22 #include "net/base/net_log.h" |
21 #include "net/base/net_log_unittest.h" | 23 #include "net/base/net_log_unittest.h" |
22 #include "net/base/request_priority.h" | 24 #include "net/base/request_priority.h" |
23 #include "net/base/test_completion_callback.h" | 25 #include "net/base/test_completion_callback.h" |
24 #include "net/http/http_response_headers.h" | 26 #include "net/http/http_response_headers.h" |
25 #include "net/socket/client_socket_factory.h" | 27 #include "net/socket/client_socket_factory.h" |
26 #include "net/socket/client_socket_handle.h" | 28 #include "net/socket/client_socket_handle.h" |
27 #include "net/socket/client_socket_pool_histograms.h" | 29 #include "net/socket/client_socket_pool_histograms.h" |
28 #include "net/socket/socket_test_util.h" | 30 #include "net/socket/socket_test_util.h" |
29 #include "net/socket/ssl_host_info.h" | 31 #include "net/socket/ssl_host_info.h" |
30 #include "net/socket/stream_socket.h" | 32 #include "net/socket/stream_socket.h" |
| 33 #include "testing/gmock/include/gmock/gmock.h" |
31 #include "testing/gtest/include/gtest/gtest.h" | 34 #include "testing/gtest/include/gtest/gtest.h" |
32 | 35 |
| 36 using ::testing::Invoke; |
| 37 using ::testing::Return; |
| 38 |
33 namespace net { | 39 namespace net { |
34 | 40 |
35 namespace { | 41 namespace { |
36 | 42 |
37 const int kDefaultMaxSockets = 4; | 43 const int kDefaultMaxSockets = 4; |
38 const int kDefaultMaxSocketsPerGroup = 2; | 44 const int kDefaultMaxSocketsPerGroup = 2; |
39 const net::RequestPriority kDefaultPriority = MEDIUM; | 45 const net::RequestPriority kDefaultPriority = MEDIUM; |
40 | 46 |
41 class TestSocketParams : public base::RefCounted<TestSocketParams> { | 47 class TestSocketParams : public base::RefCounted<TestSocketParams> { |
42 public: | 48 public: |
43 bool ignore_limits() { return false; } | 49 TestSocketParams() : ignore_limits_(false) {} |
| 50 |
| 51 void set_ignore_limits(bool ignore_limits) { |
| 52 ignore_limits_ = ignore_limits; |
| 53 } |
| 54 bool ignore_limits() { return ignore_limits_; } |
| 55 |
44 private: | 56 private: |
45 friend class base::RefCounted<TestSocketParams>; | 57 friend class base::RefCounted<TestSocketParams>; |
46 ~TestSocketParams() {} | 58 ~TestSocketParams() {} |
| 59 |
| 60 bool ignore_limits_; |
47 }; | 61 }; |
48 typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase; | 62 typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase; |
49 | 63 |
50 class MockClientSocket : public StreamSocket { | 64 class MockClientSocket : public StreamSocket { |
51 public: | 65 public: |
52 MockClientSocket() : connected_(false), was_used_to_convey_data_(false), | 66 MockClientSocket() : connected_(false), was_used_to_convey_data_(false), |
53 num_bytes_read_(0) {} | 67 num_bytes_read_(0) {} |
54 | 68 |
55 // Socket implementation. | 69 // Socket implementation. |
56 virtual int Read( | 70 virtual int Read( |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 bool store_additional_error_state_; | 365 bool store_additional_error_state_; |
352 | 366 |
353 DISALLOW_COPY_AND_ASSIGN(TestConnectJob); | 367 DISALLOW_COPY_AND_ASSIGN(TestConnectJob); |
354 }; | 368 }; |
355 | 369 |
356 class TestConnectJobFactory | 370 class TestConnectJobFactory |
357 : public TestClientSocketPoolBase::ConnectJobFactory { | 371 : public TestClientSocketPoolBase::ConnectJobFactory { |
358 public: | 372 public: |
359 explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory) | 373 explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory) |
360 : job_type_(TestConnectJob::kMockJob), | 374 : job_type_(TestConnectJob::kMockJob), |
| 375 job_types_(NULL), |
361 client_socket_factory_(client_socket_factory) {} | 376 client_socket_factory_(client_socket_factory) {} |
362 | 377 |
363 virtual ~TestConnectJobFactory() {} | 378 virtual ~TestConnectJobFactory() {} |
364 | 379 |
365 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; } | 380 void set_job_type(TestConnectJob::JobType job_type) { job_type_ = job_type; } |
366 | 381 |
| 382 void set_job_types(std::list<TestConnectJob::JobType>* job_types) { |
| 383 job_types_ = job_types; |
| 384 CHECK(!job_types_->empty()); |
| 385 } |
| 386 |
367 void set_timeout_duration(base::TimeDelta timeout_duration) { | 387 void set_timeout_duration(base::TimeDelta timeout_duration) { |
368 timeout_duration_ = timeout_duration; | 388 timeout_duration_ = timeout_duration; |
369 } | 389 } |
370 | 390 |
371 // ConnectJobFactory implementation. | 391 // ConnectJobFactory implementation. |
372 | 392 |
373 virtual ConnectJob* NewConnectJob( | 393 virtual ConnectJob* NewConnectJob( |
374 const std::string& group_name, | 394 const std::string& group_name, |
375 const TestClientSocketPoolBase::Request& request, | 395 const TestClientSocketPoolBase::Request& request, |
376 ConnectJob::Delegate* delegate) const { | 396 ConnectJob::Delegate* delegate) const { |
377 return new TestConnectJob(job_type_, | 397 EXPECT_TRUE(!job_types_ || !job_types_->empty()); |
| 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, |
378 group_name, | 404 group_name, |
379 request, | 405 request, |
380 timeout_duration_, | 406 timeout_duration_, |
381 delegate, | 407 delegate, |
382 client_socket_factory_, | 408 client_socket_factory_, |
383 NULL); | 409 NULL); |
384 } | 410 } |
385 | 411 |
386 virtual base::TimeDelta ConnectionTimeout() const { | 412 virtual base::TimeDelta ConnectionTimeout() const { |
387 return timeout_duration_; | 413 return timeout_duration_; |
388 } | 414 } |
389 | 415 |
390 private: | 416 private: |
391 TestConnectJob::JobType job_type_; | 417 TestConnectJob::JobType job_type_; |
| 418 std::list<TestConnectJob::JobType>* job_types_; |
392 base::TimeDelta timeout_duration_; | 419 base::TimeDelta timeout_duration_; |
393 MockClientSocketFactory* const client_socket_factory_; | 420 MockClientSocketFactory* const client_socket_factory_; |
394 | 421 |
395 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory); | 422 DISALLOW_COPY_AND_ASSIGN(TestConnectJobFactory); |
396 }; | 423 }; |
397 | 424 |
398 class TestClientSocketPool : public ClientSocketPool { | 425 class TestClientSocketPool : public ClientSocketPool { |
399 public: | 426 public: |
400 TestClientSocketPool( | 427 TestClientSocketPool( |
401 int max_sockets, | 428 int max_sockets, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 const std::string& group_name, | 470 const std::string& group_name, |
444 StreamSocket* socket, | 471 StreamSocket* socket, |
445 int id) OVERRIDE { | 472 int id) OVERRIDE { |
446 base_.ReleaseSocket(group_name, socket, id); | 473 base_.ReleaseSocket(group_name, socket, id); |
447 } | 474 } |
448 | 475 |
449 virtual void Flush() OVERRIDE { | 476 virtual void Flush() OVERRIDE { |
450 base_.Flush(); | 477 base_.Flush(); |
451 } | 478 } |
452 | 479 |
| 480 virtual bool IsStalled() const OVERRIDE { |
| 481 return base_.IsStalled(); |
| 482 } |
| 483 |
453 virtual void CloseIdleSockets() OVERRIDE { | 484 virtual void CloseIdleSockets() OVERRIDE { |
454 base_.CloseIdleSockets(); | 485 base_.CloseIdleSockets(); |
455 } | 486 } |
456 | 487 |
457 virtual int IdleSocketCount() const OVERRIDE { | 488 virtual int IdleSocketCount() const OVERRIDE { |
458 return base_.idle_socket_count(); | 489 return base_.idle_socket_count(); |
459 } | 490 } |
460 | 491 |
461 virtual int IdleSocketCountInGroup( | 492 virtual int IdleSocketCountInGroup( |
462 const std::string& group_name) const OVERRIDE { | 493 const std::string& group_name) const OVERRIDE { |
463 return base_.IdleSocketCountInGroup(group_name); | 494 return base_.IdleSocketCountInGroup(group_name); |
464 } | 495 } |
465 | 496 |
466 virtual LoadState GetLoadState( | 497 virtual LoadState GetLoadState( |
467 const std::string& group_name, | 498 const std::string& group_name, |
468 const ClientSocketHandle* handle) const OVERRIDE { | 499 const ClientSocketHandle* handle) const OVERRIDE { |
469 return base_.GetLoadState(group_name, handle); | 500 return base_.GetLoadState(group_name, handle); |
470 } | 501 } |
471 | 502 |
| 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 |
472 virtual DictionaryValue* GetInfoAsValue( | 511 virtual DictionaryValue* GetInfoAsValue( |
473 const std::string& name, | 512 const std::string& name, |
474 const std::string& type, | 513 const std::string& type, |
475 bool include_nested_pools) const OVERRIDE { | 514 bool include_nested_pools) const OVERRIDE { |
476 return base_.GetInfoAsValue(name, type); | 515 return base_.GetInfoAsValue(name, type); |
477 } | 516 } |
478 | 517 |
479 virtual base::TimeDelta ConnectionTimeout() const OVERRIDE { | 518 virtual base::TimeDelta ConnectionTimeout() const OVERRIDE { |
480 return base_.ConnectionTimeout(); | 519 return base_.ConnectionTimeout(); |
481 } | 520 } |
(...skipping 13 matching lines...) Expand all Loading... |
495 } | 534 } |
496 | 535 |
497 bool HasGroup(const std::string& group_name) const { | 536 bool HasGroup(const std::string& group_name) const { |
498 return base_.HasGroup(group_name); | 537 return base_.HasGroup(group_name); |
499 } | 538 } |
500 | 539 |
501 void CleanupTimedOutIdleSockets() { base_.CleanupIdleSockets(false); } | 540 void CleanupTimedOutIdleSockets() { base_.CleanupIdleSockets(false); } |
502 | 541 |
503 void EnableConnectBackupJobs() { base_.EnableConnectBackupJobs(); } | 542 void EnableConnectBackupJobs() { base_.EnableConnectBackupJobs(); } |
504 | 543 |
| 544 bool CloseOneIdleConnectionInLayeredPool() { |
| 545 return base_.CloseOneIdleConnectionInLayeredPool(); |
| 546 } |
| 547 |
505 private: | 548 private: |
506 TestClientSocketPoolBase base_; | 549 TestClientSocketPoolBase base_; |
507 | 550 |
508 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool); | 551 DISALLOW_COPY_AND_ASSIGN(TestClientSocketPool); |
509 }; | 552 }; |
510 | 553 |
511 } // namespace | 554 } // namespace |
512 | 555 |
513 REGISTER_SOCKET_PARAMS_FOR_POOL(TestClientSocketPool, TestSocketParams); | 556 REGISTER_SOCKET_PARAMS_FOR_POOL(TestClientSocketPool, TestSocketParams); |
514 | 557 |
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1160 EXPECT_EQ(1, pool_->IdleSocketCount()); | 1203 EXPECT_EQ(1, pool_->IdleSocketCount()); |
1161 } | 1204 } |
1162 | 1205 |
1163 TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) { | 1206 TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) { |
1164 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); | 1207 CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup); |
1165 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | 1208 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
1166 | 1209 |
1167 ClientSocketHandle stalled_handle; | 1210 ClientSocketHandle stalled_handle; |
1168 TestCompletionCallback callback; | 1211 TestCompletionCallback callback; |
1169 { | 1212 { |
| 1213 EXPECT_FALSE(pool_->IsStalled()); |
1170 ClientSocketHandle handles[kDefaultMaxSockets]; | 1214 ClientSocketHandle handles[kDefaultMaxSockets]; |
1171 for (int i = 0; i < kDefaultMaxSockets; ++i) { | 1215 for (int i = 0; i < kDefaultMaxSockets; ++i) { |
1172 TestCompletionCallback callback; | 1216 TestCompletionCallback callback; |
1173 EXPECT_EQ(OK, handles[i].Init(base::StringPrintf( | 1217 EXPECT_EQ(OK, handles[i].Init(base::StringPrintf( |
1174 "Take 2: %d", i), | 1218 "Take 2: %d", i), |
1175 params_, | 1219 params_, |
1176 kDefaultPriority, | 1220 kDefaultPriority, |
1177 callback.callback(), | 1221 callback.callback(), |
1178 pool_.get(), | 1222 pool_.get(), |
1179 BoundNetLog())); | 1223 BoundNetLog())); |
1180 } | 1224 } |
1181 | 1225 |
1182 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); | 1226 EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); |
1183 EXPECT_EQ(0, pool_->IdleSocketCount()); | 1227 EXPECT_EQ(0, pool_->IdleSocketCount()); |
| 1228 EXPECT_FALSE(pool_->IsStalled()); |
1184 | 1229 |
1185 // Now we will hit the socket limit. | 1230 // Now we will hit the socket limit. |
1186 EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo", | 1231 EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo", |
1187 params_, | 1232 params_, |
1188 kDefaultPriority, | 1233 kDefaultPriority, |
1189 callback.callback(), | 1234 callback.callback(), |
1190 pool_.get(), | 1235 pool_.get(), |
1191 BoundNetLog())); | 1236 BoundNetLog())); |
| 1237 EXPECT_TRUE(pool_->IsStalled()); |
1192 | 1238 |
1193 // Dropping out of scope will close all handles and return them to idle. | 1239 // Dropping out of scope will close all handles and return them to idle. |
1194 } | 1240 } |
1195 | 1241 |
1196 // But if we wait for it, the released idle sockets will be closed in | 1242 // But if we wait for it, the released idle sockets will be closed in |
1197 // preference of the waiting request. | 1243 // preference of the waiting request. |
1198 EXPECT_EQ(OK, callback.WaitForResult()); | 1244 EXPECT_EQ(OK, callback.WaitForResult()); |
1199 | 1245 |
1200 EXPECT_EQ(kDefaultMaxSockets + 1, client_socket_factory_.allocation_count()); | 1246 EXPECT_EQ(kDefaultMaxSockets + 1, client_socket_factory_.allocation_count()); |
1201 EXPECT_EQ(3, pool_->IdleSocketCount()); | 1247 EXPECT_EQ(3, pool_->IdleSocketCount()); |
(...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2001 // job. Release the socket. Run the loop again to make sure the second | 2047 // job. Release the socket. Run the loop again to make sure the second |
2002 // socket is sitting idle and the first one is released (since ReleaseSocket() | 2048 // socket is sitting idle and the first one is released (since ReleaseSocket() |
2003 // just posts a DoReleaseSocket() task). | 2049 // just posts a DoReleaseSocket() task). |
2004 | 2050 |
2005 handle.Reset(); | 2051 handle.Reset(); |
2006 EXPECT_EQ(OK, callback2.WaitForResult()); | 2052 EXPECT_EQ(OK, callback2.WaitForResult()); |
2007 // Use the socket. | 2053 // Use the socket. |
2008 EXPECT_EQ(1, handle2.socket()->Write(NULL, 1, CompletionCallback())); | 2054 EXPECT_EQ(1, handle2.socket()->Write(NULL, 1, CompletionCallback())); |
2009 handle2.Reset(); | 2055 handle2.Reset(); |
2010 | 2056 |
2011 // The idle socket timeout value was set to 10 milliseconds. Wait 20 | 2057 // The idle socket timeout value was set to 10 milliseconds. Wait 100 |
2012 // milliseconds so the sockets timeout. | 2058 // milliseconds so the sockets timeout. |
2013 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20)); | 2059 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); |
2014 MessageLoop::current()->RunAllPending(); | 2060 MessageLoop::current()->RunAllPending(); |
2015 | 2061 |
2016 ASSERT_EQ(2, pool_->IdleSocketCount()); | 2062 ASSERT_EQ(2, pool_->IdleSocketCount()); |
2017 | 2063 |
2018 // Request a new socket. This should cleanup the unused and timed out ones. | 2064 // Request a new socket. This should cleanup the unused and timed out ones. |
2019 // A new socket will be created rather than reusing the idle one. | 2065 // A new socket will be created rather than reusing the idle one. |
2020 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); | 2066 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); |
2021 TestCompletionCallback callback3; | 2067 TestCompletionCallback callback3; |
2022 rv = handle.Init("a", | 2068 rv = handle.Init("a", |
2023 params_, | 2069 params_, |
(...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3035 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); | 3081 CreatePool(kDefaultMaxSockets, kDefaultMaxSockets); |
3036 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 3082 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
3037 | 3083 |
3038 ASSERT_FALSE(pool_->HasGroup("a")); | 3084 ASSERT_FALSE(pool_->HasGroup("a")); |
3039 | 3085 |
3040 pool_->RequestSockets("a", ¶ms_, kDefaultMaxSockets - 1, | 3086 pool_->RequestSockets("a", ¶ms_, kDefaultMaxSockets - 1, |
3041 BoundNetLog()); | 3087 BoundNetLog()); |
3042 | 3088 |
3043 ASSERT_TRUE(pool_->HasGroup("a")); | 3089 ASSERT_TRUE(pool_->HasGroup("a")); |
3044 EXPECT_EQ(kDefaultMaxSockets - 1, pool_->NumConnectJobsInGroup("a")); | 3090 EXPECT_EQ(kDefaultMaxSockets - 1, pool_->NumConnectJobsInGroup("a")); |
| 3091 EXPECT_FALSE(pool_->IsStalled()); |
3045 | 3092 |
3046 ASSERT_FALSE(pool_->HasGroup("b")); | 3093 ASSERT_FALSE(pool_->HasGroup("b")); |
3047 | 3094 |
3048 pool_->RequestSockets("b", ¶ms_, kDefaultMaxSockets, | 3095 pool_->RequestSockets("b", ¶ms_, kDefaultMaxSockets, |
3049 BoundNetLog()); | 3096 BoundNetLog()); |
3050 | 3097 |
3051 ASSERT_TRUE(pool_->HasGroup("b")); | 3098 ASSERT_TRUE(pool_->HasGroup("b")); |
3052 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("b")); | 3099 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("b")); |
| 3100 EXPECT_FALSE(pool_->IsStalled()); |
3053 } | 3101 } |
3054 | 3102 |
3055 TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountIdleSockets) { | 3103 TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountIdleSockets) { |
3056 CreatePool(4, 4); | 3104 CreatePool(4, 4); |
3057 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 3105 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
3058 | 3106 |
3059 ClientSocketHandle handle1; | 3107 ClientSocketHandle handle1; |
3060 TestCompletionCallback callback1; | 3108 TestCompletionCallback callback1; |
3061 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", | 3109 EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a", |
3062 params_, | 3110 params_, |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3364 // The hung connect job should still be there, but everything else should be | 3412 // The hung connect job should still be there, but everything else should be |
3365 // complete. | 3413 // complete. |
3366 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); | 3414 EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a")); |
3367 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); | 3415 EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); |
3368 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); | 3416 EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); |
3369 } | 3417 } |
3370 | 3418 |
3371 } // namespace | 3419 } // namespace |
3372 | 3420 |
3373 } // namespace net | 3421 } // namespace net |
OLD | NEW |