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/message_loop.h" | |
7 #include "base/memory/scoped_ptr.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/gtest/include/gtest/gtest.h" | |
15 #include "testing/gmock/include/gmock/gmock.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 scoped_ptr<RequestVector> requests) | |
30 : ResourcePrefetcher(delegate, config, navigation_id, requests.Pass()) { } | |
31 | |
32 virtual ~TestResourcePrefetcher() { } | |
33 | |
34 MOCK_METHOD1(StartURLRequest, void(net::URLRequest* request)); | |
35 | |
36 void ReadFullResponse(net::URLRequest* request) OVERRIDE { | |
37 FinishRequest(request, Request::PREFETCH_STATUS_FROM_CACHE); | |
38 } | |
39 | |
40 private: | |
41 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcher); | |
42 }; | |
43 | |
44 | |
45 // Delegate for ResourcePrefetcher. | |
46 class TestResourcePrefetcherDelegate : public ResourcePrefetcher::Delegate { | |
47 public: | |
48 explicit TestResourcePrefetcherDelegate(MessageLoop* loop) | |
49 : request_context_getter_(new TestURLRequestContextGetter( | |
50 loop->message_loop_proxy())) { } | |
51 ~TestResourcePrefetcherDelegate() { } | |
52 | |
53 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE { | |
54 return request_context_getter_->GetURLRequestContext(); | |
55 } | |
56 | |
57 MOCK_METHOD2(ResourcePrefetcherFinished, | |
58 void(ResourcePrefetcher* prefetcher, | |
59 ResourcePrefetcher::RequestVector* requests)); | |
60 | |
61 private: | |
62 TestURLRequestContextGetter* request_context_getter_; | |
63 | |
64 DISALLOW_COPY_AND_ASSIGN(TestResourcePrefetcherDelegate); | |
65 }; | |
66 | |
67 | |
68 // The following unittest tests most of the ResourcePrefetcher except for: | |
69 // 1. Call to ReadFullResponse. There does not seem to be a good way to test the | |
70 // function in a unittest, and probably requires a browser_test. | |
71 // 2. Setting of the Prefetch status for cache vs non cache. | |
72 class ResourcePrefetcherTest : public testing::Test { | |
73 public: | |
74 ResourcePrefetcherTest(); | |
75 ~ResourcePrefetcherTest(); | |
76 | |
77 protected: | |
78 typedef ResourcePrefetcher::Request Request; | |
79 | |
80 void AddStartUrlRequestExpectation(const std::string& url) { | |
81 EXPECT_CALL(*prefetcher_, | |
82 StartURLRequest(Property(&net::URLRequest::original_url, | |
83 Eq(GURL(url))))); | |
84 } | |
85 | |
86 void CheckPrefetcherState(size_t inflight, size_t queue, size_t host) { | |
87 EXPECT_EQ(prefetcher_->inflight_requests_.size(), inflight); | |
88 EXPECT_EQ(prefetcher_->request_queue_.size(), queue); | |
89 EXPECT_EQ(prefetcher_->host_inflight_counts_.size(), host); | |
90 } | |
91 | |
92 net::URLRequest* GetInFlightRequest(const std::string& url_str) { | |
93 GURL url(url_str); | |
94 | |
95 for (std::list<Request*>::const_iterator it = | |
96 prefetcher_->request_queue_.begin(); | |
97 it != prefetcher_->request_queue_.end(); ++it) { | |
98 EXPECT_NE((*it)->resource_url, url); | |
99 } | |
100 for (std::map<net::URLRequest*, Request*>::const_iterator it = | |
101 prefetcher_->inflight_requests_.begin(); | |
102 it != prefetcher_->inflight_requests_.end(); ++it) { | |
103 if (it->first->original_url() == url) | |
104 return it->first; | |
105 } | |
106 EXPECT_TRUE(false) << "Infligh request not found: " << url_str; | |
107 return NULL; | |
108 } | |
109 | |
110 | |
111 void OnReceivedRedirect(const std::string& url) { | |
112 prefetcher_->OnReceivedRedirect(GetInFlightRequest(url), GURL(""), NULL); | |
113 } | |
114 void OnAuthRequired(const std::string& url) { | |
115 prefetcher_->OnAuthRequired(GetInFlightRequest(url), NULL); | |
116 } | |
117 void OnCertificateRequested(const std::string& url) { | |
118 prefetcher_->OnCertificateRequested(GetInFlightRequest(url), NULL); | |
119 } | |
120 void OnSSLCertificateError(const std::string& url) { | |
121 prefetcher_->OnSSLCertificateError(GetInFlightRequest(url), | |
122 net::SSLInfo(), false); | |
123 } | |
124 void OnResponse(const std::string& url) { | |
125 prefetcher_->OnResponseStarted(GetInFlightRequest(url)); | |
126 } | |
127 | |
128 MessageLoop loop_; | |
129 content::TestBrowserThread io_thread_; | |
130 ResourcePrefetchPredictorConfig config_; | |
131 TestResourcePrefetcherDelegate prefetcher_delegate_; | |
132 scoped_ptr<TestResourcePrefetcher> prefetcher_; | |
133 | |
134 private: | |
135 DISALLOW_COPY_AND_ASSIGN(ResourcePrefetcherTest); | |
136 }; | |
137 | |
138 ResourcePrefetcherTest::ResourcePrefetcherTest() | |
139 : loop_(MessageLoop::TYPE_IO), | |
140 io_thread_(content::BrowserThread::IO, &loop_), | |
141 prefetcher_delegate_(&loop_) { | |
142 config_.max_prefetches_inflight_per_navigation = 5; | |
143 config_.max_prefetches_inflight_per_host_per_navigation = 2; | |
144 } | |
145 | |
146 ResourcePrefetcherTest::~ResourcePrefetcherTest() { | |
147 } | |
148 | |
149 TEST_F(ResourcePrefetcherTest, TestPrefetcherFinishes) { | |
dominich
2012/09/11 17:40:11
there's quite a bit of repeated code here. In the
Shishir
2012/09/11 18:18:08
I could do that, but I the order of calls to AddSt
dominich
2012/09/11 18:40:43
Ah, I see. I could see a way to build this as a ma
Shishir
2012/09/11 19:36:31
The code looks repetitive because I have to check
| |
150 scoped_ptr<ResourcePrefetcher::RequestVector> requests( | |
151 new ResourcePrefetcher::RequestVector); | |
152 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
153 "http://www.google.com/resource1.html"))); | |
154 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
155 "http://www.google.com/resource2.png"))); | |
156 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
157 "http://yahoo.com/resource1.png"))); | |
158 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
159 "http://yahoo.com/resource2.png"))); | |
160 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
161 "http://yahoo.com/resource3.png"))); | |
162 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
163 "http://m.google.com/resource1.jpg"))); | |
164 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
165 "http://www.google.com/resource3.html"))); | |
166 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
167 "http://m.google.com/resource2.html"))); | |
168 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
169 "http://m.google.com/resource3.css"))); | |
170 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
171 "http://m.google.com/resource4.png"))); | |
172 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
173 "http://yahoo.com/resource4.png"))); | |
174 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
175 "http://yahoo.com/resource5.png"))); | |
176 | |
177 NavigationID navigation_id; | |
178 navigation_id.render_process_id = 1; | |
179 navigation_id.render_view_id = 2; | |
180 navigation_id.main_frame_url = GURL("http://www.google.com"); | |
181 | |
182 // Needed later for comparison. | |
183 ResourcePrefetcher::RequestVector* requests_ptr = requests.get(); | |
184 | |
185 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_, | |
186 config_, | |
187 navigation_id, | |
188 requests.Pass())); | |
189 | |
190 // Starting the prefetcher maxes out the number of possible requests. | |
191 AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); | |
192 AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); | |
193 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); | |
194 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); | |
195 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); | |
196 | |
197 prefetcher_->Start(); | |
198 CheckPrefetcherState(5, 7, 3); | |
199 | |
200 AddStartUrlRequestExpectation("http://m.google.com/resource2.html"); | |
201 OnResponse("http://m.google.com/resource1.jpg"); | |
202 CheckPrefetcherState(5, 6, 3); | |
203 | |
204 AddStartUrlRequestExpectation("http://www.google.com/resource3.html"); | |
205 OnSSLCertificateError("http://www.google.com/resource1.html"); | |
206 CheckPrefetcherState(5, 5, 3); | |
207 | |
208 AddStartUrlRequestExpectation("http://m.google.com/resource3.css"); | |
209 OnResponse("http://m.google.com/resource2.html"); | |
210 CheckPrefetcherState(5, 4, 3); | |
211 | |
212 AddStartUrlRequestExpectation("http://m.google.com/resource4.png"); | |
213 OnReceivedRedirect("http://www.google.com/resource3.html"); | |
214 CheckPrefetcherState(5, 3, 3); | |
215 | |
216 OnResponse("http://www.google.com/resource2.png"); | |
217 CheckPrefetcherState(4, 3, 2); | |
218 | |
219 AddStartUrlRequestExpectation("http://yahoo.com/resource3.png"); | |
220 OnReceivedRedirect("http://yahoo.com/resource2.png"); | |
221 CheckPrefetcherState(4, 2, 2); | |
222 | |
223 AddStartUrlRequestExpectation("http://yahoo.com/resource4.png"); | |
224 OnResponse("http://yahoo.com/resource1.png"); | |
225 CheckPrefetcherState(4, 1, 2); | |
226 | |
227 AddStartUrlRequestExpectation("http://yahoo.com/resource5.png"); | |
228 OnResponse("http://yahoo.com/resource4.png"); | |
229 CheckPrefetcherState(4, 0, 2); | |
230 | |
231 OnResponse("http://yahoo.com/resource5.png"); | |
232 CheckPrefetcherState(3, 0, 2); | |
233 | |
234 OnCertificateRequested("http://m.google.com/resource4.png"); | |
235 CheckPrefetcherState(2, 0, 2); | |
236 | |
237 OnAuthRequired("http://m.google.com/resource3.css"); | |
238 CheckPrefetcherState(1, 0, 1); | |
239 | |
240 // Expect the final call. | |
241 EXPECT_CALL(prefetcher_delegate_, | |
242 ResourcePrefetcherFinished(Eq(prefetcher_.get()), | |
243 Eq(requests_ptr))); | |
244 | |
245 OnResponse("http://yahoo.com/resource3.png"); | |
246 CheckPrefetcherState(0, 0, 0); | |
247 | |
248 // Check the prefetch status. | |
249 EXPECT_EQ((*requests_ptr)[0]->prefetch_status, | |
250 Request::PREFETCH_STATUS_CERT_ERROR); | |
251 EXPECT_EQ((*requests_ptr)[1]->prefetch_status, | |
252 Request::PREFETCH_STATUS_FROM_CACHE); | |
253 EXPECT_EQ((*requests_ptr)[2]->prefetch_status, | |
254 Request::PREFETCH_STATUS_FROM_CACHE); | |
255 EXPECT_EQ((*requests_ptr)[3]->prefetch_status, | |
256 Request::PREFETCH_STATUS_REDIRECTED); | |
257 EXPECT_EQ((*requests_ptr)[4]->prefetch_status, | |
258 Request::PREFETCH_STATUS_FROM_CACHE); | |
259 EXPECT_EQ((*requests_ptr)[5]->prefetch_status, | |
260 Request::PREFETCH_STATUS_FROM_CACHE); | |
261 EXPECT_EQ((*requests_ptr)[6]->prefetch_status, | |
262 Request::PREFETCH_STATUS_REDIRECTED); | |
263 EXPECT_EQ((*requests_ptr)[7]->prefetch_status, | |
264 Request::PREFETCH_STATUS_FROM_CACHE); | |
265 EXPECT_EQ((*requests_ptr)[8]->prefetch_status, | |
266 Request::PREFETCH_STATUS_AUTH_REQUIRED); | |
267 EXPECT_EQ((*requests_ptr)[9]->prefetch_status, | |
268 Request::PREFETCH_STATUS_CERT_REQUIRED); | |
269 EXPECT_EQ((*requests_ptr)[10]->prefetch_status, | |
270 Request::PREFETCH_STATUS_FROM_CACHE); | |
271 EXPECT_EQ((*requests_ptr)[11]->prefetch_status, | |
272 Request::PREFETCH_STATUS_FROM_CACHE); | |
273 } | |
274 | |
275 TEST_F(ResourcePrefetcherTest, TestPrefetcherStopped) { | |
276 scoped_ptr<ResourcePrefetcher::RequestVector> requests( | |
277 new ResourcePrefetcher::RequestVector); | |
278 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
279 "http://www.google.com/resource1.html"))); | |
280 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
281 "http://www.google.com/resource2.png"))); | |
282 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
283 "http://yahoo.com/resource1.png"))); | |
284 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
285 "http://yahoo.com/resource2.png"))); | |
286 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
287 "http://yahoo.com/resource3.png"))); | |
288 requests->push_back(new ResourcePrefetcher::Request(GURL( | |
289 "http://m.google.com/resource1.jpg"))); | |
290 | |
291 NavigationID navigation_id; | |
292 navigation_id.render_process_id = 1; | |
293 navigation_id.render_view_id = 2; | |
294 navigation_id.main_frame_url = GURL("http://www.google.com"); | |
295 | |
296 // Needed later for comparison. | |
297 ResourcePrefetcher::RequestVector* requests_ptr = requests.get(); | |
298 | |
299 prefetcher_.reset(new TestResourcePrefetcher(&prefetcher_delegate_, | |
300 config_, | |
301 navigation_id, | |
302 requests.Pass())); | |
303 | |
304 // Starting the prefetcher maxes out the number of possible requests. | |
305 AddStartUrlRequestExpectation("http://www.google.com/resource1.html"); | |
306 AddStartUrlRequestExpectation("http://www.google.com/resource2.png"); | |
307 AddStartUrlRequestExpectation("http://yahoo.com/resource1.png"); | |
308 AddStartUrlRequestExpectation("http://yahoo.com/resource2.png"); | |
309 AddStartUrlRequestExpectation("http://m.google.com/resource1.jpg"); | |
310 | |
311 prefetcher_->Start(); | |
312 CheckPrefetcherState(5, 1, 3); | |
313 | |
314 OnResponse("http://www.google.com/resource1.html"); | |
315 CheckPrefetcherState(4, 1, 3); | |
316 | |
317 prefetcher_->Stop(); // No more queueing. | |
318 | |
319 OnResponse("http://www.google.com/resource2.png"); | |
320 CheckPrefetcherState(3, 1, 2); | |
321 | |
322 OnResponse("http://yahoo.com/resource1.png"); | |
323 CheckPrefetcherState(2, 1, 2); | |
324 | |
325 OnResponse("http://yahoo.com/resource2.png"); | |
326 CheckPrefetcherState(1, 1, 1); | |
327 | |
328 // Expect the final call. | |
329 EXPECT_CALL(prefetcher_delegate_, | |
330 ResourcePrefetcherFinished(Eq(prefetcher_.get()), | |
331 Eq(requests_ptr))); | |
332 | |
333 OnResponse("http://m.google.com/resource1.jpg"); | |
334 CheckPrefetcherState(0, 1, 0); | |
335 } | |
336 | |
337 } // namespace predictors | |
OLD | NEW |