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 |