Chromium Code Reviews| Index: chrome/browser/predictors/resource_prefetcher_unittest.cc |
| diff --git a/chrome/browser/predictors/resource_prefetcher_unittest.cc b/chrome/browser/predictors/resource_prefetcher_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a0fae39d70d7d914616030044a2cfcc9c9ee9b75 |
| --- /dev/null |
| +++ b/chrome/browser/predictors/resource_prefetcher_unittest.cc |
| @@ -0,0 +1,337 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "base/memory/ref_counted.h" |
| +#include "base/message_loop.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "chrome/browser/predictors/resource_prefetcher.h" |
| +#include "chrome/browser/predictors/resource_prefetcher_manager.h" |
| +#include "chrome/test/base/testing_profile.h" |
| +#include "content/public/test/test_browser_thread.h" |
| +#include "net/url_request/url_request.h" |
| +#include "net/url_request/url_request_test_util.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| + |
| +using testing::Eq; |
| +using testing::Property; |
| + |
| +namespace predictors { |
| + |
| +// Wrapper over the ResourcePrefetcher that stubs out the StartURLRequest call |
| +// since we do not want to do network fetches in this unittest. |
| +class TestResourcePrefetcher : public ResourcePrefetcher { |
| + public: |
| + TestResourcePrefetcher(ResourcePrefetcher::Delegate* delegate, |
| + const ResourcePrefetchPredictorConfig& config, |
| + const NavigationID& navigation_id, |
| + scoped_ptr<RequestVector> requests) |
| + : ResourcePrefetcher(delegate, config, navigation_id, requests.Pass()) { } |
| + |
| + virtual ~TestResourcePrefetcher() { } |
| + |
| + MOCK_METHOD1(StartURLRequest, void(net::URLRequest* request)); |
| + |
| + void ReadFullResponse(net::URLRequest* request) OVERRIDE { |
| + FinishRequest(request, Request::PREFETCH_STATUS_FROM_CACHE); |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcher); |
| +}; |
| + |
| + |
| +// Delegate for ResourcePrefetcher. |
| +class TestResourcePrefetcherDelegate : public ResourcePrefetcher::Delegate { |
| + public: |
| + explicit TestResourcePrefetcherDelegate(MessageLoop* loop) |
| + : request_context_getter_(new TestURLRequestContextGetter( |
| + loop->message_loop_proxy())) { } |
| + ~TestResourcePrefetcherDelegate() { } |
| + |
| + virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE { |
| + return request_context_getter_->GetURLRequestContext(); |
| + } |
| + |
| + MOCK_METHOD2(ResourcePrefetcherFinished, |
| + void(ResourcePrefetcher* prefetcher, |
| + ResourcePrefetcher::RequestVector* requests)); |
| + |
| + private: |
| + TestURLRequestContextGetter* request_context_getter_; |
|
Lei Zhang
2012/09/15 01:45:11
This probably should have been a scoped_ptr.
|
| + |
| + DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcherDelegate); |
| +}; |
| + |
| + |
| +// The following unittest tests most of the ResourcePrefetcher except for: |
| +// 1. Call to ReadFullResponse. There does not seem to be a good way to test the |
| +// function in a unittest, and probably requires a browser_test. |
| +// 2. Setting of the Prefetch status for cache vs non cache. |
| +class ResourcePrefetcherTest : public testing::Test { |
| + public: |
| + ResourcePrefetcherTest(); |
| + ~ResourcePrefetcherTest(); |
| + |
| + protected: |
| + typedef ResourcePrefetcher::Request Request; |
| + |
| + void AddStartUrlRequestExpectation(const std::string& url) { |
| + EXPECT_CALL(*prefetcher_, |
| + StartURLRequest(Property(&net::URLRequest::original_url, |
| + Eq(GURL(url))))); |
| + } |
| + |
| + void CheckPrefetcherState(size_t inflight, size_t queue, size_t host) { |
| + EXPECT_EQ(prefetcher_->inflight_requests_.size(), inflight); |
| + EXPECT_EQ(prefetcher_->request_queue_.size(), queue); |
| + EXPECT_EQ(prefetcher_->host_inflight_counts_.size(), host); |
| + } |
| + |
| + net::URLRequest* GetInFlightRequest(const std::string& url_str) { |
| + GURL url(url_str); |
| + |
| + for (std::list<Request*>::const_iterator it = |
| + prefetcher_->request_queue_.begin(); |
| + it != prefetcher_->request_queue_.end(); ++it) { |
| + EXPECT_NE((*it)->resource_url, url); |
| + } |
| + for (std::map<net::URLRequest*, Request*>::const_iterator it = |
| + prefetcher_->inflight_requests_.begin(); |
| + it != prefetcher_->inflight_requests_.end(); ++it) { |
| + if (it->first->original_url() == url) |
| + return it->first; |
| + } |
| + EXPECT_TRUE(false) << "Infligh request not found: " << url_str; |
| + return NULL; |
| + } |
| + |
| + |
| + void OnReceivedRedirect(const std::string& url) { |
| + prefetcher_->OnReceivedRedirect(GetInFlightRequest(url), GURL(""), NULL); |
| + } |
| + void OnAuthRequired(const std::string& url) { |
| + prefetcher_->OnAuthRequired(GetInFlightRequest(url), NULL); |
| + } |
| + void OnCertificateRequested(const std::string& url) { |
| + prefetcher_->OnCertificateRequested(GetInFlightRequest(url), NULL); |
| + } |
| + void OnSSLCertificateError(const std::string& url) { |
| + prefetcher_->OnSSLCertificateError(GetInFlightRequest(url), |
| + net::SSLInfo(), false); |
| + } |
| + void OnResponse(const std::string& url) { |
| + prefetcher_->OnResponseStarted(GetInFlightRequest(url)); |
| + } |
| + |
| + MessageLoop loop_; |
| + content::TestBrowserThread io_thread_; |
| + ResourcePrefetchPredictorConfig config_; |
| + TestResourcePrefetcherDelegate prefetcher_delegate_; |
| + scoped_ptr<TestResourcePrefetcher> prefetcher_; |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(ResourcePrefetcherTest); |
| +}; |
| + |
| +ResourcePrefetcherTest::ResourcePrefetcherTest() |
| + : loop_(MessageLoop::TYPE_IO), |
| + io_thread_(content::BrowserThread::IO, &loop_), |
| + prefetcher_delegate_(&loop_) { |
| + config_.max_prefetches_inflight_per_navigation = 5; |
| + config_.max_prefetches_inflight_per_host_per_navigation = 2; |
| +} |
| + |
| +ResourcePrefetcherTest::~ResourcePrefetcherTest() { |
| +} |
| + |
| +TEST_F(ResourcePrefetcherTest, TestPrefetcherFinishes) { |
| + scoped_ptr<ResourcePrefetcher::RequestVector> requests( |
| + new ResourcePrefetcher::RequestVector); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://www.google.com/resource1.html"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://www.google.com/resource2.png"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://yahoo.com/resource1.png"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://yahoo.com/resource2.png"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://yahoo.com/resource3.png"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://m.google.com/resource1.jpg"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://www.google.com/resource3.html"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://m.google.com/resource2.html"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://m.google.com/resource3.css"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://m.google.com/resource4.png"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://yahoo.com/resource4.png"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://yahoo.com/resource5.png"))); |
| + |
| + NavigationID navigation_id; |
| + navigation_id.render_process_id = 1; |
| + navigation_id.render_view_id = 2; |
| + navigation_id.main_frame_url = GURL("http://www.google.com"); |
| + |
| + // Needed later for comparison. |
| + ResourcePrefetcher::RequestVector* requests_ptr = requests.get(); |
| + |
| + prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_, |
| + config_, |
| + navigation_id, |
| + requests.Pass())); |
| + |
| + // Starting the prefetcher maxes out the number of possible requests. |
| + AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); |
| + AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); |
| + AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); |
| + AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); |
| + AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); |
| + |
| + prefetcher_->Start(); |
| + CheckPrefetcherState(5, 7, 3); |
| + |
| + AddStartUrlRequestExpectation("http://m.google.com/resource2.html"); |
| + OnResponse("http://m.google.com/resource1.jpg"); |
| + CheckPrefetcherState(5, 6, 3); |
| + |
| + AddStartUrlRequestExpectation("http://www.google.com/resource3.html"); |
| + OnSSLCertificateError("http://www.google.com/resource1.html"); |
| + CheckPrefetcherState(5, 5, 3); |
| + |
| + AddStartUrlRequestExpectation("http://m.google.com/resource3.css"); |
| + OnResponse("http://m.google.com/resource2.html"); |
| + CheckPrefetcherState(5, 4, 3); |
| + |
| + AddStartUrlRequestExpectation("http://m.google.com/resource4.png"); |
| + OnReceivedRedirect("http://www.google.com/resource3.html"); |
| + CheckPrefetcherState(5, 3, 3); |
| + |
| + OnResponse("http://www.google.com/resource2.png"); |
| + CheckPrefetcherState(4, 3, 2); |
| + |
| + AddStartUrlRequestExpectation("http://yahoo.com/resource3.png"); |
| + OnReceivedRedirect("http://yahoo.com/resource2.png"); |
| + CheckPrefetcherState(4, 2, 2); |
| + |
| + AddStartUrlRequestExpectation("http://yahoo.com/resource4.png"); |
| + OnResponse("http://yahoo.com/resource1.png"); |
| + CheckPrefetcherState(4, 1, 2); |
| + |
| + AddStartUrlRequestExpectation("http://yahoo.com/resource5.png"); |
| + OnResponse("http://yahoo.com/resource4.png"); |
| + CheckPrefetcherState(4, 0, 2); |
| + |
| + OnResponse("http://yahoo.com/resource5.png"); |
| + CheckPrefetcherState(3, 0, 2); |
| + |
| + OnCertificateRequested("http://m.google.com/resource4.png"); |
| + CheckPrefetcherState(2, 0, 2); |
| + |
| + OnAuthRequired("http://m.google.com/resource3.css"); |
| + CheckPrefetcherState(1, 0, 1); |
| + |
| + // Expect the final call. |
| + EXPECT_CALL(prefetcher_delegate_, |
| + ResourcePrefetcherFinished(Eq(prefetcher_.get()), |
| + Eq(requests_ptr))); |
| + |
| + OnResponse("http://yahoo.com/resource3.png"); |
| + CheckPrefetcherState(0, 0, 0); |
| + |
| + // Check the prefetch status. |
| + EXPECT_EQ((*requests_ptr)[0]->prefetch_status, |
| + Request::PREFETCH_STATUS_CERT_ERROR); |
| + EXPECT_EQ((*requests_ptr)[1]->prefetch_status, |
| + Request::PREFETCH_STATUS_FROM_CACHE); |
| + EXPECT_EQ((*requests_ptr)[2]->prefetch_status, |
| + Request::PREFETCH_STATUS_FROM_CACHE); |
| + EXPECT_EQ((*requests_ptr)[3]->prefetch_status, |
| + Request::PREFETCH_STATUS_REDIRECTED); |
| + EXPECT_EQ((*requests_ptr)[4]->prefetch_status, |
| + Request::PREFETCH_STATUS_FROM_CACHE); |
| + EXPECT_EQ((*requests_ptr)[5]->prefetch_status, |
| + Request::PREFETCH_STATUS_FROM_CACHE); |
| + EXPECT_EQ((*requests_ptr)[6]->prefetch_status, |
| + Request::PREFETCH_STATUS_REDIRECTED); |
| + EXPECT_EQ((*requests_ptr)[7]->prefetch_status, |
| + Request::PREFETCH_STATUS_FROM_CACHE); |
| + EXPECT_EQ((*requests_ptr)[8]->prefetch_status, |
| + Request::PREFETCH_STATUS_AUTH_REQUIRED); |
| + EXPECT_EQ((*requests_ptr)[9]->prefetch_status, |
| + Request::PREFETCH_STATUS_CERT_REQUIRED); |
| + EXPECT_EQ((*requests_ptr)[10]->prefetch_status, |
| + Request::PREFETCH_STATUS_FROM_CACHE); |
| + EXPECT_EQ((*requests_ptr)[11]->prefetch_status, |
| + Request::PREFETCH_STATUS_FROM_CACHE); |
| +} |
| + |
| +TEST_F(ResourcePrefetcherTest, TestPrefetcherStopped) { |
| + scoped_ptr<ResourcePrefetcher::RequestVector> requests( |
| + new ResourcePrefetcher::RequestVector); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://www.google.com/resource1.html"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://www.google.com/resource2.png"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://yahoo.com/resource1.png"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://yahoo.com/resource2.png"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://yahoo.com/resource3.png"))); |
| + requests->push_back(new ResourcePrefetcher::Request(GURL( |
| + "http://m.google.com/resource1.jpg"))); |
| + |
| + NavigationID navigation_id; |
| + navigation_id.render_process_id = 1; |
| + navigation_id.render_view_id = 2; |
| + navigation_id.main_frame_url = GURL("http://www.google.com"); |
| + |
| + // Needed later for comparison. |
| + ResourcePrefetcher::RequestVector* requests_ptr = requests.get(); |
| + |
| + prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_, |
| + config_, |
| + navigation_id, |
| + requests.Pass())); |
| + |
| + // Starting the prefetcher maxes out the number of possible requests. |
| + AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); |
| + AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); |
| + AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); |
| + AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); |
| + AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); |
| + |
| + prefetcher_->Start(); |
| + CheckPrefetcherState(5, 1, 3); |
| + |
| + OnResponse("http://www.google.com/resource1.html"); |
| + CheckPrefetcherState(4, 1, 3); |
| + |
| + prefetcher_->Stop(); // No more queueing. |
| + |
| + OnResponse("http://www.google.com/resource2.png"); |
| + CheckPrefetcherState(3, 1, 2); |
| + |
| + OnResponse("http://yahoo.com/resource1.png"); |
| + CheckPrefetcherState(2, 1, 2); |
| + |
| + OnResponse("http://yahoo.com/resource2.png"); |
| + CheckPrefetcherState(1, 1, 1); |
| + |
| + // Expect the final call. |
| + EXPECT_CALL(prefetcher_delegate_, |
| + ResourcePrefetcherFinished(Eq(prefetcher_.get()), |
| + Eq(requests_ptr))); |
| + |
| + OnResponse("http://m.google.com/resource1.jpg"); |
| + CheckPrefetcherState(0, 1, 0); |
| +} |
| + |
| +} // namespace predictors |