OLD | NEW |
| (Empty) |
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. | |
4 | |
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" | |
17 | |
18 using testing::Eq; | |
19 using testing::Property; | |
20 | |
21 namespace predictors { | |
22 | |
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()) { } | |
34 | |
35 virtual ~TestResourcePrefetcher() { } | |
36 | |
37 MOCK_METHOD1(StartURLRequest, void(net::URLRequest* request)); | |
38 | |
39 void ReadFullResponse(net::URLRequest* request) OVERRIDE { | |
40 FinishRequest(request, Request::PREFETCH_STATUS_FROM_CACHE); | |
41 } | |
42 | |
43 private: | |
44 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcher); | |
45 }; | |
46 | |
47 | |
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() { } | |
55 | |
56 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE { | |
57 return request_context_getter_->GetURLRequestContext(); | |
58 } | |
59 | |
60 MOCK_METHOD2(ResourcePrefetcherFinished, | |
61 void(ResourcePrefetcher* prefetcher, | |
62 ResourcePrefetcher::RequestVector* requests)); | |
63 | |
64 private: | |
65 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; | |
66 | |
67 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcherDelegate); | |
68 }; | |
69 | |
70 | |
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 virtual ~ResourcePrefetcherTest(); | |
79 | |
80 protected: | |
81 typedef ResourcePrefetcher::Request Request; | |
82 | |
83 void AddStartUrlRequestExpectation(const std::string& url) { | |
84 EXPECT_CALL(*prefetcher_, | |
85 StartURLRequest(Property(&net::URLRequest::original_url, | |
86 Eq(GURL(url))))); | |
87 } | |
88 | |
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); | |
93 } | |
94 | |
95 net::URLRequest* GetInFlightRequest(const std::string& url_str) { | |
96 GURL url(url_str); | |
97 | |
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); | |
102 } | |
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; | |
108 } | |
109 EXPECT_TRUE(false) << "Infligh request not found: " << url_str; | |
110 return NULL; | |
111 } | |
112 | |
113 | |
114 void OnReceivedRedirect(const std::string& url) { | |
115 prefetcher_->OnReceivedRedirect( | |
116 GetInFlightRequest(url), net::RedirectInfo(), NULL); | |
117 } | |
118 void OnAuthRequired(const std::string& url) { | |
119 prefetcher_->OnAuthRequired(GetInFlightRequest(url), NULL); | |
120 } | |
121 void OnCertificateRequested(const std::string& url) { | |
122 prefetcher_->OnCertificateRequested(GetInFlightRequest(url), NULL); | |
123 } | |
124 void OnSSLCertificateError(const std::string& url) { | |
125 prefetcher_->OnSSLCertificateError(GetInFlightRequest(url), | |
126 net::SSLInfo(), false); | |
127 } | |
128 void OnResponse(const std::string& url) { | |
129 prefetcher_->OnResponseStarted(GetInFlightRequest(url)); | |
130 } | |
131 | |
132 base::MessageLoop loop_; | |
133 content::TestBrowserThread io_thread_; | |
134 ResourcePrefetchPredictorConfig config_; | |
135 TestResourcePrefetcherDelegate prefetcher_delegate_; | |
136 scoped_ptr<TestResourcePrefetcher> prefetcher_; | |
137 | |
138 private: | |
139 DISALLOW_COPY_AND_ASSIGN(ResourcePrefetcherTest); | |
140 }; | |
141 | |
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; | |
148 } | |
149 | |
150 ResourcePrefetcherTest::~ResourcePrefetcherTest() { | |
151 } | |
152 | |
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"))); | |
180 | |
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"); | |
185 | |
186 // Needed later for comparison. | |
187 ResourcePrefetcher::RequestVector* requests_ptr = requests.get(); | |
188 | |
189 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_, | |
190 config_, | |
191 navigation_id, | |
192 PREFETCH_KEY_TYPE_URL, | |
193 requests.Pass())); | |
194 | |
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"); | |
201 | |
202 prefetcher_->Start(); | |
203 CheckPrefetcherState(5, 7, 3); | |
204 | |
205 AddStartUrlRequestExpectation("http://m.google.com/resource2.html"); | |
206 OnResponse("http://m.google.com/resource1.jpg"); | |
207 CheckPrefetcherState(5, 6, 3); | |
208 | |
209 AddStartUrlRequestExpectation("http://www.google.com/resource3.html"); | |
210 OnSSLCertificateError("http://www.google.com/resource1.html"); | |
211 CheckPrefetcherState(5, 5, 3); | |
212 | |
213 AddStartUrlRequestExpectation("http://m.google.com/resource3.css"); | |
214 OnResponse("http://m.google.com/resource2.html"); | |
215 CheckPrefetcherState(5, 4, 3); | |
216 | |
217 AddStartUrlRequestExpectation("http://m.google.com/resource4.png"); | |
218 OnReceivedRedirect("http://www.google.com/resource3.html"); | |
219 CheckPrefetcherState(5, 3, 3); | |
220 | |
221 OnResponse("http://www.google.com/resource2.png"); | |
222 CheckPrefetcherState(4, 3, 2); | |
223 | |
224 AddStartUrlRequestExpectation("http://yahoo.com/resource3.png"); | |
225 OnReceivedRedirect("http://yahoo.com/resource2.png"); | |
226 CheckPrefetcherState(4, 2, 2); | |
227 | |
228 AddStartUrlRequestExpectation("http://yahoo.com/resource4.png"); | |
229 OnResponse("http://yahoo.com/resource1.png"); | |
230 CheckPrefetcherState(4, 1, 2); | |
231 | |
232 AddStartUrlRequestExpectation("http://yahoo.com/resource5.png"); | |
233 OnResponse("http://yahoo.com/resource4.png"); | |
234 CheckPrefetcherState(4, 0, 2); | |
235 | |
236 OnResponse("http://yahoo.com/resource5.png"); | |
237 CheckPrefetcherState(3, 0, 2); | |
238 | |
239 OnCertificateRequested("http://m.google.com/resource4.png"); | |
240 CheckPrefetcherState(2, 0, 2); | |
241 | |
242 OnAuthRequired("http://m.google.com/resource3.css"); | |
243 CheckPrefetcherState(1, 0, 1); | |
244 | |
245 // Expect the final call. | |
246 EXPECT_CALL(prefetcher_delegate_, | |
247 ResourcePrefetcherFinished(Eq(prefetcher_.get()), | |
248 Eq(requests_ptr))); | |
249 | |
250 OnResponse("http://yahoo.com/resource3.png"); | |
251 CheckPrefetcherState(0, 0, 0); | |
252 | |
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); | |
278 } | |
279 | |
280 TEST_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_frame_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 | |
343 } // namespace predictors | |
OLD | NEW |