| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/tcp_client_socket_pool.h" | 5 #include "net/socket/tcp_client_socket_pool.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/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "net/base/mock_host_resolver.h" | 10 #include "net/base/mock_host_resolver.h" |
| 11 #include "net/base/mock_network_change_notifier.h" | 11 #include "net/base/mock_network_change_notifier.h" |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 } | 199 } |
| 200 | 200 |
| 201 private: | 201 private: |
| 202 int allocation_count_; | 202 int allocation_count_; |
| 203 ClientSocketType client_socket_type_; | 203 ClientSocketType client_socket_type_; |
| 204 }; | 204 }; |
| 205 | 205 |
| 206 class TCPClientSocketPoolTest : public ClientSocketPoolTest { | 206 class TCPClientSocketPoolTest : public ClientSocketPoolTest { |
| 207 protected: | 207 protected: |
| 208 TCPClientSocketPoolTest() | 208 TCPClientSocketPoolTest() |
| 209 : ignored_request_info_("ignored", 80), | 209 : ignored_socket_params_("ignored", 80, MEDIUM, GURL(), false), |
| 210 host_resolver_(new MockHostResolver), | 210 host_resolver_(new MockHostResolver), |
| 211 pool_(new TCPClientSocketPool(kMaxSockets, | 211 pool_(new TCPClientSocketPool(kMaxSockets, |
| 212 kMaxSocketsPerGroup, | 212 kMaxSocketsPerGroup, |
| 213 host_resolver_, | 213 host_resolver_, |
| 214 &client_socket_factory_, | 214 &client_socket_factory_, |
| 215 ¬ifier_)) { | 215 ¬ifier_)) { |
| 216 } | 216 } |
| 217 | 217 |
| 218 int StartRequest(const std::string& group_name, RequestPriority priority) { | 218 int StartRequest(const std::string& group_name, RequestPriority priority) { |
| 219 return StartRequestUsingPool( | 219 return StartRequestUsingPool( |
| 220 pool_.get(), group_name, priority, ignored_request_info_); | 220 pool_.get(), group_name, priority, ignored_socket_params_); |
| 221 } | 221 } |
| 222 | 222 |
| 223 HostResolver::RequestInfo ignored_request_info_; | 223 TCPSocketParams ignored_socket_params_; |
| 224 scoped_refptr<MockHostResolver> host_resolver_; | 224 scoped_refptr<MockHostResolver> host_resolver_; |
| 225 MockClientSocketFactory client_socket_factory_; | 225 MockClientSocketFactory client_socket_factory_; |
| 226 MockNetworkChangeNotifier notifier_; | 226 MockNetworkChangeNotifier notifier_; |
| 227 scoped_refptr<TCPClientSocketPool> pool_; | 227 scoped_refptr<TCPClientSocketPool> pool_; |
| 228 }; | 228 }; |
| 229 | 229 |
| 230 TEST_F(TCPClientSocketPoolTest, Basic) { | 230 TEST_F(TCPClientSocketPoolTest, Basic) { |
| 231 TestCompletionCallback callback; | 231 TestCompletionCallback callback; |
| 232 ClientSocketHandle handle; | 232 ClientSocketHandle handle; |
| 233 HostResolver::RequestInfo info("www.google.com", 80); | 233 TCPSocketParams dest("www.google.com", 80, LOW, GURL(), false); |
| 234 int rv = handle.Init("a", info, LOW, &callback, pool_.get(), NULL); | 234 int rv = handle.Init("a", dest, LOW, &callback, pool_.get(), NULL); |
| 235 EXPECT_EQ(ERR_IO_PENDING, rv); | 235 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 236 EXPECT_FALSE(handle.is_initialized()); | 236 EXPECT_FALSE(handle.is_initialized()); |
| 237 EXPECT_FALSE(handle.socket()); | 237 EXPECT_FALSE(handle.socket()); |
| 238 | 238 |
| 239 EXPECT_EQ(OK, callback.WaitForResult()); | 239 EXPECT_EQ(OK, callback.WaitForResult()); |
| 240 EXPECT_TRUE(handle.is_initialized()); | 240 EXPECT_TRUE(handle.is_initialized()); |
| 241 EXPECT_TRUE(handle.socket()); | 241 EXPECT_TRUE(handle.socket()); |
| 242 | 242 |
| 243 handle.Reset(); | 243 handle.Reset(); |
| 244 } | 244 } |
| 245 | 245 |
| 246 TEST_F(TCPClientSocketPoolTest, InitHostResolutionFailure) { | 246 TEST_F(TCPClientSocketPoolTest, InitHostResolutionFailure) { |
| 247 host_resolver_->rules()->AddSimulatedFailure("unresolvable.host.name"); | 247 host_resolver_->rules()->AddSimulatedFailure("unresolvable.host.name"); |
| 248 TestSocketRequest req(&request_order_, &completion_count_); | 248 TestSocketRequest req(&request_order_, &completion_count_); |
| 249 HostResolver::RequestInfo info("unresolvable.host.name", 80); | 249 TCPSocketParams dest("unresolvable.host.name", 80, kDefaultPriority, GURL(), |
| 250 false); |
| 250 EXPECT_EQ(ERR_IO_PENDING, | 251 EXPECT_EQ(ERR_IO_PENDING, |
| 251 req.handle()->Init( | 252 req.handle()->Init( |
| 252 "a", info, kDefaultPriority, &req, pool_.get(), NULL)); | 253 "a", dest, kDefaultPriority, &req, pool_.get(), NULL)); |
| 253 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req.WaitForResult()); | 254 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req.WaitForResult()); |
| 254 } | 255 } |
| 255 | 256 |
| 256 TEST_F(TCPClientSocketPoolTest, InitConnectionFailure) { | 257 TEST_F(TCPClientSocketPoolTest, InitConnectionFailure) { |
| 257 client_socket_factory_.set_client_socket_type( | 258 client_socket_factory_.set_client_socket_type( |
| 258 MockClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET); | 259 MockClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET); |
| 259 TestSocketRequest req(&request_order_, &completion_count_); | 260 TestSocketRequest req(&request_order_, &completion_count_); |
| 260 HostResolver::RequestInfo info("a", 80); | 261 TCPSocketParams dest("a", 80, kDefaultPriority, GURL(), false); |
| 261 EXPECT_EQ(ERR_IO_PENDING, | 262 EXPECT_EQ(ERR_IO_PENDING, |
| 262 req.handle()->Init( | 263 req.handle()->Init( |
| 263 "a", info, kDefaultPriority, &req, pool_.get(), NULL)); | 264 "a", dest, kDefaultPriority, &req, pool_.get(), NULL)); |
| 264 EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult()); | 265 EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult()); |
| 265 | 266 |
| 266 // Make the host resolutions complete synchronously this time. | 267 // Make the host resolutions complete synchronously this time. |
| 267 host_resolver_->set_synchronous_mode(true); | 268 host_resolver_->set_synchronous_mode(true); |
| 268 EXPECT_EQ(ERR_CONNECTION_FAILED, | 269 EXPECT_EQ(ERR_CONNECTION_FAILED, |
| 269 req.handle()->Init( | 270 req.handle()->Init( |
| 270 "a", info, kDefaultPriority, &req, pool_.get(), NULL)); | 271 "a", dest, kDefaultPriority, &req, pool_.get(), NULL)); |
| 271 } | 272 } |
| 272 | 273 |
| 273 TEST_F(TCPClientSocketPoolTest, PendingRequests) { | 274 TEST_F(TCPClientSocketPoolTest, PendingRequests) { |
| 274 // First request finishes asynchronously. | 275 // First request finishes asynchronously. |
| 275 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | 276 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); |
| 276 EXPECT_EQ(OK, requests_[0]->WaitForResult()); | 277 EXPECT_EQ(OK, requests_[0]->WaitForResult()); |
| 277 | 278 |
| 278 // Make all subsequent host resolutions complete synchronously. | 279 // Make all subsequent host resolutions complete synchronously. |
| 279 host_resolver_->set_synchronous_mode(true); | 280 host_resolver_->set_synchronous_mode(true); |
| 280 | 281 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 | 365 |
| 365 // First asynchronous request, and then last 5 pending requests. | 366 // First asynchronous request, and then last 5 pending requests. |
| 366 EXPECT_EQ(6U, completion_count_); | 367 EXPECT_EQ(6U, completion_count_); |
| 367 } | 368 } |
| 368 | 369 |
| 369 // This test will start up a RequestSocket() and then immediately Cancel() it. | 370 // This test will start up a RequestSocket() and then immediately Cancel() it. |
| 370 // The pending host resolution will eventually complete, and destroy the | 371 // The pending host resolution will eventually complete, and destroy the |
| 371 // ClientSocketPool which will crash if the group was not cleared properly. | 372 // ClientSocketPool which will crash if the group was not cleared properly. |
| 372 TEST_F(TCPClientSocketPoolTest, CancelRequestClearGroup) { | 373 TEST_F(TCPClientSocketPoolTest, CancelRequestClearGroup) { |
| 373 TestSocketRequest req(&request_order_, &completion_count_); | 374 TestSocketRequest req(&request_order_, &completion_count_); |
| 374 HostResolver::RequestInfo info("www.google.com", 80); | 375 TCPSocketParams dest("www.google.com", 80, kDefaultPriority, GURL(), false); |
| 375 EXPECT_EQ(ERR_IO_PENDING, | 376 EXPECT_EQ(ERR_IO_PENDING, |
| 376 req.handle()->Init( | 377 req.handle()->Init( |
| 377 "a", info, kDefaultPriority, &req, pool_.get(), NULL)); | 378 "a", dest, kDefaultPriority, &req, pool_.get(), NULL)); |
| 378 req.handle()->Reset(); | 379 req.handle()->Reset(); |
| 379 | 380 |
| 380 // There is a race condition here. If the worker pool doesn't post the task | 381 // There is a race condition here. If the worker pool doesn't post the task |
| 381 // before we get here, then this might not run ConnectingSocket::OnIOComplete | 382 // before we get here, then this might not run ConnectingSocket::OnIOComplete |
| 382 // and therefore leak the canceled ConnectingSocket. However, other tests | 383 // and therefore leak the canceled ConnectingSocket. However, other tests |
| 383 // after this will call MessageLoop::RunAllPending() which should prevent a | 384 // after this will call MessageLoop::RunAllPending() which should prevent a |
| 384 // leak, unless the worker thread takes longer than all of them. | 385 // leak, unless the worker thread takes longer than all of them. |
| 385 PlatformThread::Sleep(10); | 386 PlatformThread::Sleep(10); |
| 386 MessageLoop::current()->RunAllPending(); | 387 MessageLoop::current()->RunAllPending(); |
| 387 } | 388 } |
| 388 | 389 |
| 389 TEST_F(TCPClientSocketPoolTest, TwoRequestsCancelOne) { | 390 TEST_F(TCPClientSocketPoolTest, TwoRequestsCancelOne) { |
| 390 TestSocketRequest req(&request_order_, &completion_count_); | 391 TestSocketRequest req(&request_order_, &completion_count_); |
| 391 TestSocketRequest req2(&request_order_, &completion_count_); | 392 TestSocketRequest req2(&request_order_, &completion_count_); |
| 392 | 393 |
| 393 HostResolver::RequestInfo info("www.google.com", 80); | 394 TCPSocketParams dest("www.google.com", 80, kDefaultPriority, GURL(), false); |
| 394 EXPECT_EQ(ERR_IO_PENDING, | 395 EXPECT_EQ(ERR_IO_PENDING, |
| 395 req.handle()->Init( | 396 req.handle()->Init( |
| 396 "a", info, kDefaultPriority, &req, pool_.get(), NULL)); | 397 "a", dest, kDefaultPriority, &req, pool_.get(), NULL)); |
| 397 EXPECT_EQ(ERR_IO_PENDING, | 398 EXPECT_EQ(ERR_IO_PENDING, |
| 398 req2.handle()->Init( | 399 req2.handle()->Init( |
| 399 "a", info, kDefaultPriority, &req2, pool_.get(), NULL)); | 400 "a", dest, kDefaultPriority, &req2, pool_.get(), NULL)); |
| 400 | 401 |
| 401 req.handle()->Reset(); | 402 req.handle()->Reset(); |
| 402 | 403 |
| 403 EXPECT_EQ(OK, req2.WaitForResult()); | 404 EXPECT_EQ(OK, req2.WaitForResult()); |
| 404 req2.handle()->Reset(); | 405 req2.handle()->Reset(); |
| 405 } | 406 } |
| 406 | 407 |
| 407 TEST_F(TCPClientSocketPoolTest, ConnectCancelConnect) { | 408 TEST_F(TCPClientSocketPoolTest, ConnectCancelConnect) { |
| 408 client_socket_factory_.set_client_socket_type( | 409 client_socket_factory_.set_client_socket_type( |
| 409 MockClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET); | 410 MockClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET); |
| 410 ClientSocketHandle handle; | 411 ClientSocketHandle handle; |
| 411 TestCompletionCallback callback; | 412 TestCompletionCallback callback; |
| 412 TestSocketRequest req(&request_order_, &completion_count_); | 413 TestSocketRequest req(&request_order_, &completion_count_); |
| 413 | 414 |
| 414 HostResolver::RequestInfo info("www.google.com", 80); | 415 TCPSocketParams dest("www.google.com", 80, kDefaultPriority, GURL(), false); |
| 415 EXPECT_EQ(ERR_IO_PENDING, | 416 EXPECT_EQ(ERR_IO_PENDING, |
| 416 handle.Init( | 417 handle.Init( |
| 417 "a", info, kDefaultPriority, &callback, pool_.get(), NULL)); | 418 "a", dest, kDefaultPriority, &callback, pool_.get(), NULL)); |
| 418 | 419 |
| 419 handle.Reset(); | 420 handle.Reset(); |
| 420 | 421 |
| 421 TestCompletionCallback callback2; | 422 TestCompletionCallback callback2; |
| 422 EXPECT_EQ(ERR_IO_PENDING, | 423 EXPECT_EQ(ERR_IO_PENDING, |
| 423 handle.Init( | 424 handle.Init( |
| 424 "a", info, kDefaultPriority, &callback2, pool_.get(), NULL)); | 425 "a", dest, kDefaultPriority, &callback2, pool_.get(), NULL)); |
| 425 | 426 |
| 426 host_resolver_->set_synchronous_mode(true); | 427 host_resolver_->set_synchronous_mode(true); |
| 427 // At this point, handle has two ConnectingSockets out for it. Due to the | 428 // At this point, handle has two ConnectingSockets out for it. Due to the |
| 428 // setting the mock resolver into synchronous mode, the host resolution for | 429 // setting the mock resolver into synchronous mode, the host resolution for |
| 429 // both will return in the same loop of the MessageLoop. The client socket | 430 // both will return in the same loop of the MessageLoop. The client socket |
| 430 // is a pending socket, so the Connect() will asynchronously complete on the | 431 // is a pending socket, so the Connect() will asynchronously complete on the |
| 431 // next loop of the MessageLoop. That means that the first | 432 // next loop of the MessageLoop. That means that the first |
| 432 // ConnectingSocket will enter OnIOComplete, and then the second one will. | 433 // ConnectingSocket will enter OnIOComplete, and then the second one will. |
| 433 // If the first one is not cancelled, it will advance the load state, and | 434 // If the first one is not cancelled, it will advance the load state, and |
| 434 // then the second one will crash. | 435 // then the second one will crash. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 // Don't allow reuse of the socket. Disconnect it and then release it and | 513 // Don't allow reuse of the socket. Disconnect it and then release it and |
| 513 // run through the MessageLoop once to get it completely released. | 514 // run through the MessageLoop once to get it completely released. |
| 514 handle_->socket()->Disconnect(); | 515 handle_->socket()->Disconnect(); |
| 515 handle_->Reset(); | 516 handle_->Reset(); |
| 516 { | 517 { |
| 517 MessageLoop::ScopedNestableTaskAllower nestable( | 518 MessageLoop::ScopedNestableTaskAllower nestable( |
| 518 MessageLoop::current()); | 519 MessageLoop::current()); |
| 519 MessageLoop::current()->RunAllPending(); | 520 MessageLoop::current()->RunAllPending(); |
| 520 } | 521 } |
| 521 within_callback_ = true; | 522 within_callback_ = true; |
| 522 int rv = handle_->Init( | 523 TCPSocketParams dest("www.google.com", 80, LOWEST, GURL(), false); |
| 523 "a", HostResolver::RequestInfo("www.google.com", 80), LOWEST, | 524 int rv = handle_->Init("a", dest, LOWEST, this, pool_.get(), NULL); |
| 524 this, pool_.get(), NULL); | |
| 525 EXPECT_EQ(OK, rv); | 525 EXPECT_EQ(OK, rv); |
| 526 } | 526 } |
| 527 } | 527 } |
| 528 | 528 |
| 529 int WaitForResult() { | 529 int WaitForResult() { |
| 530 return callback_.WaitForResult(); | 530 return callback_.WaitForResult(); |
| 531 } | 531 } |
| 532 | 532 |
| 533 private: | 533 private: |
| 534 ClientSocketHandle* const handle_; | 534 ClientSocketHandle* const handle_; |
| 535 const scoped_refptr<TCPClientSocketPool> pool_; | 535 const scoped_refptr<TCPClientSocketPool> pool_; |
| 536 bool within_callback_; | 536 bool within_callback_; |
| 537 TestCompletionCallback callback_; | 537 TestCompletionCallback callback_; |
| 538 }; | 538 }; |
| 539 | 539 |
| 540 TEST_F(TCPClientSocketPoolTest, RequestTwice) { | 540 TEST_F(TCPClientSocketPoolTest, RequestTwice) { |
| 541 ClientSocketHandle handle; | 541 ClientSocketHandle handle; |
| 542 RequestSocketCallback callback(&handle, pool_.get()); | 542 RequestSocketCallback callback(&handle, pool_.get()); |
| 543 int rv = handle.Init( | 543 TCPSocketParams dest("www.google.com", 80, LOWEST, GURL(), false); |
| 544 "a", HostResolver::RequestInfo("www.google.com", 80), LOWEST, | 544 int rv = handle.Init("a", dest, LOWEST, &callback, pool_.get(), NULL); |
| 545 &callback, pool_.get(), NULL); | |
| 546 ASSERT_EQ(ERR_IO_PENDING, rv); | 545 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 547 | 546 |
| 548 // The callback is going to request "www.google.com". We want it to complete | 547 // The callback is going to request "www.google.com". We want it to complete |
| 549 // synchronously this time. | 548 // synchronously this time. |
| 550 host_resolver_->set_synchronous_mode(true); | 549 host_resolver_->set_synchronous_mode(true); |
| 551 | 550 |
| 552 EXPECT_EQ(OK, callback.WaitForResult()); | 551 EXPECT_EQ(OK, callback.WaitForResult()); |
| 553 | 552 |
| 554 handle.Reset(); | 553 handle.Reset(); |
| 555 } | 554 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 for (int i = 0; i < kNumRequests; i++) | 596 for (int i = 0; i < kNumRequests; i++) |
| 598 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); | 597 EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); |
| 599 | 598 |
| 600 for (int i = 0; i < kNumRequests; i++) | 599 for (int i = 0; i < kNumRequests; i++) |
| 601 EXPECT_EQ(ERR_CONNECTION_FAILED, requests_[i]->WaitForResult()); | 600 EXPECT_EQ(ERR_CONNECTION_FAILED, requests_[i]->WaitForResult()); |
| 602 } | 601 } |
| 603 | 602 |
| 604 TEST_F(TCPClientSocketPoolTest, ResetIdleSocketsOnIPAddressChange) { | 603 TEST_F(TCPClientSocketPoolTest, ResetIdleSocketsOnIPAddressChange) { |
| 605 TestCompletionCallback callback; | 604 TestCompletionCallback callback; |
| 606 ClientSocketHandle handle; | 605 ClientSocketHandle handle; |
| 607 HostResolver::RequestInfo info("www.google.com", 80); | 606 TCPSocketParams dest("www.google.com", 80, LOW, GURL(), false); |
| 608 int rv = handle.Init("a", info, LOW, &callback, pool_.get(), NULL); | 607 int rv = handle.Init("a", dest, LOW, &callback, pool_.get(), NULL); |
| 609 EXPECT_EQ(ERR_IO_PENDING, rv); | 608 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 610 EXPECT_FALSE(handle.is_initialized()); | 609 EXPECT_FALSE(handle.is_initialized()); |
| 611 EXPECT_FALSE(handle.socket()); | 610 EXPECT_FALSE(handle.socket()); |
| 612 | 611 |
| 613 EXPECT_EQ(OK, callback.WaitForResult()); | 612 EXPECT_EQ(OK, callback.WaitForResult()); |
| 614 EXPECT_TRUE(handle.is_initialized()); | 613 EXPECT_TRUE(handle.is_initialized()); |
| 615 EXPECT_TRUE(handle.socket()); | 614 EXPECT_TRUE(handle.socket()); |
| 616 | 615 |
| 617 handle.Reset(); | 616 handle.Reset(); |
| 618 | 617 |
| 619 // Need to run all pending to release the socket back to the pool. | 618 // Need to run all pending to release the socket back to the pool. |
| 620 MessageLoop::current()->RunAllPending(); | 619 MessageLoop::current()->RunAllPending(); |
| 621 | 620 |
| 622 // Now we should have 1 idle socket. | 621 // Now we should have 1 idle socket. |
| 623 EXPECT_EQ(1, pool_->IdleSocketCount()); | 622 EXPECT_EQ(1, pool_->IdleSocketCount()); |
| 624 | 623 |
| 625 // After an IP address change, we should have 0 idle sockets. | 624 // After an IP address change, we should have 0 idle sockets. |
| 626 notifier_.NotifyIPAddressChange(); | 625 notifier_.NotifyIPAddressChange(); |
| 627 EXPECT_EQ(0, pool_->IdleSocketCount()); | 626 EXPECT_EQ(0, pool_->IdleSocketCount()); |
| 628 } | 627 } |
| 629 | 628 |
| 630 } // namespace | 629 } // namespace |
| 631 | 630 |
| 632 } // namespace net | 631 } // namespace net |
| OLD | NEW |