resource_prefetcher_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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 3// found in the LICENSE file. 4 5#include "base/memory/ref_counted.h" 6#include "base/message_loop.h" 7#include "base/memory/scoped_ptr.h" 8#include "chrome/browser/predictors/resource_prefetcher.h" 9#include "chrome/browser/predictors/resource_prefetcher_manager.h" 10#include "chrome/test/base/testing_profile.h" 11#include "content/public/test/test_browser_thread.h" 12#include "net/url_request/url_request.h" 13#include "net/url_request/url_request_test_util.h" 14#include "testing/gtest/include/gtest/gtest.h" 15#include "testing/gmock/include/gmock/gmock.h" 16 17using testing::Eq; 18using testing::Property; 19 20namespace predictors { 21 22// Wrapper over the ResourcePrefetcher that stubs out the StartURLRequest call 23// since we do not want to do network fetches in this unittest. 24class TestResourcePrefetcher : public ResourcePrefetcher { 25 public: 26 TestResourcePrefetcher(ResourcePrefetcher::Delegate* delegate, 27 const ResourcePrefetchPredictorConfig& config, 28 const NavigationID& navigation_id, 29 PrefetchKeyType key_type, 30 scoped_ptr<RequestVector> requests) 31 : ResourcePrefetcher(delegate, config, navigation_id, 32 key_type, requests.Pass()) { } 33 34 virtual ~TestResourcePrefetcher() { } 35 36 MOCK_METHOD1(StartURLRequest, void(net::URLRequest* request)); 37 38 void ReadFullResponse(net::URLRequest* request) OVERRIDE { 39 FinishRequest(request, Request::PREFETCH_STATUS_FROM_CACHE); 40 } 41 42 private: 43 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcher); 44}; 45 46 47// Delegate for ResourcePrefetcher. 48class TestResourcePrefetcherDelegate : public ResourcePrefetcher::Delegate { 49 public: 50 explicit TestResourcePrefetcherDelegate(MessageLoop* loop) 51 : request_context_getter_(new net::TestURLRequestContextGetter( 52 loop->message_loop_proxy())) { } 53 ~TestResourcePrefetcherDelegate() { } 54 55 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE { 56 return request_context_getter_->GetURLRequestContext(); 57 } 58 59 MOCK_METHOD2(ResourcePrefetcherFinished, 60 void(ResourcePrefetcher* prefetcher, 61 ResourcePrefetcher::RequestVector* requests)); 62 63 private: 64 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; 65 66 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcherDelegate); 67}; 68 69 70// The following unittest tests most of the ResourcePrefetcher except for: 71// 1. Call to ReadFullResponse. There does not seem to be a good way to test the 72// function in a unittest, and probably requires a browser_test. 73// 2. Setting of the Prefetch status for cache vs non cache. 74class ResourcePrefetcherTest : public testing::Test { 75 public: 76 ResourcePrefetcherTest(); 77 virtual ~ResourcePrefetcherTest(); 78 79 protected: 80 typedef ResourcePrefetcher::Request Request; 81 82 void AddStartUrlRequestExpectation(const std::string& url) { 83 EXPECT_CALL(*prefetcher_, 84 StartURLRequest(Property(&net::URLRequest::original_url, 85 Eq(GURL(url))))); 86 } 87 88 void CheckPrefetcherState(size_t inflight, size_t queue, size_t host) { 89 EXPECT_EQ(prefetcher_->inflight_requests_.size(), inflight); 90 EXPECT_EQ(prefetcher_->request_queue_.size(), queue); 91 EXPECT_EQ(prefetcher_->host_inflight_counts_.size(), host); 92 } 93 94 net::URLRequest* GetInFlightRequest(const std::string& url_str) { 95 GURL url(url_str); 96 97 for (std::list<Request*>::const_iterator it = 98 prefetcher_->request_queue_.begin(); 99 it != prefetcher_->request_queue_.end(); ++it) { 100 EXPECT_NE((*it)->resource_url, url); 101 } 102 for (std::map<net::URLRequest*, Request*>::const_iterator it = 103 prefetcher_->inflight_requests_.begin(); 104 it != prefetcher_->inflight_requests_.end(); ++it) { 105 if (it->first->original_url() == url) 106 return it->first; 107 } 108 EXPECT_TRUE(false) << "Infligh request not found: " << url_str; 109 return NULL; 110 } 111 112 113 void OnReceivedRedirect(const std::string& url) { 114 prefetcher_->OnReceivedRedirect(GetInFlightRequest(url), GURL(""), NULL); 115 } 116 void OnAuthRequired(const std::string& url) { 117 prefetcher_->OnAuthRequired(GetInFlightRequest(url), NULL); 118 } 119 void OnCertificateRequested(const std::string& url) { 120 prefetcher_->OnCertificateRequested(GetInFlightRequest(url), NULL); 121 } 122 void OnSSLCertificateError(const std::string& url) { 123 prefetcher_->OnSSLCertificateError(GetInFlightRequest(url), 124 net::SSLInfo(), false); 125 } 126 void OnResponse(const std::string& url) { 127 prefetcher_->OnResponseStarted(GetInFlightRequest(url)); 128 } 129 130 MessageLoop loop_; 131 content::TestBrowserThread io_thread_; 132 ResourcePrefetchPredictorConfig config_; 133 TestResourcePrefetcherDelegate prefetcher_delegate_; 134 scoped_ptr<TestResourcePrefetcher> prefetcher_; 135 136 private: 137 DISALLOW_COPY_AND_ASSIGN(ResourcePrefetcherTest); 138}; 139 140ResourcePrefetcherTest::ResourcePrefetcherTest() 141 : loop_(MessageLoop::TYPE_IO), 142 io_thread_(content::BrowserThread::IO, &loop_), 143 prefetcher_delegate_(&loop_) { 144 config_.max_prefetches_inflight_per_navigation = 5; 145 config_.max_prefetches_inflight_per_host_per_navigation = 2; 146} 147 148ResourcePrefetcherTest::~ResourcePrefetcherTest() { 149} 150 151TEST_F(ResourcePrefetcherTest, TestPrefetcherFinishes) { 152 scoped_ptr<ResourcePrefetcher::RequestVector> requests( 153 new ResourcePrefetcher::RequestVector); 154 requests->push_back(new ResourcePrefetcher::Request(GURL( 155 "http://www.google.com/resource1.html"))); 156 requests->push_back(new ResourcePrefetcher::Request(GURL( 157 "http://www.google.com/resource2.png"))); 158 requests->push_back(new ResourcePrefetcher::Request(GURL( 159 "http://yahoo.com/resource1.png"))); 160 requests->push_back(new ResourcePrefetcher::Request(GURL( 161 "http://yahoo.com/resource2.png"))); 162 requests->push_back(new ResourcePrefetcher::Request(GURL( 163 "http://yahoo.com/resource3.png"))); 164 requests->push_back(new ResourcePrefetcher::Request(GURL( 165 "http://m.google.com/resource1.jpg"))); 166 requests->push_back(new ResourcePrefetcher::Request(GURL( 167 "http://www.google.com/resource3.html"))); 168 requests->push_back(new ResourcePrefetcher::Request(GURL( 169 "http://m.google.com/resource2.html"))); 170 requests->push_back(new ResourcePrefetcher::Request(GURL( 171 "http://m.google.com/resource3.css"))); 172 requests->push_back(new ResourcePrefetcher::Request(GURL( 173 "http://m.google.com/resource4.png"))); 174 requests->push_back(new ResourcePrefetcher::Request(GURL( 175 "http://yahoo.com/resource4.png"))); 176 requests->push_back(new ResourcePrefetcher::Request(GURL( 177 "http://yahoo.com/resource5.png"))); 178 179 NavigationID navigation_id; 180 navigation_id.render_process_id = 1; 181 navigation_id.render_view_id = 2; 182 navigation_id.main_frame_url = GURL("http://www.google.com"); 183 184 // Needed later for comparison. 185 ResourcePrefetcher::RequestVector* requests_ptr = requests.get(); 186 187 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_, 188 config_, 189 navigation_id, 190 PREFETCH_KEY_TYPE_URL, 191 requests.Pass())); 192 193 // Starting the prefetcher maxes out the number of possible requests. 194 AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); 195 AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); 196 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); 197 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); 198 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); 199 200 prefetcher_->Start(); 201 CheckPrefetcherState(5, 7, 3); 202 203 AddStartUrlRequestExpectation("http://m.google.com/resource2.html"); 204 OnResponse("http://m.google.com/resource1.jpg"); 205 CheckPrefetcherState(5, 6, 3); 206 207 AddStartUrlRequestExpectation("http://www.google.com/resource3.html"); 208 OnSSLCertificateError("http://www.google.com/resource1.html"); 209 CheckPrefetcherState(5, 5, 3); 210 211 AddStartUrlRequestExpectation("http://m.google.com/resource3.css"); 212 OnResponse("http://m.google.com/resource2.html"); 213 CheckPrefetcherState(5, 4, 3); 214 215 AddStartUrlRequestExpectation("http://m.google.com/resource4.png"); 216 OnReceivedRedirect("http://www.google.com/resource3.html"); 217 CheckPrefetcherState(5, 3, 3); 218 219 OnResponse("http://www.google.com/resource2.png"); 220 CheckPrefetcherState(4, 3, 2); 221 222 AddStartUrlRequestExpectation("http://yahoo.com/resource3.png"); 223 OnReceivedRedirect("http://yahoo.com/resource2.png"); 224 CheckPrefetcherState(4, 2, 2); 225 226 AddStartUrlRequestExpectation("http://yahoo.com/resource4.png"); 227 OnResponse("http://yahoo.com/resource1.png"); 228 CheckPrefetcherState(4, 1, 2); 229 230 AddStartUrlRequestExpectation("http://yahoo.com/resource5.png"); 231 OnResponse("http://yahoo.com/resource4.png"); 232 CheckPrefetcherState(4, 0, 2); 233 234 OnResponse("http://yahoo.com/resource5.png"); 235 CheckPrefetcherState(3, 0, 2); 236 237 OnCertificateRequested("http://m.google.com/resource4.png"); 238 CheckPrefetcherState(2, 0, 2); 239 240 OnAuthRequired("http://m.google.com/resource3.css"); 241 CheckPrefetcherState(1, 0, 1); 242 243 // Expect the final call. 244 EXPECT_CALL(prefetcher_delegate_, 245 ResourcePrefetcherFinished(Eq(prefetcher_.get()), 246 Eq(requests_ptr))); 247 248 OnResponse("http://yahoo.com/resource3.png"); 249 CheckPrefetcherState(0, 0, 0); 250 251 // Check the prefetch status. 252 EXPECT_EQ((*requests_ptr)[0]->prefetch_status, 253 Request::PREFETCH_STATUS_CERT_ERROR); 254 EXPECT_EQ((*requests_ptr)[1]->prefetch_status, 255 Request::PREFETCH_STATUS_FROM_CACHE); 256 EXPECT_EQ((*requests_ptr)[2]->prefetch_status, 257 Request::PREFETCH_STATUS_FROM_CACHE); 258 EXPECT_EQ((*requests_ptr)[3]->prefetch_status, 259 Request::PREFETCH_STATUS_REDIRECTED); 260 EXPECT_EQ((*requests_ptr)[4]->prefetch_status, 261 Request::PREFETCH_STATUS_FROM_CACHE); 262 EXPECT_EQ((*requests_ptr)[5]->prefetch_status, 263 Request::PREFETCH_STATUS_FROM_CACHE); 264 EXPECT_EQ((*requests_ptr)[6]->prefetch_status, 265 Request::PREFETCH_STATUS_REDIRECTED); 266 EXPECT_EQ((*requests_ptr)[7]->prefetch_status, 267 Request::PREFETCH_STATUS_FROM_CACHE); 268 EXPECT_EQ((*requests_ptr)[8]->prefetch_status, 269 Request::PREFETCH_STATUS_AUTH_REQUIRED); 270 EXPECT_EQ((*requests_ptr)[9]->prefetch_status, 271 Request::PREFETCH_STATUS_CERT_REQUIRED); 272 EXPECT_EQ((*requests_ptr)[10]->prefetch_status, 273 Request::PREFETCH_STATUS_FROM_CACHE); 274 EXPECT_EQ((*requests_ptr)[11]->prefetch_status, 275 Request::PREFETCH_STATUS_FROM_CACHE); 276 277 delete requests_ptr; 278} 279 280TEST_F(ResourcePrefetcherTest, TestPrefetcherStopped) { 281 scoped_ptr<ResourcePrefetcher::RequestVector> requests( 282 new ResourcePrefetcher::RequestVector); 283 requests->push_back(new ResourcePrefetcher::Request(GURL( 284 "http://www.google.com/resource1.html"))); 285 requests->push_back(new ResourcePrefetcher::Request(GURL( 286 "http://www.google.com/resource2.png"))); 287 requests->push_back(new ResourcePrefetcher::Request(GURL( 288 "http://yahoo.com/resource1.png"))); 289 requests->push_back(new ResourcePrefetcher::Request(GURL( 290 "http://yahoo.com/resource2.png"))); 291 requests->push_back(new ResourcePrefetcher::Request(GURL( 292 "http://yahoo.com/resource3.png"))); 293 requests->push_back(new ResourcePrefetcher::Request(GURL( 294 "http://m.google.com/resource1.jpg"))); 295 296 NavigationID navigation_id; 297 navigation_id.render_process_id = 1; 298 navigation_id.render_view_id = 2; 299 navigation_id.main_frame_url = GURL("http://www.google.com"); 300 301 // Needed later for comparison. 302 ResourcePrefetcher::RequestVector* requests_ptr = requests.get(); 303 304 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_, 305 config_, 306 navigation_id, 307 PREFETCH_KEY_TYPE_HOST, 308 requests.Pass())); 309 310 // Starting the prefetcher maxes out the number of possible requests. 311 AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); 312 AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); 313 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); 314 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); 315 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); 316 317 prefetcher_->Start(); 318 CheckPrefetcherState(5, 1, 3); 319 320 OnResponse("http://www.google.com/resource1.html"); 321 CheckPrefetcherState(4, 1, 3); 322 323 prefetcher_->Stop(); // No more queueing. 324 325 OnResponse("http://www.google.com/resource2.png"); 326 CheckPrefetcherState(3, 1, 2); 327 328 OnResponse("http://yahoo.com/resource1.png"); 329 CheckPrefetcherState(2, 1, 2); 330 331 OnResponse("http://yahoo.com/resource2.png"); 332 CheckPrefetcherState(1, 1, 1); 333 334 // Expect the final call. 335 EXPECT_CALL(prefetcher_delegate_, 336 ResourcePrefetcherFinished(Eq(prefetcher_.get()), 337 Eq(requests_ptr))); 338 339 OnResponse("http://m.google.com/resource1.jpg"); 340 CheckPrefetcherState(0, 1, 0); 341 342 delete requests_ptr; 343} 344 345} // namespace predictors 346