| 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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 kMockFailingJob, | 127 kMockFailingJob, |
| 128 kMockPendingJob, | 128 kMockPendingJob, |
| 129 kMockPendingFailingJob, | 129 kMockPendingFailingJob, |
| 130 }; | 130 }; |
| 131 | 131 |
| 132 TestConnectJob(JobType job_type, | 132 TestConnectJob(JobType job_type, |
| 133 const std::string& group_name, | 133 const std::string& group_name, |
| 134 const ClientSocketPoolBase::Request& request, | 134 const ClientSocketPoolBase::Request& request, |
| 135 ConnectJob::Delegate* delegate, | 135 ConnectJob::Delegate* delegate, |
| 136 ClientSocketFactory* client_socket_factory) | 136 ClientSocketFactory* client_socket_factory) |
| 137 : job_type_(job_type), | 137 : ConnectJob(group_name, request.handle, delegate), |
| 138 group_name_(group_name), | 138 job_type_(job_type), |
| 139 handle_(request.handle), | |
| 140 client_socket_factory_(client_socket_factory), | 139 client_socket_factory_(client_socket_factory), |
| 141 delegate_(delegate), | |
| 142 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} | 140 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} |
| 143 | 141 |
| 144 // ConnectJob methods: | 142 // ConnectJob methods: |
| 145 | 143 |
| 146 virtual int Connect() { | 144 virtual int Connect() { |
| 147 AddressList ignored; | 145 AddressList ignored; |
| 148 client_socket_factory_->CreateTCPClientSocket(ignored); | 146 client_socket_factory_->CreateTCPClientSocket(ignored); |
| 149 switch (job_type_) { | 147 switch (job_type_) { |
| 150 case kMockJob: | 148 case kMockJob: |
| 151 return DoConnect(true /* successful */, false /* sync */); | 149 return DoConnect(true /* successful */, false /* sync */); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 169 return ERR_IO_PENDING; | 167 return ERR_IO_PENDING; |
| 170 default: | 168 default: |
| 171 NOTREACHED(); | 169 NOTREACHED(); |
| 172 return ERR_FAILED; | 170 return ERR_FAILED; |
| 173 } | 171 } |
| 174 } | 172 } |
| 175 | 173 |
| 176 private: | 174 private: |
| 177 int DoConnect(bool succeed, bool was_async) { | 175 int DoConnect(bool succeed, bool was_async) { |
| 178 int result = ERR_CONNECTION_FAILED; | 176 int result = ERR_CONNECTION_FAILED; |
| 179 ClientSocket* socket = NULL; | |
| 180 if (succeed) { | 177 if (succeed) { |
| 181 result = OK; | 178 result = OK; |
| 182 socket = new MockClientSocket(); | 179 set_socket(new MockClientSocket()); |
| 183 socket->Connect(NULL); | 180 socket()->Connect(NULL); |
| 184 } | 181 } |
| 185 delegate_->OnConnectJobComplete( | 182 |
| 186 group_name_, handle_, socket, result, was_async); | 183 if (was_async) |
| 184 delegate()->OnConnectJobComplete(result, this); |
| 187 return result; | 185 return result; |
| 188 } | 186 } |
| 189 | 187 |
| 190 const JobType job_type_; | 188 const JobType job_type_; |
| 191 const std::string group_name_; | |
| 192 const ClientSocketHandle* handle_; | |
| 193 ClientSocketFactory* const client_socket_factory_; | 189 ClientSocketFactory* const client_socket_factory_; |
| 194 Delegate* const delegate_; | |
| 195 ScopedRunnableMethodFactory<TestConnectJob> method_factory_; | 190 ScopedRunnableMethodFactory<TestConnectJob> method_factory_; |
| 196 | 191 |
| 197 DISALLOW_COPY_AND_ASSIGN(TestConnectJob); | 192 DISALLOW_COPY_AND_ASSIGN(TestConnectJob); |
| 198 }; | 193 }; |
| 199 | 194 |
| 200 class TestConnectJobFactory : public ClientSocketPoolBase::ConnectJobFactory { | 195 class TestConnectJobFactory : public ClientSocketPoolBase::ConnectJobFactory { |
| 201 public: | 196 public: |
| 202 explicit TestConnectJobFactory(ClientSocketFactory* client_socket_factory) | 197 explicit TestConnectJobFactory(ClientSocketFactory* client_socket_factory) |
| 203 : job_type_(TestConnectJob::kMockJob), | 198 : job_type_(TestConnectJob::kMockJob), |
| 204 client_socket_factory_(client_socket_factory) {} | 199 client_socket_factory_(client_socket_factory) {} |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 } | 518 } |
| 524 | 519 |
| 525 EXPECT_EQ(request_order_[arraysize(reqs) - 2], | 520 EXPECT_EQ(request_order_[arraysize(reqs) - 2], |
| 526 reqs[arraysize(reqs) - 1].get()) << | 521 reqs[arraysize(reqs) - 1].get()) << |
| 527 "The last request with priority 1 should not have been inserted " | 522 "The last request with priority 1 should not have been inserted " |
| 528 "earlier into the queue."; | 523 "earlier into the queue."; |
| 529 } | 524 } |
| 530 | 525 |
| 531 class RequestSocketCallback : public CallbackRunner< Tuple1<int> > { | 526 class RequestSocketCallback : public CallbackRunner< Tuple1<int> > { |
| 532 public: | 527 public: |
| 533 RequestSocketCallback(ClientSocketHandle* handle) | 528 RequestSocketCallback(ClientSocketHandle* handle, |
| 529 TestConnectJobFactory* test_connect_job_factory, |
| 530 TestConnectJob::JobType next_job_type) |
| 534 : handle_(handle), | 531 : handle_(handle), |
| 535 within_callback_(false) {} | 532 within_callback_(false), |
| 533 test_connect_job_factory_(test_connect_job_factory), |
| 534 next_job_type_(next_job_type) {} |
| 536 | 535 |
| 537 virtual void RunWithParams(const Tuple1<int>& params) { | 536 virtual void RunWithParams(const Tuple1<int>& params) { |
| 538 callback_.RunWithParams(params); | 537 callback_.RunWithParams(params); |
| 539 ASSERT_EQ(OK, params.a); | 538 ASSERT_EQ(OK, params.a); |
| 540 | 539 |
| 541 if (!within_callback_) { | 540 if (!within_callback_) { |
| 541 test_connect_job_factory_->set_job_type(next_job_type_); |
| 542 handle_->Reset(); | 542 handle_->Reset(); |
| 543 within_callback_ = true; | 543 within_callback_ = true; |
| 544 int rv = handle_->Init( | 544 int rv = handle_->Init( |
| 545 "a", HostResolver::RequestInfo("www.google.com", 80), 0, this); | 545 "a", HostResolver::RequestInfo("www.google.com", 80), 0, this); |
| 546 EXPECT_EQ(ERR_IO_PENDING, rv); | 546 switch (next_job_type_) { |
| 547 case TestConnectJob::kMockJob: |
| 548 EXPECT_EQ(OK, rv); |
| 549 break; |
| 550 case TestConnectJob::kMockPendingJob: |
| 551 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 552 break; |
| 553 default: |
| 554 FAIL() << "Unexpected job type: " << next_job_type_; |
| 555 break; |
| 556 } |
| 547 } | 557 } |
| 548 } | 558 } |
| 549 | 559 |
| 550 int WaitForResult() { | 560 int WaitForResult() { |
| 551 return callback_.WaitForResult(); | 561 return callback_.WaitForResult(); |
| 552 } | 562 } |
| 553 | 563 |
| 554 private: | 564 private: |
| 555 ClientSocketHandle* const handle_; | 565 ClientSocketHandle* const handle_; |
| 556 bool within_callback_; | 566 bool within_callback_; |
| 567 TestConnectJobFactory* const test_connect_job_factory_; |
| 568 TestConnectJob::JobType next_job_type_; |
| 557 TestCompletionCallback callback_; | 569 TestCompletionCallback callback_; |
| 558 }; | 570 }; |
| 559 | 571 |
| 560 TEST_F(ClientSocketPoolBaseTest, RequestTwice) { | 572 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) { |
| 561 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 573 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 562 ClientSocketHandle handle(pool_.get()); | 574 ClientSocketHandle handle(pool_.get()); |
| 563 RequestSocketCallback callback(&handle); | 575 RequestSocketCallback callback( |
| 576 &handle, connect_job_factory_, TestConnectJob::kMockPendingJob); |
| 564 int rv = handle.Init( | 577 int rv = handle.Init( |
| 565 "a", ignored_request_info_, 0, &callback); | 578 "a", ignored_request_info_, 0, &callback); |
| 566 ASSERT_EQ(ERR_IO_PENDING, rv); | 579 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 567 | 580 |
| 568 EXPECT_EQ(OK, callback.WaitForResult()); | 581 EXPECT_EQ(OK, callback.WaitForResult()); |
| 569 | |
| 570 handle.Reset(); | 582 handle.Reset(); |
| 571 } | 583 } |
| 572 | 584 |
| 585 TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) { |
| 586 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 587 ClientSocketHandle handle(pool_.get()); |
| 588 RequestSocketCallback callback( |
| 589 &handle, connect_job_factory_, TestConnectJob::kMockJob); |
| 590 int rv = handle.Init( |
| 591 "a", ignored_request_info_, 0, &callback); |
| 592 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 593 |
| 594 EXPECT_EQ(OK, callback.WaitForResult()); |
| 595 handle.Reset(); |
| 596 } |
| 597 |
| 573 // Make sure that pending requests get serviced after active requests get | 598 // Make sure that pending requests get serviced after active requests get |
| 574 // cancelled. | 599 // cancelled. |
| 575 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) { | 600 TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) { |
| 576 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); | 601 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob); |
| 577 | 602 |
| 578 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; | 603 scoped_ptr<TestSocketRequest> reqs[kNumRequests]; |
| 579 | 604 |
| 580 // Queue up all the requests | 605 // Queue up all the requests |
| 581 for (size_t i = 0; i < arraysize(reqs); ++i) { | 606 for (size_t i = 0; i < arraysize(reqs); ++i) { |
| 582 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | 607 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 608 for (size_t i = 0; i < arraysize(reqs); ++i) { | 633 for (size_t i = 0; i < arraysize(reqs); ++i) { |
| 609 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); | 634 reqs[i].reset(new TestSocketRequest(pool_.get(), &request_order_)); |
| 610 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); | 635 int rv = reqs[i]->handle.Init("a", ignored_request_info_, 5, reqs[i].get()); |
| 611 EXPECT_EQ(ERR_IO_PENDING, rv); | 636 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 612 } | 637 } |
| 613 | 638 |
| 614 for (size_t i = 0; i < arraysize(reqs); ++i) | 639 for (size_t i = 0; i < arraysize(reqs); ++i) |
| 615 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult()); | 640 EXPECT_EQ(ERR_CONNECTION_FAILED, reqs[i]->WaitForResult()); |
| 616 } | 641 } |
| 617 | 642 |
| 643 // A pending asynchronous job completes, which will free up a socket slot. The |
| 644 // next job finishes synchronously. The callback for the asynchronous job |
| 645 // should be first though. |
| 646 TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) { |
| 647 // First two jobs are async. |
| 648 connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob); |
| 649 |
| 650 // Start job 1 (async error). |
| 651 TestSocketRequest req1(pool_.get(), &request_order_); |
| 652 int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1); |
| 653 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 654 |
| 655 // Start job 2 (async error). |
| 656 TestSocketRequest req2(pool_.get(), &request_order_); |
| 657 rv = req2.handle.Init("a", ignored_request_info_, 5, &req2); |
| 658 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 659 |
| 660 // The pending job is sync. |
| 661 connect_job_factory_->set_job_type(TestConnectJob::kMockJob); |
| 662 |
| 663 // Request 3 does not have a ConnectJob yet. It's just pending. |
| 664 TestSocketRequest req3(pool_.get(), &request_order_); |
| 665 rv = req3.handle.Init("a", ignored_request_info_, 5, &req3); |
| 666 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 667 |
| 668 EXPECT_EQ(ERR_CONNECTION_FAILED, req1.WaitForResult()); |
| 669 EXPECT_EQ(ERR_CONNECTION_FAILED, req2.WaitForResult()); |
| 670 EXPECT_EQ(OK, req3.WaitForResult()); |
| 671 |
| 672 ASSERT_EQ(3U, request_order_.size()); |
| 673 |
| 674 // 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 |
| 676 // synchronously succeeds, so the request order is 1, 3, 2. |
| 677 EXPECT_EQ(&req1, request_order_[0]); |
| 678 EXPECT_EQ(&req2, request_order_[2]); |
| 679 EXPECT_EQ(&req3, request_order_[1]); |
| 680 } |
| 681 |
| 618 } // namespace | 682 } // namespace |
| 619 | 683 |
| 620 } // namespace net | 684 } // namespace net |
| OLD | NEW |