| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/predictors/resource_prefetcher.h" | 5 #include "chrome/browser/predictors/resource_prefetcher.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 namespace predictors { | 28 namespace predictors { |
| 29 | 29 |
| 30 // Wrapper over the ResourcePrefetcher that stubs out the StartURLRequest call | 30 // Wrapper over the ResourcePrefetcher that stubs out the StartURLRequest call |
| 31 // since we do not want to do network fetches in this unittest. | 31 // since we do not want to do network fetches in this unittest. |
| 32 class TestResourcePrefetcher : public ResourcePrefetcher { | 32 class TestResourcePrefetcher : public ResourcePrefetcher { |
| 33 public: | 33 public: |
| 34 TestResourcePrefetcher(ResourcePrefetcher::Delegate* delegate, | 34 TestResourcePrefetcher(ResourcePrefetcher::Delegate* delegate, |
| 35 const ResourcePrefetchPredictorConfig& config, | 35 const ResourcePrefetchPredictorConfig& config, |
| 36 const NavigationID& navigation_id, | 36 const NavigationID& navigation_id, |
| 37 PrefetchKeyType key_type, | 37 PrefetchKeyType key_type, |
| 38 std::unique_ptr<RequestVector> requests) | 38 const std::vector<GURL>& urls) |
| 39 : ResourcePrefetcher(delegate, | 39 : ResourcePrefetcher(delegate, config, navigation_id, key_type, urls) {} |
| 40 config, | |
| 41 navigation_id, | |
| 42 key_type, | |
| 43 std::move(requests)) {} | |
| 44 | 40 |
| 45 ~TestResourcePrefetcher() override {} | 41 ~TestResourcePrefetcher() override {} |
| 46 | 42 |
| 47 MOCK_METHOD1(StartURLRequest, void(net::URLRequest* request)); | 43 MOCK_METHOD1(StartURLRequest, void(net::URLRequest* request)); |
| 48 | 44 |
| 49 void ReadFullResponse(net::URLRequest* request) override { | 45 void ReadFullResponse(net::URLRequest* request) override { |
| 50 EXPECT_TRUE(request->load_flags() & net::LOAD_PREFETCH); | 46 EXPECT_TRUE(request->load_flags() & net::LOAD_PREFETCH); |
| 51 FinishRequest(request, Request::PREFETCH_STATUS_FROM_CACHE); | 47 FinishRequest(request); |
| 52 } | 48 } |
| 53 | 49 |
| 54 private: | 50 private: |
| 55 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcher); | 51 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcher); |
| 56 }; | 52 }; |
| 57 | 53 |
| 58 | 54 |
| 59 // Delegate for ResourcePrefetcher. | 55 // Delegate for ResourcePrefetcher. |
| 60 class TestResourcePrefetcherDelegate : public ResourcePrefetcher::Delegate { | 56 class TestResourcePrefetcherDelegate : public ResourcePrefetcher::Delegate { |
| 61 public: | 57 public: |
| 62 explicit TestResourcePrefetcherDelegate(base::MessageLoop* loop) | 58 explicit TestResourcePrefetcherDelegate(base::MessageLoop* loop) |
| 63 : request_context_getter_( | 59 : request_context_getter_( |
| 64 new net::TestURLRequestContextGetter(loop->task_runner())) {} | 60 new net::TestURLRequestContextGetter(loop->task_runner())) {} |
| 65 ~TestResourcePrefetcherDelegate() { } | 61 ~TestResourcePrefetcherDelegate() { } |
| 66 | 62 |
| 67 net::URLRequestContext* GetURLRequestContext() override { | 63 net::URLRequestContext* GetURLRequestContext() override { |
| 68 return request_context_getter_->GetURLRequestContext(); | 64 return request_context_getter_->GetURLRequestContext(); |
| 69 } | 65 } |
| 70 | 66 |
| 71 MOCK_METHOD2(ResourcePrefetcherFinished, | 67 MOCK_METHOD1(ResourcePrefetcherFinished, |
| 72 void(ResourcePrefetcher* prefetcher, | 68 void(ResourcePrefetcher* prefetcher)); |
| 73 ResourcePrefetcher::RequestVector* requests)); | |
| 74 | 69 |
| 75 private: | 70 private: |
| 76 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; | 71 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; |
| 77 | 72 |
| 78 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcherDelegate); | 73 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcherDelegate); |
| 79 }; | 74 }; |
| 80 | 75 |
| 81 | 76 |
| 82 // The following unittest tests most of the ResourcePrefetcher except for: | 77 // The following unittest tests most of the ResourcePrefetcher except for: |
| 83 // 1. Call to ReadFullResponse. There does not seem to be a good way to test the | 78 // 1. Call to ReadFullResponse. There does not seem to be a good way to test the |
| 84 // function in a unittest, and probably requires a browser_test. | 79 // function in a unittest, and probably requires a browser_test. |
| 85 // 2. Setting of the Prefetch status for cache vs non cache. | 80 // 2. Setting of the Prefetch status for cache vs non cache. |
| 86 class ResourcePrefetcherTest : public testing::Test { | 81 class ResourcePrefetcherTest : public testing::Test { |
| 87 public: | 82 public: |
| 88 ResourcePrefetcherTest(); | 83 ResourcePrefetcherTest(); |
| 89 ~ResourcePrefetcherTest() override; | 84 ~ResourcePrefetcherTest() override; |
| 90 | 85 |
| 91 protected: | 86 protected: |
| 92 typedef ResourcePrefetcher::Request Request; | |
| 93 | |
| 94 void AddStartUrlRequestExpectation(const std::string& url) { | 87 void AddStartUrlRequestExpectation(const std::string& url) { |
| 95 EXPECT_CALL(*prefetcher_, | 88 EXPECT_CALL(*prefetcher_, |
| 96 StartURLRequest(Property(&net::URLRequest::original_url, | 89 StartURLRequest(Property(&net::URLRequest::original_url, |
| 97 Eq(GURL(url))))); | 90 Eq(GURL(url))))); |
| 98 } | 91 } |
| 99 | 92 |
| 100 void CheckPrefetcherState(size_t inflight, size_t queue, size_t host) { | 93 void CheckPrefetcherState(size_t inflight, size_t queue, size_t host) { |
| 101 EXPECT_EQ(prefetcher_->inflight_requests_.size(), inflight); | 94 EXPECT_EQ(prefetcher_->inflight_requests_.size(), inflight); |
| 102 EXPECT_EQ(prefetcher_->request_queue_.size(), queue); | 95 EXPECT_EQ(prefetcher_->request_queue_.size(), queue); |
| 103 EXPECT_EQ(prefetcher_->host_inflight_counts_.size(), host); | 96 EXPECT_EQ(prefetcher_->host_inflight_counts_.size(), host); |
| 104 } | 97 } |
| 105 | 98 |
| 106 net::URLRequest* GetInFlightRequest(const std::string& url_str) { | 99 net::URLRequest* GetInFlightRequest(const std::string& url_str) { |
| 107 GURL url(url_str); | 100 GURL url(url_str); |
| 108 | 101 |
| 109 for (auto* request : prefetcher_->request_queue_) { | 102 for (const auto& queued_url : prefetcher_->request_queue_) { |
| 110 EXPECT_NE(request->resource_url, url); | 103 EXPECT_NE(queued_url, url); |
| 111 } | 104 } |
| 112 for (const auto& key_value : prefetcher_->inflight_requests_) { | 105 for (const auto& key_value : prefetcher_->inflight_requests_) { |
| 113 if (key_value.first->original_url() == url) | 106 if (key_value.first->original_url() == url) |
| 114 return key_value.first; | 107 return key_value.first; |
| 115 } | 108 } |
| 116 EXPECT_TRUE(false) << "In flight request not found: " << url_str; | 109 EXPECT_TRUE(false) << "In flight request not found: " << url_str; |
| 117 return NULL; | 110 return NULL; |
| 118 } | 111 } |
| 119 | 112 |
| 120 | 113 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 151 io_thread_(content::BrowserThread::IO, &loop_), | 144 io_thread_(content::BrowserThread::IO, &loop_), |
| 152 prefetcher_delegate_(&loop_) { | 145 prefetcher_delegate_(&loop_) { |
| 153 config_.max_prefetches_inflight_per_navigation = 5; | 146 config_.max_prefetches_inflight_per_navigation = 5; |
| 154 config_.max_prefetches_inflight_per_host_per_navigation = 2; | 147 config_.max_prefetches_inflight_per_host_per_navigation = 2; |
| 155 } | 148 } |
| 156 | 149 |
| 157 ResourcePrefetcherTest::~ResourcePrefetcherTest() { | 150 ResourcePrefetcherTest::~ResourcePrefetcherTest() { |
| 158 } | 151 } |
| 159 | 152 |
| 160 TEST_F(ResourcePrefetcherTest, TestPrefetcherFinishes) { | 153 TEST_F(ResourcePrefetcherTest, TestPrefetcherFinishes) { |
| 161 std::unique_ptr<ResourcePrefetcher::RequestVector> requests( | 154 std::vector<GURL> urls = {GURL("http://www.google.com/resource1.html"), |
| 162 new ResourcePrefetcher::RequestVector); | 155 GURL("http://www.google.com/resource2.png"), |
| 163 requests->push_back(new ResourcePrefetcher::Request(GURL( | 156 GURL("http://yahoo.com/resource1.png"), |
| 164 "http://www.google.com/resource1.html"))); | 157 GURL("http://yahoo.com/resource2.png"), |
| 165 requests->push_back(new ResourcePrefetcher::Request(GURL( | 158 GURL("http://yahoo.com/resource3.png"), |
| 166 "http://www.google.com/resource2.png"))); | 159 GURL("http://m.google.com/resource1.jpg"), |
| 167 requests->push_back(new ResourcePrefetcher::Request(GURL( | 160 GURL("http://www.google.com/resource3.html"), |
| 168 "http://yahoo.com/resource1.png"))); | 161 GURL("http://m.google.com/resource2.html"), |
| 169 requests->push_back(new ResourcePrefetcher::Request(GURL( | 162 GURL("http://m.google.com/resource3.css"), |
| 170 "http://yahoo.com/resource2.png"))); | 163 GURL("http://m.google.com/resource4.png"), |
| 171 requests->push_back(new ResourcePrefetcher::Request(GURL( | 164 GURL("http://yahoo.com/resource4.png"), |
| 172 "http://yahoo.com/resource3.png"))); | 165 GURL("http://yahoo.com/resource5.png")}; |
| 173 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
| 174 "http://m.google.com/resource1.jpg"))); | |
| 175 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
| 176 "http://www.google.com/resource3.html"))); | |
| 177 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
| 178 "http://m.google.com/resource2.html"))); | |
| 179 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
| 180 "http://m.google.com/resource3.css"))); | |
| 181 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
| 182 "http://m.google.com/resource4.png"))); | |
| 183 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
| 184 "http://yahoo.com/resource4.png"))); | |
| 185 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
| 186 "http://yahoo.com/resource5.png"))); | |
| 187 | 166 |
| 188 NavigationID navigation_id(1, 2, GURL("http://www.google.com")); | 167 NavigationID navigation_id(1, 2, GURL("http://www.google.com")); |
| 189 | 168 |
| 190 // Needed later for comparison. | 169 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_, config_, |
| 191 ResourcePrefetcher::RequestVector* requests_ptr = requests.get(); | 170 navigation_id, |
| 192 | 171 PREFETCH_KEY_TYPE_URL, urls)); |
| 193 prefetcher_.reset( | |
| 194 new TestResourcePrefetcher(&prefetcher_delegate_, config_, navigation_id, | |
| 195 PREFETCH_KEY_TYPE_URL, std::move(requests))); | |
| 196 | 172 |
| 197 // Starting the prefetcher maxes out the number of possible requests. | 173 // Starting the prefetcher maxes out the number of possible requests. |
| 198 AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); | 174 AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); |
| 199 AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); | 175 AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); |
| 200 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); | 176 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); |
| 201 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); | 177 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); |
| 202 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); | 178 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); |
| 203 | 179 |
| 204 prefetcher_->Start(); | 180 prefetcher_->Start(); |
| 205 CheckPrefetcherState(5, 7, 3); | 181 CheckPrefetcherState(5, 7, 3); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 CheckPrefetcherState(3, 0, 2); | 215 CheckPrefetcherState(3, 0, 2); |
| 240 | 216 |
| 241 OnCertificateRequested("http://m.google.com/resource4.png"); | 217 OnCertificateRequested("http://m.google.com/resource4.png"); |
| 242 CheckPrefetcherState(2, 0, 2); | 218 CheckPrefetcherState(2, 0, 2); |
| 243 | 219 |
| 244 OnAuthRequired("http://m.google.com/resource3.css"); | 220 OnAuthRequired("http://m.google.com/resource3.css"); |
| 245 CheckPrefetcherState(1, 0, 1); | 221 CheckPrefetcherState(1, 0, 1); |
| 246 | 222 |
| 247 // Expect the final call. | 223 // Expect the final call. |
| 248 EXPECT_CALL(prefetcher_delegate_, | 224 EXPECT_CALL(prefetcher_delegate_, |
| 249 ResourcePrefetcherFinished(Eq(prefetcher_.get()), | 225 ResourcePrefetcherFinished(Eq(prefetcher_.get()))); |
| 250 Eq(requests_ptr))); | |
| 251 | 226 |
| 252 OnResponse("http://yahoo.com/resource3.png"); | 227 OnResponse("http://yahoo.com/resource3.png"); |
| 253 CheckPrefetcherState(0, 0, 0); | 228 CheckPrefetcherState(0, 0, 0); |
| 254 | |
| 255 // Check the prefetch status. | |
| 256 EXPECT_EQ(Request::PREFETCH_STATUS_CERT_ERROR, | |
| 257 (*requests_ptr)[0]->prefetch_status); | |
| 258 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE, | |
| 259 (*requests_ptr)[1]->prefetch_status); | |
| 260 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE, | |
| 261 (*requests_ptr)[2]->prefetch_status); | |
| 262 EXPECT_EQ(Request::PREFETCH_STATUS_REDIRECTED, | |
| 263 (*requests_ptr)[3]->prefetch_status); | |
| 264 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE, | |
| 265 (*requests_ptr)[4]->prefetch_status); | |
| 266 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE, | |
| 267 (*requests_ptr)[5]->prefetch_status); | |
| 268 EXPECT_EQ(Request::PREFETCH_STATUS_REDIRECTED, | |
| 269 (*requests_ptr)[6]->prefetch_status); | |
| 270 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE, | |
| 271 (*requests_ptr)[7]->prefetch_status); | |
| 272 EXPECT_EQ(Request::PREFETCH_STATUS_AUTH_REQUIRED, | |
| 273 (*requests_ptr)[8]->prefetch_status); | |
| 274 EXPECT_EQ(Request::PREFETCH_STATUS_CERT_REQUIRED, | |
| 275 (*requests_ptr)[9]->prefetch_status); | |
| 276 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE, | |
| 277 (*requests_ptr)[10]->prefetch_status); | |
| 278 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE, | |
| 279 (*requests_ptr)[11]->prefetch_status); | |
| 280 | |
| 281 // We need to delete requests_ptr here, though it looks to be managed by the | |
| 282 // scoped_ptr requests. The scoped_ptr requests releases itself and the raw | |
| 283 // pointer requests_ptr is passed to ResourcePrefetcherFinished(). In the | |
| 284 // test, ResourcePrefetcherFinished() is a mock function and does not handle | |
| 285 // the raw pointer properly. In the real code, requests_ptr will eventually be | |
| 286 // passed to and managed by ResourcePrefetchPredictor::Result::Result. | |
| 287 delete requests_ptr; | |
| 288 } | 229 } |
| 289 | 230 |
| 290 TEST_F(ResourcePrefetcherTest, TestPrefetcherStopped) { | 231 TEST_F(ResourcePrefetcherTest, TestPrefetcherStopped) { |
| 291 std::unique_ptr<ResourcePrefetcher::RequestVector> requests( | 232 std::vector<GURL> urls = {GURL("http://www.google.com/resource1.html"), |
| 292 new ResourcePrefetcher::RequestVector); | 233 GURL("http://www.google.com/resource2.png"), |
| 293 requests->push_back(new ResourcePrefetcher::Request(GURL( | 234 GURL("http://yahoo.com/resource1.png"), |
| 294 "http://www.google.com/resource1.html"))); | 235 GURL("http://yahoo.com/resource2.png"), |
| 295 requests->push_back(new ResourcePrefetcher::Request(GURL( | 236 GURL("http://yahoo.com/resource3.png"), |
| 296 "http://www.google.com/resource2.png"))); | 237 GURL("http://m.google.com/resource1.jpg")}; |
| 297 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
| 298 "http://yahoo.com/resource1.png"))); | |
| 299 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
| 300 "http://yahoo.com/resource2.png"))); | |
| 301 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
| 302 "http://yahoo.com/resource3.png"))); | |
| 303 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
| 304 "http://m.google.com/resource1.jpg"))); | |
| 305 | 238 |
| 306 NavigationID navigation_id(1, 2, GURL("http://www.google.com")); | 239 NavigationID navigation_id(1, 2, GURL("http://www.google.com")); |
| 307 | 240 |
| 308 // Needed later for comparison. | 241 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_, config_, |
| 309 ResourcePrefetcher::RequestVector* requests_ptr = requests.get(); | 242 navigation_id, |
| 310 | 243 PREFETCH_KEY_TYPE_HOST, urls)); |
| 311 prefetcher_.reset( | |
| 312 new TestResourcePrefetcher(&prefetcher_delegate_, config_, navigation_id, | |
| 313 PREFETCH_KEY_TYPE_HOST, std::move(requests))); | |
| 314 | 244 |
| 315 // Starting the prefetcher maxes out the number of possible requests. | 245 // Starting the prefetcher maxes out the number of possible requests. |
| 316 AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); | 246 AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); |
| 317 AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); | 247 AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); |
| 318 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); | 248 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); |
| 319 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); | 249 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); |
| 320 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); | 250 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); |
| 321 | 251 |
| 322 prefetcher_->Start(); | 252 prefetcher_->Start(); |
| 323 CheckPrefetcherState(5, 1, 3); | 253 CheckPrefetcherState(5, 1, 3); |
| 324 | 254 |
| 325 OnResponse("http://www.google.com/resource1.html"); | 255 OnResponse("http://www.google.com/resource1.html"); |
| 326 CheckPrefetcherState(4, 1, 3); | 256 CheckPrefetcherState(4, 1, 3); |
| 327 | 257 |
| 328 prefetcher_->Stop(); // No more queueing. | 258 prefetcher_->Stop(); // No more queueing. |
| 329 | 259 |
| 330 OnResponse("http://www.google.com/resource2.png"); | 260 OnResponse("http://www.google.com/resource2.png"); |
| 331 CheckPrefetcherState(3, 1, 2); | 261 CheckPrefetcherState(3, 1, 2); |
| 332 | 262 |
| 333 OnResponse("http://yahoo.com/resource1.png"); | 263 OnResponse("http://yahoo.com/resource1.png"); |
| 334 CheckPrefetcherState(2, 1, 2); | 264 CheckPrefetcherState(2, 1, 2); |
| 335 | 265 |
| 336 OnResponse("http://yahoo.com/resource2.png"); | 266 OnResponse("http://yahoo.com/resource2.png"); |
| 337 CheckPrefetcherState(1, 1, 1); | 267 CheckPrefetcherState(1, 1, 1); |
| 338 | 268 |
| 339 // Expect the final call. | 269 // Expect the final call. |
| 340 EXPECT_CALL(prefetcher_delegate_, | 270 EXPECT_CALL(prefetcher_delegate_, |
| 341 ResourcePrefetcherFinished(Eq(prefetcher_.get()), | 271 ResourcePrefetcherFinished(Eq(prefetcher_.get()))); |
| 342 Eq(requests_ptr))); | |
| 343 | 272 |
| 344 OnResponse("http://m.google.com/resource1.jpg"); | 273 OnResponse("http://m.google.com/resource1.jpg"); |
| 345 CheckPrefetcherState(0, 1, 0); | 274 CheckPrefetcherState(0, 1, 0); |
| 346 | |
| 347 // We need to delete requests_ptr here, though it looks to be managed by the | |
| 348 // scoped_ptr requests. The scoped_ptr requests releases itself and the raw | |
| 349 // pointer requests_ptr is passed to ResourcePrefetcherFinished(). In the | |
| 350 // test, ResourcePrefetcherFinished() is a mock function and does not handle | |
| 351 // the raw pointer properly. In the real code, requests_ptr will eventually be | |
| 352 // passed to and managed by ResourcePrefetchPredictor::Result::Result. | |
| 353 delete requests_ptr; | |
| 354 } | 275 } |
| 355 | 276 |
| 356 } // namespace predictors | 277 } // namespace predictors |
| OLD | NEW |