Chromium Code Reviews| 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 "net/base/host_resolver_unittest.h" | 9 #include "net/base/host_resolver_unittest.h" |
| 10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 // Note that the first and the last are the same, the first should be handled | 23 // Note that the first and the last are the same, the first should be handled |
| 24 // before the last, since it was inserted first. | 24 // before the last, since it was inserted first. |
| 25 const int kPriorities[] = { 1, 3, 4, 2, 1 }; | 25 const int kPriorities[] = { 1, 3, 4, 2, 1 }; |
| 26 | 26 |
| 27 // This is the number of extra requests beyond the first few that use up all | 27 // This is the number of extra requests beyond the first few that use up all |
| 28 // available sockets in the socket group. | 28 // available sockets in the socket group. |
| 29 const int kNumPendingRequests = arraysize(kPriorities); | 29 const int kNumPendingRequests = arraysize(kPriorities); |
| 30 | 30 |
| 31 const int kNumRequests = kMaxSocketsPerGroup + kNumPendingRequests; | 31 const int kNumRequests = kMaxSocketsPerGroup + kNumPendingRequests; |
| 32 | 32 |
| 33 const int kDefaultPriority = 5; | |
| 34 | |
| 33 class MockClientSocket : public ClientSocket { | 35 class MockClientSocket : public ClientSocket { |
| 34 public: | 36 public: |
| 35 MockClientSocket() : connected_(false) {} | 37 MockClientSocket() : connected_(false) {} |
| 36 | 38 |
| 37 // Socket methods: | 39 // Socket methods: |
| 38 virtual int Read( | 40 virtual int Read( |
| 39 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) { | 41 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) { |
| 40 return ERR_UNEXPECTED; | 42 return ERR_UNEXPECTED; |
| 41 } | 43 } |
| 42 | 44 |
| 43 virtual int Write( | 45 virtual int Write( |
| 44 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) { | 46 IOBuffer* /* buf */, int /* len */, CompletionCallback* /* callback */) { |
| 45 return ERR_UNEXPECTED; | 47 return ERR_UNEXPECTED; |
| 46 } | 48 } |
| 47 | 49 |
| 48 // ClientSocket methods: | 50 // ClientSocket methods: |
| 49 | 51 |
| 50 virtual int Connect(CompletionCallback* callback) { | 52 virtual int Connect(CompletionCallback* callback) { |
| 51 connected_ = true; | 53 connected_ = true; |
| 52 return OK; | 54 return OK; |
| 53 } | 55 } |
| 54 | 56 |
| 55 virtual void Disconnect() { connected_ = false; } | 57 virtual void Disconnect() { connected_ = false; } |
| 56 virtual bool IsConnected() const { return connected_; } | 58 virtual bool IsConnected() const { return connected_; } |
| 57 virtual bool IsConnectedAndIdle() const { return connected_; } | 59 virtual bool IsConnectedAndIdle() const { return connected_; } |
| 58 | 60 |
| 59 #if defined(OS_LINUX) | 61 #if defined(OS_LINUX) |
| 60 virtual int GetPeerName(struct sockaddr* /* name */, | 62 virtual int GetPeerName(struct sockaddr* /* name */, |
| 61 socklen_t* /* namelen */) { | 63 socklen_t* /* namelen */) { |
| 62 return 0; | 64 return 0; |
| 63 } | 65 } |
| 64 #endif | 66 #endif |
| 65 | 67 |
| 66 private: | 68 private: |
| 67 bool connected_; | 69 bool connected_; |
| 68 | 70 |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 285 virtual void SetUp() { | 287 virtual void SetUp() { |
| 286 TestSocketRequest::completion_count = 0; | 288 TestSocketRequest::completion_count = 0; |
| 287 } | 289 } |
| 288 | 290 |
| 289 virtual void TearDown() { | 291 virtual void TearDown() { |
| 290 // The tests often call Reset() on handles at the end which may post | 292 // The tests often call Reset() on handles at the end which may post |
| 291 // DoReleaseSocket() tasks. | 293 // DoReleaseSocket() tasks. |
| 292 MessageLoop::current()->RunAllPending(); | 294 MessageLoop::current()->RunAllPending(); |
| 293 } | 295 } |
| 294 | 296 |
| 297 void CreateConnections(scoped_ptr<TestSocketRequest>* reqs, size_t count) { | |
|
willchan no longer on Chromium
2009/07/06 17:11:03
It strikes me as odd that you have |count| as a va
| |
| 298 for (size_t i = 0; i < count; ++i) | |
| 299 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | |
| 300 | |
| 301 // Create connections or queue up requests. | |
| 302 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | |
| 303 int rv = reqs[i]->handle.Init("a", ignored_request_info_, | |
| 304 kDefaultPriority, reqs[i].get()); | |
| 305 EXPECT_EQ(OK, rv); | |
| 306 request_order_.push_back(reqs[i].get()); | |
| 307 } | |
| 308 | |
| 309 // The rest are pending since we've used all active sockets. | |
| 310 for (int i = 0; i < kNumPendingRequests; ++i) { | |
| 311 int rv = reqs[kMaxSocketsPerGroup + i]->handle.Init( | |
| 312 "a", ignored_request_info_, kPriorities[i], | |
| 313 reqs[kMaxSocketsPerGroup + i].get()); | |
| 314 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 315 } | |
| 316 } | |
| 317 | |
| 318 enum KeepAlive { | |
| 319 KEEP_ALIVE, | |
| 320 NO_KEEP_ALIVE, | |
| 321 }; | |
| 322 | |
| 323 void ReleaseAllConnections(scoped_ptr<TestSocketRequest>* reqs, | |
| 324 size_t count, KeepAlive keep_alive) { | |
| 325 bool released_one; | |
| 326 do { | |
| 327 released_one = false; | |
| 328 for (size_t i = 0; i < count; ++i) { | |
| 329 if (reqs[i]->handle.is_initialized()) { | |
| 330 if (keep_alive == NO_KEEP_ALIVE) | |
| 331 reqs[i]->handle.socket()->Disconnect(); | |
| 332 reqs[i]->handle.Reset(); | |
| 333 MessageLoop::current()->RunAllPending(); | |
| 334 released_one = true; | |
| 335 } | |
| 336 } | |
| 337 } while (released_one); | |
| 338 } | |
| 339 | |
| 295 HostResolver::RequestInfo ignored_request_info_; | 340 HostResolver::RequestInfo ignored_request_info_; |
| 296 MockClientSocketFactory client_socket_factory_; | 341 MockClientSocketFactory client_socket_factory_; |
| 297 TestConnectJobFactory* const connect_job_factory_; | 342 TestConnectJobFactory* const connect_job_factory_; |
| 298 scoped_refptr<ClientSocketPool> pool_; | 343 scoped_refptr<ClientSocketPool> pool_; |
| 299 std::vector<TestSocketRequest*> request_order_; | 344 std::vector<TestSocketRequest*> request_order_; |
| 300 }; | 345 }; |
| 301 | 346 |
| 302 TEST_F(ClientSocketPoolBaseTest, Basic) { | 347 TEST_F(ClientSocketPoolBaseTest, Basic) { |
| 303 TestCompletionCallback callback; | 348 TestCompletionCallback callback; |
| 304 ClientSocketHandle handle(pool_.get()); | 349 ClientSocketHandle handle(pool_.get()); |
| 305 int rv = handle.Init("a", ignored_request_info_, 0, &callback); | 350 EXPECT_EQ(OK, handle.Init("a", ignored_request_info_, kDefaultPriority, |
| 306 EXPECT_EQ(OK, rv); | 351 &callback)); |
| 307 EXPECT_TRUE(handle.is_initialized()); | 352 EXPECT_TRUE(handle.is_initialized()); |
| 308 EXPECT_TRUE(handle.socket()); | 353 EXPECT_TRUE(handle.socket()); |
| 309 handle.Reset(); | 354 handle.Reset(); |
| 310 } | 355 } |
| 311 | 356 |
| 312 TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) { | 357 TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) { |
| 313 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob); | 358 connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob); |
| 314 TestSocketRequest req(pool_.get(), &request_order_); | 359 TestSocketRequest req(pool_.get(), &request_order_); |
| 315 EXPECT_EQ(ERR_CONNECTION_FAILED, | 360 EXPECT_EQ(ERR_CONNECTION_FAILED, |
| 316 req.handle.Init("a", ignored_request_info_, 5, &req)); | 361 req.handle.Init("a", ignored_request_info_, |
| 362 kDefaultPriority, &req)); | |
| 317 } | 363 } |
| 318 | 364 |
| 319 TEST_F(ClientSocketPoolBaseTest, PendingRequests) { | 365 TEST_F(ClientSocketPoolBaseTest, PendingRequests) { |
| 320 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 366 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
| 321 | 367 |
| 322 for (size_t i = 0; i < arraysize(reqs); ++i) | 368 CreateConnections(reqs, arraysize(reqs)); |
| 323 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | 369 ReleaseAllConnections(reqs, arraysize(reqs), KEEP_ALIVE); |
| 324 | |
| 325 // Create connections or queue up requests. | |
| 326 | |
| 327 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | |
| 328 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); | |
| 329 EXPECT_EQ(OK, rv); | |
| 330 request_order_.push_back(reqs[i].get()); | |
| 331 } | |
| 332 | |
| 333 // The rest are pending since we've used all active sockets. | |
| 334 for (int i = 0; i < kNumPendingRequests; ++i) { | |
| 335 int rv = reqs[kMaxSocketsPerGroup + i]->handle.Init( | |
| 336 "a", ignored_request_info_, kPriorities[i], | |
| 337 reqs[kMaxSocketsPerGroup + i].get()); | |
| 338 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 339 } | |
| 340 | |
| 341 // Release any connections until we have no connections. | |
| 342 bool released_one; | |
| 343 do { | |
| 344 released_one = false; | |
| 345 for (size_t i = 0; i < arraysize(reqs); ++i) { | |
| 346 if (reqs[i]->handle.is_initialized()) { | |
| 347 reqs[i]->handle.Reset(); | |
| 348 MessageLoop::current()->RunAllPending(); | |
| 349 released_one = true; | |
| 350 } | |
| 351 } | |
| 352 } while (released_one); | |
| 353 | 370 |
| 354 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); | 371 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); |
| 355 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); | 372 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); |
| 356 | 373 |
| 357 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | 374 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { |
| 358 EXPECT_EQ(request_order_[i], reqs[i].get()) << | 375 EXPECT_EQ(request_order_[i], reqs[i].get()) << |
| 359 "Request " << i << " was not in order."; | 376 "Request " << i << " was not in order."; |
| 360 } | 377 } |
| 361 | 378 |
| 362 for (int i = 0; i < kNumPendingRequests - 1; ++i) { | 379 for (int i = 0; i < kNumPendingRequests - 1; ++i) { |
| 363 int index_in_queue = (kNumPendingRequests - 1) - kPriorities[i]; | 380 int index_in_queue = (kNumPendingRequests - 1) - kPriorities[i]; |
| 364 EXPECT_EQ(request_order_[kMaxSocketsPerGroup + index_in_queue], | 381 EXPECT_EQ(request_order_[kMaxSocketsPerGroup + index_in_queue], |
| 365 reqs[kMaxSocketsPerGroup + i].get()) << | 382 reqs[kMaxSocketsPerGroup + i].get()) << |
| 366 "Request " << kMaxSocketsPerGroup + i << " was not in order."; | 383 "Request " << kMaxSocketsPerGroup + i << " was not in order."; |
| 367 } | 384 } |
| 368 | 385 |
| 369 EXPECT_EQ(request_order_[arraysize(reqs) - 1], | 386 EXPECT_EQ(request_order_[arraysize(reqs) - 1], |
| 370 reqs[arraysize(reqs) - 1].get()) << | 387 reqs[arraysize(reqs) - 1].get()) << |
| 371 "The last request with priority 1 should not have been inserted " | 388 "The last request with priority 1 should not have been inserted " |
| 372 "earlier into the queue."; | 389 "earlier into the queue."; |
| 373 } | 390 } |
| 374 | 391 |
| 375 TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) { | 392 TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) { |
| 376 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 393 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
| 377 for (size_t i = 0; i < arraysize(reqs); ++i) | |
| 378 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | |
| 379 | 394 |
| 380 // Create connections or queue up requests. | 395 CreateConnections(reqs, arraysize(reqs)); |
| 381 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | 396 ReleaseAllConnections(reqs, arraysize(reqs), NO_KEEP_ALIVE); |
| 382 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); | |
| 383 EXPECT_EQ(OK, rv); | |
| 384 request_order_.push_back(reqs[i].get()); | |
| 385 } | |
| 386 | |
| 387 // The rest are pending since we've used all active sockets. | |
| 388 for (int i = 0; i < kNumPendingRequests; ++i) { | |
| 389 int rv = reqs[kMaxSocketsPerGroup + i]->handle.Init( | |
| 390 "a", ignored_request_info_, kPriorities[i], | |
| 391 reqs[kMaxSocketsPerGroup + i].get()); | |
| 392 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 393 } | |
| 394 | |
| 395 // Release any connections until we have no connections. | |
| 396 bool released_one; | |
| 397 do { | |
| 398 released_one = false; | |
| 399 for (size_t i = 0; i < arraysize(reqs); ++i) { | |
| 400 if (reqs[i]->handle.is_initialized()) { | |
| 401 reqs[i]->handle.socket()->Disconnect(); // No keep alive. | |
| 402 reqs[i]->handle.Reset(); | |
| 403 MessageLoop::current()->RunAllPending(); | |
| 404 released_one = true; | |
| 405 } | |
| 406 } | |
| 407 } while (released_one); | |
| 408 | 397 |
| 409 for (int i = kMaxSocketsPerGroup; i < kNumRequests; ++i) | 398 for (int i = kMaxSocketsPerGroup; i < kNumRequests; ++i) |
| 410 EXPECT_EQ(OK, reqs[i]->WaitForResult()); | 399 EXPECT_EQ(OK, reqs[i]->WaitForResult()); |
| 411 | 400 |
| 412 EXPECT_EQ(kNumRequests, client_socket_factory_.allocation_count()); | 401 EXPECT_EQ(kNumRequests, client_socket_factory_.allocation_count()); |
| 413 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); | 402 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); |
| 414 } | 403 } |
| 415 | 404 |
| 416 // This test will start up a RequestSocket() and then immediately Cancel() it. | 405 // This test will start up a RequestSocket() and then immediately Cancel() it. |
| 417 // The pending connect job will be cancelled and should not call back into | 406 // The pending connect job will be cancelled and should not call back into |
| 418 // ClientSocketPoolBase. | 407 // ClientSocketPoolBase. |
| 419 TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) { | 408 TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) { |
| 420 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 409 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 421 TestSocketRequest req(pool_.get(), &request_order_); | 410 TestSocketRequest req(pool_.get(), &request_order_); |
| 422 EXPECT_EQ(ERR_IO_PENDING, | 411 EXPECT_EQ(ERR_IO_PENDING, |
| 423 req.handle.Init("a", ignored_request_info_, 5, &req)); | 412 req.handle.Init("a", ignored_request_info_, |
| 413 kDefaultPriority, &req)); | |
| 424 req.handle.Reset(); | 414 req.handle.Reset(); |
| 425 } | 415 } |
| 426 | 416 |
| 427 TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) { | 417 TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) { |
| 428 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 418 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 429 TestSocketRequest req(pool_.get(), &request_order_); | 419 TestSocketRequest req(pool_.get(), &request_order_); |
| 430 TestSocketRequest req2(pool_.get(), &request_order_); | 420 TestSocketRequest req2(pool_.get(), &request_order_); |
| 431 | 421 |
| 432 EXPECT_EQ(ERR_IO_PENDING, | 422 EXPECT_EQ(ERR_IO_PENDING, |
| 433 req.handle.Init("a", ignored_request_info_, 5, &req)); | 423 req.handle.Init("a", ignored_request_info_, |
| 424 kDefaultPriority, &req)); | |
| 434 EXPECT_EQ(ERR_IO_PENDING, | 425 EXPECT_EQ(ERR_IO_PENDING, |
| 435 req2.handle.Init("a", ignored_request_info_, 5, &req2)); | 426 req2.handle.Init("a", ignored_request_info_, |
| 427 kDefaultPriority, &req2)); | |
| 436 | 428 |
| 437 req.handle.Reset(); | 429 req.handle.Reset(); |
| 438 | 430 |
| 439 EXPECT_EQ(OK, req2.WaitForResult()); | 431 EXPECT_EQ(OK, req2.WaitForResult()); |
| 440 req2.handle.Reset(); | 432 req2.handle.Reset(); |
| 441 } | 433 } |
| 442 | 434 |
| 443 TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) { | 435 TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) { |
| 444 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 436 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 445 ClientSocketHandle handle(pool_.get()); | 437 ClientSocketHandle handle(pool_.get()); |
| 446 TestCompletionCallback callback; | 438 TestCompletionCallback callback; |
| 447 TestSocketRequest req(pool_.get(), &request_order_); | 439 TestSocketRequest req(pool_.get(), &request_order_); |
| 448 | 440 |
| 449 EXPECT_EQ(ERR_IO_PENDING, | 441 EXPECT_EQ(ERR_IO_PENDING, |
| 450 handle.Init("a", ignored_request_info_, 5, &callback)); | 442 handle.Init("a", ignored_request_info_, |
| 443 kDefaultPriority, &callback)); | |
| 451 | 444 |
| 452 handle.Reset(); | 445 handle.Reset(); |
| 453 | 446 |
| 454 TestCompletionCallback callback2; | 447 TestCompletionCallback callback2; |
| 455 EXPECT_EQ(ERR_IO_PENDING, | 448 EXPECT_EQ(ERR_IO_PENDING, |
| 456 handle.Init("a", ignored_request_info_, 5, &callback2)); | 449 handle.Init("a", ignored_request_info_, |
| 450 kDefaultPriority, &callback2)); | |
| 457 | 451 |
| 458 EXPECT_EQ(OK, callback2.WaitForResult()); | 452 EXPECT_EQ(OK, callback2.WaitForResult()); |
| 459 EXPECT_FALSE(callback.have_result()); | 453 EXPECT_FALSE(callback.have_result()); |
| 460 | 454 |
| 461 handle.Reset(); | 455 handle.Reset(); |
| 462 } | 456 } |
| 463 | 457 |
| 464 TEST_F(ClientSocketPoolBaseTest, CancelRequest) { | 458 TEST_F(ClientSocketPoolBaseTest, CancelRequest) { |
| 465 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 459 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
| 466 | 460 |
| 467 for (size_t i = 0; i < arraysize(reqs); ++i) | 461 CreateConnections(reqs, arraysize(reqs)); |
| 468 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | |
| 469 | |
| 470 // Create connections or queue up requests. | |
| 471 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | |
| 472 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); | |
| 473 EXPECT_EQ(OK, rv); | |
| 474 request_order_.push_back(reqs[i].get()); | |
| 475 } | |
| 476 | |
| 477 // The rest are pending since we've used all active sockets. | |
| 478 for (int i = 0; i < kNumPendingRequests; ++i) { | |
| 479 EXPECT_EQ(ERR_IO_PENDING, reqs[kMaxSocketsPerGroup + i]->handle.Init( | |
| 480 "a", ignored_request_info_, kPriorities[i], | |
| 481 reqs[kMaxSocketsPerGroup + i].get())); | |
| 482 } | |
| 483 | 462 |
| 484 // Cancel a request. | 463 // Cancel a request. |
| 485 size_t index_to_cancel = kMaxSocketsPerGroup + 2; | 464 size_t index_to_cancel = kMaxSocketsPerGroup + 2; |
| 486 EXPECT_TRUE(!reqs[index_to_cancel]->handle.is_initialized()); | 465 EXPECT_TRUE(!reqs[index_to_cancel]->handle.is_initialized()); |
| 487 reqs[index_to_cancel]->handle.Reset(); | 466 reqs[index_to_cancel]->handle.Reset(); |
| 488 | 467 |
| 489 // Release any connections until we have no connections. | 468 ReleaseAllConnections(reqs, arraysize(reqs), KEEP_ALIVE); |
| 490 bool released_one; | |
| 491 do { | |
| 492 released_one = false; | |
| 493 for (size_t i = 0; i < arraysize(reqs); ++i) { | |
| 494 if (reqs[i]->handle.is_initialized()) { | |
| 495 reqs[i]->handle.Reset(); | |
| 496 MessageLoop::current()->RunAllPending(); | |
| 497 released_one = true; | |
| 498 } | |
| 499 } | |
| 500 } while (released_one); | |
| 501 | 469 |
| 502 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); | 470 EXPECT_EQ(kMaxSocketsPerGroup, client_socket_factory_.allocation_count()); |
| 503 EXPECT_EQ(kNumPendingRequests - 1, TestSocketRequest::completion_count); | 471 EXPECT_EQ(kNumPendingRequests - 1, TestSocketRequest::completion_count); |
| 504 | 472 |
| 505 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { | 473 for (int i = 0; i < kMaxSocketsPerGroup; ++i) { |
| 506 EXPECT_EQ(request_order_[i], reqs[i].get()) << | 474 EXPECT_EQ(request_order_[i], reqs[i].get()) << |
| 507 "Request " << i << " was not in order."; | 475 "Request " << i << " was not in order."; |
| 508 } | 476 } |
| 509 | 477 |
| 510 for (int i = 0; i < kNumPendingRequests - 1; ++i) { | 478 for (int i = 0; i < kNumPendingRequests - 1; ++i) { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 535 | 503 |
| 536 virtual void RunWithParams(const Tuple1<int>& params) { | 504 virtual void RunWithParams(const Tuple1<int>& params) { |
| 537 callback_.RunWithParams(params); | 505 callback_.RunWithParams(params); |
| 538 ASSERT_EQ(OK, params.a); | 506 ASSERT_EQ(OK, params.a); |
| 539 | 507 |
| 540 if (!within_callback_) { | 508 if (!within_callback_) { |
| 541 test_connect_job_factory_->set_job_type(next_job_type_); | 509 test_connect_job_factory_->set_job_type(next_job_type_); |
| 542 handle_->Reset(); | 510 handle_->Reset(); |
| 543 within_callback_ = true; | 511 within_callback_ = true; |
| 544 int rv = handle_->Init( | 512 int rv = handle_->Init( |
| 545 "a", HostResolver::RequestInfo("www.google.com", 80), 0, this); | 513 "a", HostResolver::RequestInfo("www.google.com", 80), |
| 514 kDefaultPriority, this); | |
| 546 switch (next_job_type_) { | 515 switch (next_job_type_) { |
| 547 case TestConnectJob::kMockJob: | 516 case TestConnectJob::kMockJob: |
| 548 EXPECT_EQ(OK, rv); | 517 EXPECT_EQ(OK, rv); |
| 549 break; | 518 break; |
| 550 case TestConnectJob::kMockPendingJob: | 519 case TestConnectJob::kMockPendingJob: |
| 551 EXPECT_EQ(ERR_IO_PENDING, rv); | 520 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 552 break; | 521 break; |
| 553 default: | 522 default: |
| 554 FAIL() << "Unexpected job type: " << next_job_type_; | 523 FAIL() << "Unexpected job type: " << next_job_type_; |
| 555 break; | 524 break; |
| 556 } | 525 } |
| 557 } | 526 } |
| 558 } | 527 } |
| 559 | 528 |
| 560 int WaitForResult() { | 529 int WaitForResult() { |
| 561 return callback_.WaitForResult(); | 530 return callback_.WaitForResult(); |
| 562 } | 531 } |
| 563 | 532 |
| 564 private: | 533 private: |
| 565 ClientSocketHandle* const handle_; | 534 ClientSocketHandle* const handle_; |
| 566 bool within_callback_; | 535 bool within_callback_; |
| 567 TestConnectJobFactory* const test_connect_job_factory_; | 536 TestConnectJobFactory* const test_connect_job_factory_; |
| 568 TestConnectJob::JobType next_job_type_; | 537 TestConnectJob::JobType next_job_type_; |
| 569 TestCompletionCallback callback_; | 538 TestCompletionCallback callback_; |
| 570 }; | 539 }; |
| 571 | 540 |
| 572 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { | 541 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { |
| 573 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 542 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 574 ClientSocketHandle handle(pool_.get()); | 543 ClientSocketHandle handle(pool_.get()); |
| 575 RequestSocketCallback callback( | 544 RequestSocketCallback callback( |
| 576 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob); | 545 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob); |
| 577 int rv = handle.Init( | 546 int rv = handle.Init( |
| 578 "a", ignored_request_info_, 0, &callback); | 547 "a", ignored_request_info_, kDefaultPriority, &callback); |
| 579 ASSERT_EQ(ERR_IO_PENDING, rv); | 548 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 580 | 549 |
| 581 EXPECT_EQ(OK, callback.WaitForResult()); | 550 EXPECT_EQ(OK, callback.WaitForResult()); |
| 582 handle.Reset(); | 551 handle.Reset(); |
| 583 } | 552 } |
| 584 | 553 |
| 585 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { | 554 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { |
| 586 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 555 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 587 ClientSocketHandle handle(pool_.get()); | 556 ClientSocketHandle handle(pool_.get()); |
| 588 RequestSocketCallback callback( | 557 RequestSocketCallback callback( |
| 589 &handle, connect_job_factory_, TestConnectJob::kMockJob); | 558 &handle, connect_job_factory_, TestConnectJob::kMockJob); |
| 590 int rv = handle.Init( | 559 int rv = handle.Init( |
| 591 "a", ignored_request_info_, 0, &callback); | 560 "a", ignored_request_info_, kDefaultPriority, &callback); |
| 592 ASSERT_EQ(ERR_IO_PENDING, rv); | 561 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 593 | 562 |
| 594 EXPECT_EQ(OK, callback.WaitForResult()); | 563 EXPECT_EQ(OK, callback.WaitForResult()); |
| 595 handle.Reset(); | 564 handle.Reset(); |
| 596 } | 565 } |
| 597 | 566 |
| 598 // Make sure that pending requests get serviced after active requests get | 567 // Make sure that pending requests get serviced after active requests get |
| 599 // cancelled. | 568 // cancelled. |
| 600 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) { | 569 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) { |
| 601 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 570 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 602 | 571 |
| 603 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 572 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
| 604 | 573 |
| 605 // Queue up all the requests | 574 // Queue up all the requests |
| 606 for (size_t i = 0; i < arraysize(reqs); ++i) { | 575 for (size_t i = 0; i < arraysize(reqs); ++i) { |
| 607 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | 576 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); |
| 608 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); | 577 int rv = reqs[i]->handle.Init("a", ignored_request_info_, |
| 578 kDefaultPriority, reqs[i].get()); | |
| 609 EXPECT_EQ(ERR_IO_PENDING, rv); | 579 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 610 } | 580 } |
| 611 | 581 |
| 612 // Now, kMaxSocketsPerGroup requests should be active. Let's cancel them. | 582 // Now, kMaxSocketsPerGroup requests should be active. Let's cancel them. |
| 613 for (int i = 0; i < kMaxSocketsPerGroup; ++i) | 583 for (int i = 0; i < kMaxSocketsPerGroup; ++i) |
| 614 reqs[i]->handle.Reset(); | 584 reqs[i]->handle.Reset(); |
| 615 | 585 |
| 616 // Let's wait for the rest to complete now. | 586 // Let's wait for the rest to complete now. |
| 617 | |
| 618 for (size_t i = kMaxSocketsPerGroup; i < arraysize(reqs); ++i) { | 587 for (size_t i = kMaxSocketsPerGroup; i < arraysize(reqs); ++i) { |
| 619 EXPECT_EQ(OK, reqs[i]->WaitForResult()); | 588 EXPECT_EQ(OK, reqs[i]->WaitForResult()); |
| 620 reqs[i]->handle.Reset(); | 589 reqs[i]->handle.Reset(); |
| 621 } | 590 } |
| 622 | 591 |
| 623 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); | 592 EXPECT_EQ(kNumPendingRequests, TestSocketRequest::completion_count); |
| 624 } | 593 } |
| 625 | 594 |
| 626 // Make sure that pending requests get serviced after active requests fail. | 595 // Make sure that pending requests get serviced after active requests fail. |
| 627 TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) { | 596 TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) { |
| 628 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); | 597 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); |
| 629 | 598 |
| 630 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup * 2 + 1]; | 599 scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup * 2 + 1]; |
| 631 | 600 |
| 632 // Queue up all the requests | 601 // Queue up all the requests |
| 633 for (size_t i = 0; i < arraysize(reqs); ++i) { | 602 for (size_t i = 0; i < arraysize(reqs); ++i) { |
| 634 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | 603 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); |
| 635 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); | 604 int rv = reqs[i]->handle.Init("a", ignored_request_info_, |
| 605 kDefaultPriority, reqs[i].get()); | |
| 636 EXPECT_EQ(ERR_IO_PENDING, rv); | 606 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 637 } | 607 } |
| 638 | 608 |
| 639 for (size_t i = 0; i < arraysize(reqs); ++i) | 609 for (size_t i = 0; i < arraysize(reqs); ++i) |
| 640 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult()); | 610 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult()); |
| 641 } | 611 } |
| 642 | 612 |
| 643 // A pending asynchronous job completes, which will free up a socket slot. The | 613 // A pending asynchronous job completes, which will free up a socket slot. The |
| 644 // next job finishes synchronously. The callback for the asynchronous job | 614 // next job finishes synchronously. The callback for the asynchronous job |
| 645 // should be first though. | 615 // should be first though. |
| 646 TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) { | 616 TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) { |
| 647 // First two jobs are async. | 617 // First two jobs are async. |
| 648 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); | 618 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); |
| 649 | 619 |
| 650 // Start job 1 (async error). | 620 // Start job 1 (async error). |
| 651 TestSocketRequest req1(pool_.get(), &request_order_); | 621 TestSocketRequest req1(pool_.get(), &request_order_); |
| 652 int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1); | 622 int rv = req1.handle.Init("a", ignored_request_info_, |
| 623 kDefaultPriority, &req1); | |
| 653 EXPECT_EQ(ERR_IO_PENDING, rv); | 624 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 654 | 625 |
| 655 // Start job 2 (async error). | 626 // Start job 2 (async error). |
| 656 TestSocketRequest req2(pool_.get(), &request_order_); | 627 TestSocketRequest req2(pool_.get(), &request_order_); |
| 657 rv = req2.handle.Init("a", ignored_request_info_, 5, &req2); | 628 rv = req2.handle.Init("a", ignored_request_info_, kDefaultPriority, &req2); |
| 658 EXPECT_EQ(ERR_IO_PENDING, rv); | 629 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 659 | 630 |
| 660 // The pending job is sync. | 631 // The pending job is sync. |
| 661 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); | 632 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
| 662 | 633 |
| 663 // Request 3 does not have a ConnectJob yet. It's just pending. | 634 // Request 3 does not have a ConnectJob yet. It's just pending. |
| 664 TestSocketRequest req3(pool_.get(), &request_order_); | 635 TestSocketRequest req3(pool_.get(), &request_order_); |
| 665 rv = req3.handle.Init("a", ignored_request_info_, 5, &req3); | 636 rv = req3.handle.Init("a", ignored_request_info_, kDefaultPriority, &req3); |
| 666 EXPECT_EQ(ERR_IO_PENDING, rv); | 637 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 667 | 638 |
| 668 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult()); | 639 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult()); |
| 669 EXPECT_EQ(ERR_CONNECTION_FAILED, req2.WaitForResult()); | 640 EXPECT_EQ(ERR_CONNECTION_FAILED, req2.WaitForResult()); |
| 670 EXPECT_EQ(OK, req3.WaitForResult()); | 641 EXPECT_EQ(OK, req3.WaitForResult()); |
| 671 | 642 |
| 672 ASSERT_EQ(3U, request_order_.size()); | 643 ASSERT_EQ(3U, request_order_.size()); |
| 673 | 644 |
| 674 // After job 1 finishes unsuccessfully, it will try to process the pending | 645 // After job 1 finishes unsuccessfully, it will try to process the pending |
| 675 // requests queue, so it starts up job 3 for request 3. This job | 646 // requests queue, so it starts up job 3 for request 3. This job |
| 676 // synchronously succeeds, so the request order is 1, 3, 2. | 647 // synchronously succeeds, so the request order is 1, 3, 2. |
| 677 EXPECT_EQ(&req1, request_order_[0]); | 648 EXPECT_EQ(&req1, request_order_[0]); |
| 678 EXPECT_EQ(&req2, request_order_[2]); | 649 EXPECT_EQ(&req2, request_order_[2]); |
| 679 EXPECT_EQ(&req3, request_order_[1]); | 650 EXPECT_EQ(&req3, request_order_[1]); |
| 680 } | 651 } |
| 681 | 652 |
| 682 } // namespace | 653 } // namespace |
| 683 | 654 |
| 684 } // namespace net | 655 } // namespace net |
| OLD | NEW |