- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / predictors / resource_prefetcher_unittest.cc
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