OLD | NEW |
| (Empty) |
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/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/url_request.h" | |
13 #include "net/url_request/url_request_test_util.h" | |
14 #include "testing/gmock/include/gmock/gmock.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 | |
17 using testing::Eq; | |
18 using testing::Property; | |
19 | |
20 namespace 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. | |
24 class 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. | |
48 class TestResourcePrefetcherDelegate : public ResourcePrefetcher::Delegate { | |
49 public: | |
50 explicit TestResourcePrefetcherDelegate(base::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. | |
74 class 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( | |
115 GetInFlightRequest(url), GURL(std::string()), NULL); | |
116 } | |
117 void OnAuthRequired(const std::string& url) { | |
118 prefetcher_->OnAuthRequired(GetInFlightRequest(url), NULL); | |
119 } | |
120 void OnCertificateRequested(const std::string& url) { | |
121 prefetcher_->OnCertificateRequested(GetInFlightRequest(url), NULL); | |
122 } | |
123 void OnSSLCertificateError(const std::string& url) { | |
124 prefetcher_->OnSSLCertificateError(GetInFlightRequest(url), | |
125 net::SSLInfo(), false); | |
126 } | |
127 void OnResponse(const std::string& url) { | |
128 prefetcher_->OnResponseStarted(GetInFlightRequest(url)); | |
129 } | |
130 | |
131 base::MessageLoop loop_; | |
132 content::TestBrowserThread io_thread_; | |
133 ResourcePrefetchPredictorConfig config_; | |
134 TestResourcePrefetcherDelegate prefetcher_delegate_; | |
135 scoped_ptr<TestResourcePrefetcher> prefetcher_; | |
136 | |
137 private: | |
138 DISALLOW_COPY_AND_ASSIGN(ResourcePrefetcherTest); | |
139 }; | |
140 | |
141 ResourcePrefetcherTest::ResourcePrefetcherTest() | |
142 : loop_(base::MessageLoop::TYPE_IO), | |
143 io_thread_(content::BrowserThread::IO, &loop_), | |
144 prefetcher_delegate_(&loop_) { | |
145 config_.max_prefetches_inflight_per_navigation = 5; | |
146 config_.max_prefetches_inflight_per_host_per_navigation = 2; | |
147 } | |
148 | |
149 ResourcePrefetcherTest::~ResourcePrefetcherTest() { | |
150 } | |
151 | |
152 TEST_F(ResourcePrefetcherTest, TestPrefetcherFinishes) { | |
153 scoped_ptr<ResourcePrefetcher::RequestVector> requests( | |
154 new ResourcePrefetcher::RequestVector); | |
155 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
156 "http://www.google.com/resource1.html"))); | |
157 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
158 "http://www.google.com/resource2.png"))); | |
159 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
160 "http://yahoo.com/resource1.png"))); | |
161 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
162 "http://yahoo.com/resource2.png"))); | |
163 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
164 "http://yahoo.com/resource3.png"))); | |
165 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
166 "http://m.google.com/resource1.jpg"))); | |
167 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
168 "http://www.google.com/resource3.html"))); | |
169 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
170 "http://m.google.com/resource2.html"))); | |
171 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
172 "http://m.google.com/resource3.css"))); | |
173 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
174 "http://m.google.com/resource4.png"))); | |
175 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
176 "http://yahoo.com/resource4.png"))); | |
177 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
178 "http://yahoo.com/resource5.png"))); | |
179 | |
180 NavigationID navigation_id; | |
181 navigation_id.render_process_id = 1; | |
182 navigation_id.render_view_id = 2; | |
183 navigation_id.main_frame_url = GURL("http://www.google.com"); | |
184 | |
185 // Needed later for comparison. | |
186 ResourcePrefetcher::RequestVector* requests_ptr = requests.get(); | |
187 | |
188 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_, | |
189 config_, | |
190 navigation_id, | |
191 PREFETCH_KEY_TYPE_URL, | |
192 requests.Pass())); | |
193 | |
194 // Starting the prefetcher maxes out the number of possible requests. | |
195 AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); | |
196 AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); | |
197 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); | |
198 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); | |
199 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); | |
200 | |
201 prefetcher_->Start(); | |
202 CheckPrefetcherState(5, 7, 3); | |
203 | |
204 AddStartUrlRequestExpectation("http://m.google.com/resource2.html"); | |
205 OnResponse("http://m.google.com/resource1.jpg"); | |
206 CheckPrefetcherState(5, 6, 3); | |
207 | |
208 AddStartUrlRequestExpectation("http://www.google.com/resource3.html"); | |
209 OnSSLCertificateError("http://www.google.com/resource1.html"); | |
210 CheckPrefetcherState(5, 5, 3); | |
211 | |
212 AddStartUrlRequestExpectation("http://m.google.com/resource3.css"); | |
213 OnResponse("http://m.google.com/resource2.html"); | |
214 CheckPrefetcherState(5, 4, 3); | |
215 | |
216 AddStartUrlRequestExpectation("http://m.google.com/resource4.png"); | |
217 OnReceivedRedirect("http://www.google.com/resource3.html"); | |
218 CheckPrefetcherState(5, 3, 3); | |
219 | |
220 OnResponse("http://www.google.com/resource2.png"); | |
221 CheckPrefetcherState(4, 3, 2); | |
222 | |
223 AddStartUrlRequestExpectation("http://yahoo.com/resource3.png"); | |
224 OnReceivedRedirect("http://yahoo.com/resource2.png"); | |
225 CheckPrefetcherState(4, 2, 2); | |
226 | |
227 AddStartUrlRequestExpectation("http://yahoo.com/resource4.png"); | |
228 OnResponse("http://yahoo.com/resource1.png"); | |
229 CheckPrefetcherState(4, 1, 2); | |
230 | |
231 AddStartUrlRequestExpectation("http://yahoo.com/resource5.png"); | |
232 OnResponse("http://yahoo.com/resource4.png"); | |
233 CheckPrefetcherState(4, 0, 2); | |
234 | |
235 OnResponse("http://yahoo.com/resource5.png"); | |
236 CheckPrefetcherState(3, 0, 2); | |
237 | |
238 OnCertificateRequested("http://m.google.com/resource4.png"); | |
239 CheckPrefetcherState(2, 0, 2); | |
240 | |
241 OnAuthRequired("http://m.google.com/resource3.css"); | |
242 CheckPrefetcherState(1, 0, 1); | |
243 | |
244 // Expect the final call. | |
245 EXPECT_CALL(prefetcher_delegate_, | |
246 ResourcePrefetcherFinished(Eq(prefetcher_.get()), | |
247 Eq(requests_ptr))); | |
248 | |
249 OnResponse("http://yahoo.com/resource3.png"); | |
250 CheckPrefetcherState(0, 0, 0); | |
251 | |
252 // Check the prefetch status. | |
253 EXPECT_EQ((*requests_ptr)[0]->prefetch_status, | |
254 Request::PREFETCH_STATUS_CERT_ERROR); | |
255 EXPECT_EQ((*requests_ptr)[1]->prefetch_status, | |
256 Request::PREFETCH_STATUS_FROM_CACHE); | |
257 EXPECT_EQ((*requests_ptr)[2]->prefetch_status, | |
258 Request::PREFETCH_STATUS_FROM_CACHE); | |
259 EXPECT_EQ((*requests_ptr)[3]->prefetch_status, | |
260 Request::PREFETCH_STATUS_REDIRECTED); | |
261 EXPECT_EQ((*requests_ptr)[4]->prefetch_status, | |
262 Request::PREFETCH_STATUS_FROM_CACHE); | |
263 EXPECT_EQ((*requests_ptr)[5]->prefetch_status, | |
264 Request::PREFETCH_STATUS_FROM_CACHE); | |
265 EXPECT_EQ((*requests_ptr)[6]->prefetch_status, | |
266 Request::PREFETCH_STATUS_REDIRECTED); | |
267 EXPECT_EQ((*requests_ptr)[7]->prefetch_status, | |
268 Request::PREFETCH_STATUS_FROM_CACHE); | |
269 EXPECT_EQ((*requests_ptr)[8]->prefetch_status, | |
270 Request::PREFETCH_STATUS_AUTH_REQUIRED); | |
271 EXPECT_EQ((*requests_ptr)[9]->prefetch_status, | |
272 Request::PREFETCH_STATUS_CERT_REQUIRED); | |
273 EXPECT_EQ((*requests_ptr)[10]->prefetch_status, | |
274 Request::PREFETCH_STATUS_FROM_CACHE); | |
275 EXPECT_EQ((*requests_ptr)[11]->prefetch_status, | |
276 Request::PREFETCH_STATUS_FROM_CACHE); | |
277 | |
278 delete requests_ptr; | |
279 } | |
280 | |
281 TEST_F(ResourcePrefetcherTest, TestPrefetcherStopped) { | |
282 scoped_ptr<ResourcePrefetcher::RequestVector> requests( | |
283 new ResourcePrefetcher::RequestVector); | |
284 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
285 "http://www.google.com/resource1.html"))); | |
286 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
287 "http://www.google.com/resource2.png"))); | |
288 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
289 "http://yahoo.com/resource1.png"))); | |
290 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
291 "http://yahoo.com/resource2.png"))); | |
292 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
293 "http://yahoo.com/resource3.png"))); | |
294 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
295 "http://m.google.com/resource1.jpg"))); | |
296 | |
297 NavigationID navigation_id; | |
298 navigation_id.render_process_id = 1; | |
299 navigation_id.render_view_id = 2; | |
300 navigation_id.main_frame_url = GURL("http://www.google.com"); | |
301 | |
302 // Needed later for comparison. | |
303 ResourcePrefetcher::RequestVector* requests_ptr = requests.get(); | |
304 | |
305 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_, | |
306 config_, | |
307 navigation_id, | |
308 PREFETCH_KEY_TYPE_HOST, | |
309 requests.Pass())); | |
310 | |
311 // Starting the prefetcher maxes out the number of possible requests. | |
312 AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); | |
313 AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); | |
314 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); | |
315 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); | |
316 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); | |
317 | |
318 prefetcher_->Start(); | |
319 CheckPrefetcherState(5, 1, 3); | |
320 | |
321 OnResponse("http://www.google.com/resource1.html"); | |
322 CheckPrefetcherState(4, 1, 3); | |
323 | |
324 prefetcher_->Stop(); // No more queueing. | |
325 | |
326 OnResponse("http://www.google.com/resource2.png"); | |
327 CheckPrefetcherState(3, 1, 2); | |
328 | |
329 OnResponse("http://yahoo.com/resource1.png"); | |
330 CheckPrefetcherState(2, 1, 2); | |
331 | |
332 OnResponse("http://yahoo.com/resource2.png"); | |
333 CheckPrefetcherState(1, 1, 1); | |
334 | |
335 // Expect the final call. | |
336 EXPECT_CALL(prefetcher_delegate_, | |
337 ResourcePrefetcherFinished(Eq(prefetcher_.get()), | |
338 Eq(requests_ptr))); | |
339 | |
340 OnResponse("http://m.google.com/resource1.jpg"); | |
341 CheckPrefetcherState(0, 1, 0); | |
342 | |
343 delete requests_ptr; | |
344 } | |
345 | |
346 } // namespace predictors | |
OLD | NEW |