Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / predictors / resource_prefetcher_unittest.cc
blob73098fa5fc6d7190a53c0865d39c556d6dd11175
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
3 // found in the LICENSE file.
5 #include "base/memory/ref_counted.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/message_loop/message_loop.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/base/load_flags.h"
13 #include "net/url_request/redirect_info.h"
14 #include "net/url_request/url_request.h"
15 #include "net/url_request/url_request_test_util.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using testing::Eq;
20 using testing::Property;
22 namespace predictors {
24 // Wrapper over the ResourcePrefetcher that stubs out the StartURLRequest call
25 // since we do not want to do network fetches in this unittest.
26 class TestResourcePrefetcher : public ResourcePrefetcher {
27 public:
28 TestResourcePrefetcher(ResourcePrefetcher::Delegate* delegate,
29 const ResourcePrefetchPredictorConfig& config,
30 const NavigationID& navigation_id,
31 PrefetchKeyType key_type,
32 scoped_ptr<RequestVector> requests)
33 : ResourcePrefetcher(delegate, config, navigation_id,
34 key_type, requests.Pass()) { }
36 ~TestResourcePrefetcher() override {}
38 MOCK_METHOD1(StartURLRequest, void(net::URLRequest* request));
40 void ReadFullResponse(net::URLRequest* request) override {
41 EXPECT_TRUE(request->load_flags() & net::LOAD_PREFETCH);
42 FinishRequest(request, Request::PREFETCH_STATUS_FROM_CACHE);
45 private:
46 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcher);
50 // Delegate for ResourcePrefetcher.
51 class TestResourcePrefetcherDelegate : public ResourcePrefetcher::Delegate {
52 public:
53 explicit TestResourcePrefetcherDelegate(base::MessageLoop* loop)
54 : request_context_getter_(
55 new net::TestURLRequestContextGetter(loop->task_runner())) {}
56 ~TestResourcePrefetcherDelegate() { }
58 net::URLRequestContext* GetURLRequestContext() override {
59 return request_context_getter_->GetURLRequestContext();
62 MOCK_METHOD2(ResourcePrefetcherFinished,
63 void(ResourcePrefetcher* prefetcher,
64 ResourcePrefetcher::RequestVector* requests));
66 private:
67 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
69 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcherDelegate);
73 // The following unittest tests most of the ResourcePrefetcher except for:
74 // 1. Call to ReadFullResponse. There does not seem to be a good way to test the
75 // function in a unittest, and probably requires a browser_test.
76 // 2. Setting of the Prefetch status for cache vs non cache.
77 class ResourcePrefetcherTest : public testing::Test {
78 public:
79 ResourcePrefetcherTest();
80 ~ResourcePrefetcherTest() override;
82 protected:
83 typedef ResourcePrefetcher::Request Request;
85 void AddStartUrlRequestExpectation(const std::string& url) {
86 EXPECT_CALL(*prefetcher_,
87 StartURLRequest(Property(&net::URLRequest::original_url,
88 Eq(GURL(url)))));
91 void CheckPrefetcherState(size_t inflight, size_t queue, size_t host) {
92 EXPECT_EQ(prefetcher_->inflight_requests_.size(), inflight);
93 EXPECT_EQ(prefetcher_->request_queue_.size(), queue);
94 EXPECT_EQ(prefetcher_->host_inflight_counts_.size(), host);
97 net::URLRequest* GetInFlightRequest(const std::string& url_str) {
98 GURL url(url_str);
100 for (std::list<Request*>::const_iterator it =
101 prefetcher_->request_queue_.begin();
102 it != prefetcher_->request_queue_.end(); ++it) {
103 EXPECT_NE((*it)->resource_url, url);
105 for (std::map<net::URLRequest*, Request*>::const_iterator it =
106 prefetcher_->inflight_requests_.begin();
107 it != prefetcher_->inflight_requests_.end(); ++it) {
108 if (it->first->original_url() == url)
109 return it->first;
111 EXPECT_TRUE(false) << "Infligh request not found: " << url_str;
112 return NULL;
116 void OnReceivedRedirect(const std::string& url) {
117 prefetcher_->OnReceivedRedirect(
118 GetInFlightRequest(url), net::RedirectInfo(), NULL);
120 void OnAuthRequired(const std::string& url) {
121 prefetcher_->OnAuthRequired(GetInFlightRequest(url), NULL);
123 void OnCertificateRequested(const std::string& url) {
124 prefetcher_->OnCertificateRequested(GetInFlightRequest(url), NULL);
126 void OnSSLCertificateError(const std::string& url) {
127 prefetcher_->OnSSLCertificateError(GetInFlightRequest(url),
128 net::SSLInfo(), false);
130 void OnResponse(const std::string& url) {
131 prefetcher_->OnResponseStarted(GetInFlightRequest(url));
134 base::MessageLoop loop_;
135 content::TestBrowserThread io_thread_;
136 ResourcePrefetchPredictorConfig config_;
137 TestResourcePrefetcherDelegate prefetcher_delegate_;
138 scoped_ptr<TestResourcePrefetcher> prefetcher_;
140 private:
141 DISALLOW_COPY_AND_ASSIGN(ResourcePrefetcherTest);
144 ResourcePrefetcherTest::ResourcePrefetcherTest()
145 : loop_(base::MessageLoop::TYPE_IO),
146 io_thread_(content::BrowserThread::IO, &loop_),
147 prefetcher_delegate_(&loop_) {
148 config_.max_prefetches_inflight_per_navigation = 5;
149 config_.max_prefetches_inflight_per_host_per_navigation = 2;
152 ResourcePrefetcherTest::~ResourcePrefetcherTest() {
155 TEST_F(ResourcePrefetcherTest, TestPrefetcherFinishes) {
156 scoped_ptr<ResourcePrefetcher::RequestVector> requests(
157 new ResourcePrefetcher::RequestVector);
158 requests->push_back(new ResourcePrefetcher::Request(GURL(
159 "http://www.google.com/resource1.html")));
160 requests->push_back(new ResourcePrefetcher::Request(GURL(
161 "http://www.google.com/resource2.png")));
162 requests->push_back(new ResourcePrefetcher::Request(GURL(
163 "http://yahoo.com/resource1.png")));
164 requests->push_back(new ResourcePrefetcher::Request(GURL(
165 "http://yahoo.com/resource2.png")));
166 requests->push_back(new ResourcePrefetcher::Request(GURL(
167 "http://yahoo.com/resource3.png")));
168 requests->push_back(new ResourcePrefetcher::Request(GURL(
169 "http://m.google.com/resource1.jpg")));
170 requests->push_back(new ResourcePrefetcher::Request(GURL(
171 "http://www.google.com/resource3.html")));
172 requests->push_back(new ResourcePrefetcher::Request(GURL(
173 "http://m.google.com/resource2.html")));
174 requests->push_back(new ResourcePrefetcher::Request(GURL(
175 "http://m.google.com/resource3.css")));
176 requests->push_back(new ResourcePrefetcher::Request(GURL(
177 "http://m.google.com/resource4.png")));
178 requests->push_back(new ResourcePrefetcher::Request(GURL(
179 "http://yahoo.com/resource4.png")));
180 requests->push_back(new ResourcePrefetcher::Request(GURL(
181 "http://yahoo.com/resource5.png")));
183 NavigationID navigation_id;
184 navigation_id.render_process_id = 1;
185 navigation_id.render_frame_id = 2;
186 navigation_id.main_frame_url = GURL("http://www.google.com");
188 // Needed later for comparison.
189 ResourcePrefetcher::RequestVector* requests_ptr = requests.get();
191 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_,
192 config_,
193 navigation_id,
194 PREFETCH_KEY_TYPE_URL,
195 requests.Pass()));
197 // Starting the prefetcher maxes out the number of possible requests.
198 AddStartUrlRequestExpectation("http://www.google.com/resource1.html");
199 AddStartUrlRequestExpectation("http://www.google.com/resource2.png");
200 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png");
201 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png");
202 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg");
204 prefetcher_->Start();
205 CheckPrefetcherState(5, 7, 3);
207 AddStartUrlRequestExpectation("http://m.google.com/resource2.html");
208 OnResponse("http://m.google.com/resource1.jpg");
209 CheckPrefetcherState(5, 6, 3);
211 AddStartUrlRequestExpectation("http://www.google.com/resource3.html");
212 OnSSLCertificateError("http://www.google.com/resource1.html");
213 CheckPrefetcherState(5, 5, 3);
215 AddStartUrlRequestExpectation("http://m.google.com/resource3.css");
216 OnResponse("http://m.google.com/resource2.html");
217 CheckPrefetcherState(5, 4, 3);
219 AddStartUrlRequestExpectation("http://m.google.com/resource4.png");
220 OnReceivedRedirect("http://www.google.com/resource3.html");
221 CheckPrefetcherState(5, 3, 3);
223 OnResponse("http://www.google.com/resource2.png");
224 CheckPrefetcherState(4, 3, 2);
226 AddStartUrlRequestExpectation("http://yahoo.com/resource3.png");
227 OnReceivedRedirect("http://yahoo.com/resource2.png");
228 CheckPrefetcherState(4, 2, 2);
230 AddStartUrlRequestExpectation("http://yahoo.com/resource4.png");
231 OnResponse("http://yahoo.com/resource1.png");
232 CheckPrefetcherState(4, 1, 2);
234 AddStartUrlRequestExpectation("http://yahoo.com/resource5.png");
235 OnResponse("http://yahoo.com/resource4.png");
236 CheckPrefetcherState(4, 0, 2);
238 OnResponse("http://yahoo.com/resource5.png");
239 CheckPrefetcherState(3, 0, 2);
241 OnCertificateRequested("http://m.google.com/resource4.png");
242 CheckPrefetcherState(2, 0, 2);
244 OnAuthRequired("http://m.google.com/resource3.css");
245 CheckPrefetcherState(1, 0, 1);
247 // Expect the final call.
248 EXPECT_CALL(prefetcher_delegate_,
249 ResourcePrefetcherFinished(Eq(prefetcher_.get()),
250 Eq(requests_ptr)));
252 OnResponse("http://yahoo.com/resource3.png");
253 CheckPrefetcherState(0, 0, 0);
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);
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;
290 TEST_F(ResourcePrefetcherTest, TestPrefetcherStopped) {
291 scoped_ptr<ResourcePrefetcher::RequestVector> requests(
292 new ResourcePrefetcher::RequestVector);
293 requests->push_back(new ResourcePrefetcher::Request(GURL(
294 "http://www.google.com/resource1.html")));
295 requests->push_back(new ResourcePrefetcher::Request(GURL(
296 "http://www.google.com/resource2.png")));
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")));
306 NavigationID navigation_id;
307 navigation_id.render_process_id = 1;
308 navigation_id.render_frame_id = 2;
309 navigation_id.main_frame_url = GURL("http://www.google.com");
311 // Needed later for comparison.
312 ResourcePrefetcher::RequestVector* requests_ptr = requests.get();
314 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_,
315 config_,
316 navigation_id,
317 PREFETCH_KEY_TYPE_HOST,
318 requests.Pass()));
320 // Starting the prefetcher maxes out the number of possible requests.
321 AddStartUrlRequestExpectation("http://www.google.com/resource1.html");
322 AddStartUrlRequestExpectation("http://www.google.com/resource2.png");
323 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png");
324 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png");
325 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg");
327 prefetcher_->Start();
328 CheckPrefetcherState(5, 1, 3);
330 OnResponse("http://www.google.com/resource1.html");
331 CheckPrefetcherState(4, 1, 3);
333 prefetcher_->Stop(); // No more queueing.
335 OnResponse("http://www.google.com/resource2.png");
336 CheckPrefetcherState(3, 1, 2);
338 OnResponse("http://yahoo.com/resource1.png");
339 CheckPrefetcherState(2, 1, 2);
341 OnResponse("http://yahoo.com/resource2.png");
342 CheckPrefetcherState(1, 1, 1);
344 // Expect the final call.
345 EXPECT_CALL(prefetcher_delegate_,
346 ResourcePrefetcherFinished(Eq(prefetcher_.get()),
347 Eq(requests_ptr)));
349 OnResponse("http://m.google.com/resource1.jpg");
350 CheckPrefetcherState(0, 1, 0);
352 // We need to delete requests_ptr here, though it looks to be managed by the
353 // scoped_ptr requests. The scoped_ptr requests releases itself and the raw
354 // pointer requests_ptr is passed to ResourcePrefetcherFinished(). In the
355 // test, ResourcePrefetcherFinished() is a mock function and does not handle
356 // the raw pointer properly. In the real code, requests_ptr will eventually be
357 // passed to and managed by ResourcePrefetchPredictor::Result::Result.
358 delete requests_ptr;
361 } // namespace predictors