| 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/proxy/multi_threaded_proxy_resolver.h" | 5 #include "net/proxy/multi_threaded_proxy_resolver.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 // Tests setting the PAC script once, lazily creating new threads, and | 519 // Tests setting the PAC script once, lazily creating new threads, and |
| 520 // cancelling requests. | 520 // cancelling requests. |
| 521 TEST_F(MultiThreadedProxyResolverTest, ThreeThreads_Basic) { | 521 TEST_F(MultiThreadedProxyResolverTest, ThreeThreads_Basic) { |
| 522 const size_t kNumThreads = 3u; | 522 const size_t kNumThreads = 3u; |
| 523 ASSERT_NO_FATAL_FAILURE(Init(kNumThreads)); | 523 ASSERT_NO_FATAL_FAILURE(Init(kNumThreads)); |
| 524 | 524 |
| 525 // Verify that it reaches the synchronous resolver. | 525 // Verify that it reaches the synchronous resolver. |
| 526 // One thread has been provisioned (i.e. one ProxyResolver was created). | 526 // One thread has been provisioned (i.e. one ProxyResolver was created). |
| 527 ASSERT_EQ(1u, factory().resolvers().size()); | 527 ASSERT_EQ(1u, factory().resolvers().size()); |
| 528 | 528 |
| 529 const int kNumRequests = 9; | 529 const int kNumRequests = 8; |
| 530 int rv; | 530 int rv; |
| 531 TestCompletionCallback callback[kNumRequests]; | 531 TestCompletionCallback callback[kNumRequests]; |
| 532 ProxyInfo results[kNumRequests]; | 532 ProxyInfo results[kNumRequests]; |
| 533 ProxyResolver::RequestHandle request[kNumRequests]; | 533 ProxyResolver::RequestHandle request[kNumRequests]; |
| 534 | 534 |
| 535 // Start request 0 -- this should run on thread 0 as there is nothing else | 535 // Start request 0 -- this should run on thread 0 as there is nothing else |
| 536 // going on right now. | 536 // going on right now. |
| 537 rv = resolver().GetProxyForURL(GURL("http://request0"), &results[0], | 537 rv = resolver().GetProxyForURL(GURL("http://request0"), &results[0], |
| 538 callback[0].callback(), &request[0], | 538 callback[0].callback(), &request[0], |
| 539 BoundNetLog()); | 539 BoundNetLog()); |
| 540 EXPECT_EQ(ERR_IO_PENDING, rv); | 540 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 541 | 541 |
| 542 // Wait for request 0 to finish. | 542 // Wait for request 0 to finish. |
| 543 rv = callback[0].WaitForResult(); | 543 rv = callback[0].WaitForResult(); |
| 544 EXPECT_EQ(0, rv); | 544 EXPECT_EQ(0, rv); |
| 545 EXPECT_EQ("PROXY request0:80", results[0].ToPacString()); | 545 EXPECT_EQ("PROXY request0:80", results[0].ToPacString()); |
| 546 ASSERT_EQ(1u, factory().resolvers().size()); | 546 ASSERT_EQ(1u, factory().resolvers().size()); |
| 547 EXPECT_EQ(1, factory().resolvers()[0]->request_count()); | 547 EXPECT_EQ(1, factory().resolvers()[0]->request_count()); |
| 548 | 548 |
| 549 base::MessageLoop::current()->RunUntilIdle(); | 549 base::MessageLoop::current()->RunUntilIdle(); |
| 550 | 550 |
| 551 // We now start 8 requests in parallel -- this will cause the maximum of | 551 // We now block the first resolver to ensure a request is sent to the second |
| 552 // three threads to be provisioned (an additional two from what we already | 552 // thread. |
| 553 // have). | 553 factory().resolvers()[0]->Block(); |
| 554 rv = resolver().GetProxyForURL(GURL("http://request1"), &results[1], |
| 555 callback[1].callback(), &request[1], |
| 556 BoundNetLog()); |
| 557 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 558 rv = resolver().GetProxyForURL(GURL("http://request2"), &results[2], |
| 559 callback[2].callback(), &request[2], |
| 560 BoundNetLog()); |
| 561 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 562 EXPECT_EQ(0, callback[2].WaitForResult()); |
| 563 ASSERT_EQ(2u, factory().resolvers().size()); |
| 554 | 564 |
| 555 for (int i = 1; i < kNumRequests; ++i) { | 565 // We now block the second resolver as well to ensure a request is sent to the |
| 556 rv = resolver().GetProxyForURL( | 566 // third thread. |
| 557 GURL(base::StringPrintf("http://request%d", i)), &results[i], | 567 factory().resolvers()[1]->Block(); |
| 558 callback[i].callback(), &request[i], BoundNetLog()); | 568 rv = resolver().GetProxyForURL(GURL("http://request3"), &results[3], |
| 559 EXPECT_EQ(ERR_IO_PENDING, rv); | 569 callback[3].callback(), &request[3], |
| 560 } | 570 BoundNetLog()); |
| 561 | 571 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 562 // Cancel 3 of the 8 oustanding requests. | 572 rv = resolver().GetProxyForURL(GURL("http://request4"), &results[4], |
| 563 resolver().CancelRequest(request[1]); | 573 callback[4].callback(), &request[4], |
| 564 resolver().CancelRequest(request[3]); | 574 BoundNetLog()); |
| 565 resolver().CancelRequest(request[6]); | 575 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 566 | 576 EXPECT_EQ(0, callback[4].WaitForResult()); |
| 567 // Wait for the remaining requests to complete. | |
| 568 int kNonCancelledRequests[] = {2, 4, 5, 7, 8}; | |
| 569 for (size_t i = 0; i < arraysize(kNonCancelledRequests); ++i) { | |
| 570 int request_index = kNonCancelledRequests[i]; | |
| 571 EXPECT_GE(callback[request_index].WaitForResult(), 0); | |
| 572 } | |
| 573 | |
| 574 // Check that the cancelled requests never invoked their callback. | |
| 575 EXPECT_FALSE(callback[1].have_result()); | |
| 576 EXPECT_FALSE(callback[3].have_result()); | |
| 577 EXPECT_FALSE(callback[6].have_result()); | |
| 578 | 577 |
| 579 // We should now have a total of 3 threads, each with its own ProxyResolver | 578 // We should now have a total of 3 threads, each with its own ProxyResolver |
| 580 // that will get initialized with the same data. | 579 // that will get initialized with the same data. |
| 581 ASSERT_EQ(3u, factory().resolvers().size()); | 580 ASSERT_EQ(3u, factory().resolvers().size()); |
| 582 | 581 |
| 583 ASSERT_EQ(3u, factory().script_data().size()); | 582 ASSERT_EQ(3u, factory().script_data().size()); |
| 584 for (int i = 0; i < 3; ++i) { | 583 for (int i = 0; i < 3; ++i) { |
| 585 EXPECT_EQ(ASCIIToUTF16("pac script bytes"), | 584 EXPECT_EQ(ASCIIToUTF16("pac script bytes"), |
| 586 factory().script_data()[i]->utf16()) | 585 factory().script_data()[i]->utf16()) |
| 587 << "i=" << i; | 586 << "i=" << i; |
| 588 } | 587 } |
| 589 | 588 |
| 590 // We don't know the exact ordering that requests ran on threads with, | 589 // Start and cancel two requests. Since the first two threads are still |
| 591 // but we do know the total count that should have reached the threads. | 590 // blocked, they'll both be serviced by the third thread. The first request |
| 592 // 8 total were submitted, and three were cancelled. Of the three that | 591 // will reach the resolver, but the second will still be queued when canceled. |
| 593 // were cancelled, one of them (request 1) was cancelled after it had | 592 // Start a third request so we can be sure the resolver has completed running |
| 594 // already been posted to the worker thread. So the resolvers will | 593 // the first request. |
| 595 // have seen 6 total (and 1 from the run prior). | 594 rv = resolver().GetProxyForURL(GURL("http://request5"), &results[5], |
| 596 int total_count = 0; | 595 callback[5].callback(), &request[5], |
| 597 for (int i = 0; i < 3; ++i) { | 596 BoundNetLog()); |
| 598 total_count += factory().resolvers()[i]->request_count(); | 597 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 599 } | 598 rv = resolver().GetProxyForURL(GURL("http://request6"), &results[6], |
| 600 EXPECT_EQ(7, total_count); | 599 callback[6].callback(), &request[6], |
| 600 BoundNetLog()); |
| 601 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 602 rv = resolver().GetProxyForURL(GURL("http://request7"), &results[7], |
| 603 callback[7].callback(), &request[7], |
| 604 BoundNetLog()); |
| 605 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 606 resolver().CancelRequest(request[5]); |
| 607 resolver().CancelRequest(request[6]); |
| 608 |
| 609 EXPECT_EQ(2, callback[7].WaitForResult()); |
| 610 |
| 611 // Check that the cancelled requests never invoked their callback. |
| 612 EXPECT_FALSE(callback[5].have_result()); |
| 613 EXPECT_FALSE(callback[6].have_result()); |
| 614 |
| 615 // Unblock the first two threads and wait for their requests to complete. |
| 616 factory().resolvers()[0]->Unblock(); |
| 617 factory().resolvers()[1]->Unblock(); |
| 618 EXPECT_EQ(1, callback[1].WaitForResult()); |
| 619 EXPECT_EQ(1, callback[3].WaitForResult()); |
| 620 |
| 621 EXPECT_EQ(2, factory().resolvers()[0]->request_count()); |
| 622 EXPECT_EQ(2, factory().resolvers()[1]->request_count()); |
| 623 EXPECT_EQ(3, factory().resolvers()[2]->request_count()); |
| 601 } | 624 } |
| 602 | 625 |
| 603 // Tests using two threads. The first request hangs the first thread. Checks | 626 // Tests using two threads. The first request hangs the first thread. Checks |
| 604 // that other requests are able to complete while this first request remains | 627 // that other requests are able to complete while this first request remains |
| 605 // stalled. | 628 // stalled. |
| 606 TEST_F(MultiThreadedProxyResolverTest, OneThreadBlocked) { | 629 TEST_F(MultiThreadedProxyResolverTest, OneThreadBlocked) { |
| 607 const size_t kNumThreads = 2u; | 630 const size_t kNumThreads = 2u; |
| 608 ASSERT_NO_FATAL_FAILURE(Init(kNumThreads)); | 631 ASSERT_NO_FATAL_FAILURE(Init(kNumThreads)); |
| 609 | 632 |
| 610 int rv; | 633 int rv; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 } | 778 } |
| 756 // The factory destructor will block until the worker thread stops, but it may | 779 // The factory destructor will block until the worker thread stops, but it may |
| 757 // post tasks to the origin message loop which are still pending. Run them | 780 // post tasks to the origin message loop which are still pending. Run them |
| 758 // now to ensure it works as expected. | 781 // now to ensure it works as expected. |
| 759 base::RunLoop().RunUntilIdle(); | 782 base::RunLoop().RunUntilIdle(); |
| 760 } | 783 } |
| 761 | 784 |
| 762 } // namespace | 785 } // namespace |
| 763 | 786 |
| 764 } // namespace net | 787 } // namespace net |
| OLD | NEW |