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 |