Fix sorting issues in chrome_browser.gypi restructuring
[chromium-blink-merge.git] / chrome / browser / predictors / resource_prefetcher_unittest.cc
bloba2bd443b5047e49c50786e186f6a90da9c5b1056
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/url_request/redirect_info.h"
13 #include "net/url_request/url_request.h"
14 #include "net/url_request/url_request_test_util.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 using testing::Eq;
19 using testing::Property;
21 namespace predictors {
23 // Wrapper over the ResourcePrefetcher that stubs out the StartURLRequest call
24 // since we do not want to do network fetches in this unittest.
25 class TestResourcePrefetcher : public ResourcePrefetcher {
26 public:
27 TestResourcePrefetcher(ResourcePrefetcher::Delegate* delegate,
28 const ResourcePrefetchPredictorConfig& config,
29 const NavigationID& navigation_id,
30 PrefetchKeyType key_type,
31 scoped_ptr<RequestVector> requests)
32 : ResourcePrefetcher(delegate, config, navigation_id,
33 key_type, requests.Pass()) { }
35 virtual ~TestResourcePrefetcher() { }
37 MOCK_METHOD1(StartURLRequest, void(net::URLRequest* request));
39 void ReadFullResponse(net::URLRequest* request) override {
40 FinishRequest(request, Request::PREFETCH_STATUS_FROM_CACHE);
43 private:
44 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcher);
48 // Delegate for ResourcePrefetcher.
49 class TestResourcePrefetcherDelegate : public ResourcePrefetcher::Delegate {
50 public:
51 explicit TestResourcePrefetcherDelegate(base::MessageLoop* loop)
52 : request_context_getter_(new net::TestURLRequestContextGetter(
53 loop->message_loop_proxy())) { }
54 ~TestResourcePrefetcherDelegate() { }
56 virtual net::URLRequestContext* GetURLRequestContext() override {
57 return request_context_getter_->GetURLRequestContext();
60 MOCK_METHOD2(ResourcePrefetcherFinished,
61 void(ResourcePrefetcher* prefetcher,
62 ResourcePrefetcher::RequestVector* requests));
64 private:
65 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
67 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcherDelegate);
71 // The following unittest tests most of the ResourcePrefetcher except for:
72 // 1. Call to ReadFullResponse. There does not seem to be a good way to test the
73 // function in a unittest, and probably requires a browser_test.
74 // 2. Setting of the Prefetch status for cache vs non cache.
75 class ResourcePrefetcherTest : public testing::Test {
76 public:
77 ResourcePrefetcherTest();
78 ~ResourcePrefetcherTest() override;
80 protected:
81 typedef ResourcePrefetcher::Request Request;
83 void AddStartUrlRequestExpectation(const std::string& url) {
84 EXPECT_CALL(*prefetcher_,
85 StartURLRequest(Property(&net::URLRequest::original_url,
86 Eq(GURL(url)))));
89 void CheckPrefetcherState(size_t inflight, size_t queue, size_t host) {
90 EXPECT_EQ(prefetcher_->inflight_requests_.size(), inflight);
91 EXPECT_EQ(prefetcher_->request_queue_.size(), queue);
92 EXPECT_EQ(prefetcher_->host_inflight_counts_.size(), host);
95 net::URLRequest* GetInFlightRequest(const std::string& url_str) {
96 GURL url(url_str);
98 for (std::list<Request*>::const_iterator it =
99 prefetcher_->request_queue_.begin();
100 it != prefetcher_->request_queue_.end(); ++it) {
101 EXPECT_NE((*it)->resource_url, url);
103 for (std::map<net::URLRequest*, Request*>::const_iterator it =
104 prefetcher_->inflight_requests_.begin();
105 it != prefetcher_->inflight_requests_.end(); ++it) {
106 if (it->first->original_url() == url)
107 return it->first;
109 EXPECT_TRUE(false) << "Infligh request not found: " << url_str;
110 return NULL;
114 void OnReceivedRedirect(const std::string& url) {
115 prefetcher_->OnReceivedRedirect(
116 GetInFlightRequest(url), net::RedirectInfo(), NULL);
118 void OnAuthRequired(const std::string& url) {
119 prefetcher_->OnAuthRequired(GetInFlightRequest(url), NULL);
121 void OnCertificateRequested(const std::string& url) {
122 prefetcher_->OnCertificateRequested(GetInFlightRequest(url), NULL);
124 void OnSSLCertificateError(const std::string& url) {
125 prefetcher_->OnSSLCertificateError(GetInFlightRequest(url),
126 net::SSLInfo(), false);
128 void OnResponse(const std::string& url) {
129 prefetcher_->OnResponseStarted(GetInFlightRequest(url));
132 base::MessageLoop loop_;
133 content::TestBrowserThread io_thread_;
134 ResourcePrefetchPredictorConfig config_;
135 TestResourcePrefetcherDelegate prefetcher_delegate_;
136 scoped_ptr<TestResourcePrefetcher> prefetcher_;
138 private:
139 DISALLOW_COPY_AND_ASSIGN(ResourcePrefetcherTest);
142 ResourcePrefetcherTest::ResourcePrefetcherTest()
143 : loop_(base::MessageLoop::TYPE_IO),
144 io_thread_(content::BrowserThread::IO, &loop_),
145 prefetcher_delegate_(&loop_) {
146 config_.max_prefetches_inflight_per_navigation = 5;
147 config_.max_prefetches_inflight_per_host_per_navigation = 2;
150 ResourcePrefetcherTest::~ResourcePrefetcherTest() {
153 TEST_F(ResourcePrefetcherTest, TestPrefetcherFinishes) {
154 scoped_ptr<ResourcePrefetcher::RequestVector> requests(
155 new ResourcePrefetcher::RequestVector);
156 requests->push_back(new ResourcePrefetcher::Request(GURL(
157 "http://www.google.com/resource1.html")));
158 requests->push_back(new ResourcePrefetcher::Request(GURL(
159 "http://www.google.com/resource2.png")));
160 requests->push_back(new ResourcePrefetcher::Request(GURL(
161 "http://yahoo.com/resource1.png")));
162 requests->push_back(new ResourcePrefetcher::Request(GURL(
163 "http://yahoo.com/resource2.png")));
164 requests->push_back(new ResourcePrefetcher::Request(GURL(
165 "http://yahoo.com/resource3.png")));
166 requests->push_back(new ResourcePrefetcher::Request(GURL(
167 "http://m.google.com/resource1.jpg")));
168 requests->push_back(new ResourcePrefetcher::Request(GURL(
169 "http://www.google.com/resource3.html")));
170 requests->push_back(new ResourcePrefetcher::Request(GURL(
171 "http://m.google.com/resource2.html")));
172 requests->push_back(new ResourcePrefetcher::Request(GURL(
173 "http://m.google.com/resource3.css")));
174 requests->push_back(new ResourcePrefetcher::Request(GURL(
175 "http://m.google.com/resource4.png")));
176 requests->push_back(new ResourcePrefetcher::Request(GURL(
177 "http://yahoo.com/resource4.png")));
178 requests->push_back(new ResourcePrefetcher::Request(GURL(
179 "http://yahoo.com/resource5.png")));
181 NavigationID navigation_id;
182 navigation_id.render_process_id = 1;
183 navigation_id.render_frame_id = 2;
184 navigation_id.main_frame_url = GURL("http://www.google.com");
186 // Needed later for comparison.
187 ResourcePrefetcher::RequestVector* requests_ptr = requests.get();
189 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_,
190 config_,
191 navigation_id,
192 PREFETCH_KEY_TYPE_URL,
193 requests.Pass()));
195 // Starting the prefetcher maxes out the number of possible requests.
196 AddStartUrlRequestExpectation("http://www.google.com/resource1.html");
197 AddStartUrlRequestExpectation("http://www.google.com/resource2.png");
198 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png");
199 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png");
200 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg");
202 prefetcher_->Start();
203 CheckPrefetcherState(5, 7, 3);
205 AddStartUrlRequestExpectation("http://m.google.com/resource2.html");
206 OnResponse("http://m.google.com/resource1.jpg");
207 CheckPrefetcherState(5, 6, 3);
209 AddStartUrlRequestExpectation("http://www.google.com/resource3.html");
210 OnSSLCertificateError("http://www.google.com/resource1.html");
211 CheckPrefetcherState(5, 5, 3);
213 AddStartUrlRequestExpectation("http://m.google.com/resource3.css");
214 OnResponse("http://m.google.com/resource2.html");
215 CheckPrefetcherState(5, 4, 3);
217 AddStartUrlRequestExpectation("http://m.google.com/resource4.png");
218 OnReceivedRedirect("http://www.google.com/resource3.html");
219 CheckPrefetcherState(5, 3, 3);
221 OnResponse("http://www.google.com/resource2.png");
222 CheckPrefetcherState(4, 3, 2);
224 AddStartUrlRequestExpectation("http://yahoo.com/resource3.png");
225 OnReceivedRedirect("http://yahoo.com/resource2.png");
226 CheckPrefetcherState(4, 2, 2);
228 AddStartUrlRequestExpectation("http://yahoo.com/resource4.png");
229 OnResponse("http://yahoo.com/resource1.png");
230 CheckPrefetcherState(4, 1, 2);
232 AddStartUrlRequestExpectation("http://yahoo.com/resource5.png");
233 OnResponse("http://yahoo.com/resource4.png");
234 CheckPrefetcherState(4, 0, 2);
236 OnResponse("http://yahoo.com/resource5.png");
237 CheckPrefetcherState(3, 0, 2);
239 OnCertificateRequested("http://m.google.com/resource4.png");
240 CheckPrefetcherState(2, 0, 2);
242 OnAuthRequired("http://m.google.com/resource3.css");
243 CheckPrefetcherState(1, 0, 1);
245 // Expect the final call.
246 EXPECT_CALL(prefetcher_delegate_,
247 ResourcePrefetcherFinished(Eq(prefetcher_.get()),
248 Eq(requests_ptr)));
250 OnResponse("http://yahoo.com/resource3.png");
251 CheckPrefetcherState(0, 0, 0);
253 // Check the prefetch status.
254 EXPECT_EQ(Request::PREFETCH_STATUS_CERT_ERROR,
255 (*requests_ptr)[0]->prefetch_status);
256 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE,
257 (*requests_ptr)[1]->prefetch_status);
258 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE,
259 (*requests_ptr)[2]->prefetch_status);
260 EXPECT_EQ(Request::PREFETCH_STATUS_REDIRECTED,
261 (*requests_ptr)[3]->prefetch_status);
262 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE,
263 (*requests_ptr)[4]->prefetch_status);
264 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE,
265 (*requests_ptr)[5]->prefetch_status);
266 EXPECT_EQ(Request::PREFETCH_STATUS_REDIRECTED,
267 (*requests_ptr)[6]->prefetch_status);
268 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE,
269 (*requests_ptr)[7]->prefetch_status);
270 EXPECT_EQ(Request::PREFETCH_STATUS_AUTH_REQUIRED,
271 (*requests_ptr)[8]->prefetch_status);
272 EXPECT_EQ(Request::PREFETCH_STATUS_CERT_REQUIRED,
273 (*requests_ptr)[9]->prefetch_status);
274 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE,
275 (*requests_ptr)[10]->prefetch_status);
276 EXPECT_EQ(Request::PREFETCH_STATUS_FROM_CACHE,
277 (*requests_ptr)[11]->prefetch_status);
279 // We need to delete requests_ptr here, though it looks to be managed by the
280 // scoped_ptr requests. The scoped_ptr requests releases itself and the raw
281 // pointer requests_ptr is passed to ResourcePrefetcherFinished(). In the
282 // test, ResourcePrefetcherFinished() is a mock function and does not handle
283 // the raw pointer properly. In the real code, requests_ptr will eventually be
284 // passed to and managed by ResourcePrefetchPredictor::Result::Result.
285 delete requests_ptr;
288 TEST_F(ResourcePrefetcherTest, TestPrefetcherStopped) {
289 scoped_ptr<ResourcePrefetcher::RequestVector> requests(
290 new ResourcePrefetcher::RequestVector);
291 requests->push_back(new ResourcePrefetcher::Request(GURL(
292 "http://www.google.com/resource1.html")));
293 requests->push_back(new ResourcePrefetcher::Request(GURL(
294 "http://www.google.com/resource2.png")));
295 requests->push_back(new ResourcePrefetcher::Request(GURL(
296 "http://yahoo.com/resource1.png")));
297 requests->push_back(new ResourcePrefetcher::Request(GURL(
298 "http://yahoo.com/resource2.png")));
299 requests->push_back(new ResourcePrefetcher::Request(GURL(
300 "http://yahoo.com/resource3.png")));
301 requests->push_back(new ResourcePrefetcher::Request(GURL(
302 "http://m.google.com/resource1.jpg")));
304 NavigationID navigation_id;
305 navigation_id.render_process_id = 1;
306 navigation_id.render_frame_id = 2;
307 navigation_id.main_frame_url = GURL("http://www.google.com");
309 // Needed later for comparison.
310 ResourcePrefetcher::RequestVector* requests_ptr = requests.get();
312 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_,
313 config_,
314 navigation_id,
315 PREFETCH_KEY_TYPE_HOST,
316 requests.Pass()));
318 // Starting the prefetcher maxes out the number of possible requests.
319 AddStartUrlRequestExpectation("http://www.google.com/resource1.html");
320 AddStartUrlRequestExpectation("http://www.google.com/resource2.png");
321 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png");
322 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png");
323 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg");
325 prefetcher_->Start();
326 CheckPrefetcherState(5, 1, 3);
328 OnResponse("http://www.google.com/resource1.html");
329 CheckPrefetcherState(4, 1, 3);
331 prefetcher_->Stop(); // No more queueing.
333 OnResponse("http://www.google.com/resource2.png");
334 CheckPrefetcherState(3, 1, 2);
336 OnResponse("http://yahoo.com/resource1.png");
337 CheckPrefetcherState(2, 1, 2);
339 OnResponse("http://yahoo.com/resource2.png");
340 CheckPrefetcherState(1, 1, 1);
342 // Expect the final call.
343 EXPECT_CALL(prefetcher_delegate_,
344 ResourcePrefetcherFinished(Eq(prefetcher_.get()),
345 Eq(requests_ptr)));
347 OnResponse("http://m.google.com/resource1.jpg");
348 CheckPrefetcherState(0, 1, 0);
350 // We need to delete requests_ptr here, though it looks to be managed by the
351 // scoped_ptr requests. The scoped_ptr requests releases itself and the raw
352 // pointer requests_ptr is passed to ResourcePrefetcherFinished(). In the
353 // test, ResourcePrefetcherFinished() is a mock function and does not handle
354 // the raw pointer properly. In the real code, requests_ptr will eventually be
355 // passed to and managed by ResourcePrefetchPredictor::Result::Result.
356 delete requests_ptr;
359 } // namespace predictors