prerender_manager_unittest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2010 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/time.h"
6#include "chrome/browser/prerender/prerender_contents.h"
7#include "chrome/browser/prerender/prerender_manager.h"
8#include "content/browser/browser_thread.h"
9#include "googleurl/src/gurl.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
12namespace prerender {
13
14namespace {
15
16class DummyPrerenderContents : public PrerenderContents {
17 public:
18  DummyPrerenderContents(PrerenderManager* prerender_manager,
19                         const GURL& url,
20                         FinalStatus expected_final_status)
21      : PrerenderContents(prerender_manager, NULL, url,
22                          std::vector<GURL>(), GURL()),
23        has_started_(false),
24        expected_final_status_(expected_final_status) {
25  }
26
27  DummyPrerenderContents(PrerenderManager* prerender_manager,
28                         const GURL& url,
29                         const std::vector<GURL> alias_urls,
30                         FinalStatus expected_final_status)
31      : PrerenderContents(prerender_manager, NULL, url, alias_urls, GURL()),
32        has_started_(false),
33        expected_final_status_(expected_final_status) {
34  }
35
36  virtual ~DummyPrerenderContents() {
37    EXPECT_EQ(expected_final_status_, final_status());
38  }
39
40  virtual void StartPrerendering() OVERRIDE {
41    has_started_ = true;
42  }
43
44  bool has_started() const { return has_started_; }
45
46 private:
47  bool has_started_;
48  FinalStatus expected_final_status_;
49};
50
51class TestPrerenderManager : public PrerenderManager {
52 public:
53  TestPrerenderManager()
54      : PrerenderManager(NULL),
55        time_(base::Time::Now()),
56        next_pc_(NULL) {
57  }
58
59  void AdvanceTime(base::TimeDelta delta) {
60    time_ += delta;
61  }
62
63  void SetNextPrerenderContents(PrerenderContents* pc) {
64    next_pc_.reset(pc);
65  }
66
67  // Shorthand to add a simple preload with no aliases.
68  bool AddSimplePreload(const GURL& url) {
69    return AddPreload(url, std::vector<GURL>(), GURL());
70  }
71
72  PrerenderContents* next_pc() { return next_pc_.get(); }
73
74 protected:
75  virtual ~TestPrerenderManager() {
76    if (next_pc()) {
77      next_pc()->set_final_status(
78          FINAL_STATUS_MANAGER_SHUTDOWN);
79    }
80  }
81
82 private:
83  virtual base::Time GetCurrentTime() const OVERRIDE {
84    return time_;
85  }
86
87  virtual PrerenderContents* CreatePrerenderContents(
88      const GURL& url,
89      const std::vector<GURL>& alias_urls,
90      const GURL& referrer) OVERRIDE {
91    DCHECK(next_pc_.get());
92    return next_pc_.release();
93  }
94
95  base::Time time_;
96  scoped_ptr<PrerenderContents> next_pc_;
97};
98
99}  // namespace
100
101class PrerenderManagerTest : public testing::Test {
102 public:
103  PrerenderManagerTest() : prerender_manager_(new TestPrerenderManager()),
104                           ui_thread_(BrowserThread::UI, &message_loop_) {
105  }
106
107 protected:
108  scoped_refptr<TestPrerenderManager> prerender_manager_;
109
110 private:
111  // Needed to pass PrerenderManager's DCHECKs.
112  MessageLoop message_loop_;
113  BrowserThread ui_thread_;
114};
115
116TEST_F(PrerenderManagerTest, EmptyTest) {
117  GURL url("http://www.google.com/");
118  EXPECT_FALSE(prerender_manager_->MaybeUsePreloadedPage(NULL, url));
119}
120
121TEST_F(PrerenderManagerTest, FoundTest) {
122  GURL url("http://www.google.com/");
123  DummyPrerenderContents* pc =
124      new DummyPrerenderContents(prerender_manager_.get(),
125                                 url,
126                                 FINAL_STATUS_USED);
127  prerender_manager_->SetNextPrerenderContents(pc);
128  EXPECT_TRUE(prerender_manager_->AddSimplePreload(url));
129  EXPECT_TRUE(pc->has_started());
130  ASSERT_EQ(pc, prerender_manager_->GetEntry(url));
131  pc->set_final_status(FINAL_STATUS_USED);
132  delete pc;
133}
134
135// Make sure that if queue a request, and a second prerender request for the
136// same URL comes in, that we drop the second request and keep the first one.
137TEST_F(PrerenderManagerTest, DropSecondRequestTest) {
138  GURL url("http://www.google.com/");
139  DummyPrerenderContents* pc =
140      new DummyPrerenderContents(prerender_manager_.get(), url,
141                                 FINAL_STATUS_USED);
142  DummyPrerenderContents* null = NULL;
143  prerender_manager_->SetNextPrerenderContents(pc);
144  EXPECT_TRUE(prerender_manager_->AddSimplePreload(url));
145  EXPECT_EQ(null, prerender_manager_->next_pc());
146  EXPECT_TRUE(pc->has_started());
147  DummyPrerenderContents* pc1 =
148      new DummyPrerenderContents(
149          prerender_manager_.get(), url,
150          FINAL_STATUS_MANAGER_SHUTDOWN);
151  prerender_manager_->SetNextPrerenderContents(pc1);
152  EXPECT_FALSE(prerender_manager_->AddSimplePreload(url));
153  EXPECT_EQ(pc1, prerender_manager_->next_pc());
154  EXPECT_FALSE(pc1->has_started());
155  ASSERT_EQ(pc, prerender_manager_->GetEntry(url));
156  pc->set_final_status(FINAL_STATUS_USED);
157  delete pc;
158}
159
160// Ensure that we expire a prerendered page after the max. permitted time.
161TEST_F(PrerenderManagerTest, ExpireTest) {
162  GURL url("http://www.google.com/");
163  DummyPrerenderContents* pc =
164      new DummyPrerenderContents(prerender_manager_.get(), url,
165                                 FINAL_STATUS_TIMED_OUT);
166  DummyPrerenderContents* null = NULL;
167  prerender_manager_->SetNextPrerenderContents(pc);
168  EXPECT_TRUE(prerender_manager_->AddSimplePreload(url));
169  EXPECT_EQ(null, prerender_manager_->next_pc());
170  EXPECT_TRUE(pc->has_started());
171  prerender_manager_->AdvanceTime(prerender_manager_->max_prerender_age()
172                                  + base::TimeDelta::FromSeconds(1));
173  ASSERT_EQ(null, prerender_manager_->GetEntry(url));
174}
175
176// LRU Test.  Make sure that if we prerender more than one request, that
177// the oldest one will be dropped.
178TEST_F(PrerenderManagerTest, DropOldestRequestTest) {
179  GURL url("http://www.google.com/");
180  DummyPrerenderContents* pc =
181      new DummyPrerenderContents(prerender_manager_.get(), url,
182                                 FINAL_STATUS_EVICTED);
183  DummyPrerenderContents* null = NULL;
184  prerender_manager_->SetNextPrerenderContents(pc);
185  EXPECT_TRUE(prerender_manager_->AddSimplePreload(url));
186  EXPECT_EQ(null, prerender_manager_->next_pc());
187  EXPECT_TRUE(pc->has_started());
188  GURL url1("http://news.google.com/");
189  DummyPrerenderContents* pc1 =
190      new DummyPrerenderContents(prerender_manager_.get(), url1,
191                                 FINAL_STATUS_USED);
192  prerender_manager_->SetNextPrerenderContents(pc1);
193  EXPECT_TRUE(prerender_manager_->AddSimplePreload(url1));
194  EXPECT_EQ(null, prerender_manager_->next_pc());
195  EXPECT_TRUE(pc1->has_started());
196  ASSERT_EQ(null, prerender_manager_->GetEntry(url));
197  ASSERT_EQ(pc1, prerender_manager_->GetEntry(url1));
198  pc1->set_final_status(FINAL_STATUS_USED);
199  delete pc1;
200}
201
202// Two element prerender test.  Ensure that the LRU operates correctly if we
203// permit 2 elements to be kept prerendered.
204TEST_F(PrerenderManagerTest, TwoElementPrerenderTest) {
205  prerender_manager_->set_max_elements(2);
206  GURL url("http://www.google.com/");
207  DummyPrerenderContents* pc =
208      new DummyPrerenderContents(prerender_manager_.get(), url,
209                                 FINAL_STATUS_EVICTED);
210  DummyPrerenderContents* null = NULL;
211  prerender_manager_->SetNextPrerenderContents(pc);
212  EXPECT_TRUE(prerender_manager_->AddSimplePreload(url));
213  EXPECT_EQ(null, prerender_manager_->next_pc());
214  EXPECT_TRUE(pc->has_started());
215  GURL url1("http://news.google.com/");
216  DummyPrerenderContents* pc1 =
217      new DummyPrerenderContents(prerender_manager_.get(),  url1,
218                                 FINAL_STATUS_USED);
219  prerender_manager_->SetNextPrerenderContents(pc1);
220  EXPECT_TRUE(prerender_manager_->AddSimplePreload(url1));
221  EXPECT_EQ(null, prerender_manager_->next_pc());
222  EXPECT_TRUE(pc1->has_started());
223  GURL url2("http://images.google.com/");
224  DummyPrerenderContents* pc2 =
225      new DummyPrerenderContents(prerender_manager_.get(), url2,
226                                 FINAL_STATUS_USED);
227  prerender_manager_->SetNextPrerenderContents(pc2);
228  EXPECT_TRUE(prerender_manager_->AddSimplePreload(url2));
229  EXPECT_EQ(null, prerender_manager_->next_pc());
230  EXPECT_TRUE(pc2->has_started());
231  ASSERT_EQ(null, prerender_manager_->GetEntry(url));
232  ASSERT_EQ(pc1, prerender_manager_->GetEntry(url1));
233  ASSERT_EQ(pc2, prerender_manager_->GetEntry(url2));
234  pc1->set_final_status(FINAL_STATUS_USED);
235  delete pc1;
236  pc2->set_final_status(FINAL_STATUS_USED);
237  delete pc2;
238}
239
240TEST_F(PrerenderManagerTest, AliasURLTest) {
241  GURL url("http://www.google.com/");
242  GURL alias_url1("http://www.google.com/index.html");
243  GURL alias_url2("http://google.com/");
244  GURL not_an_alias_url("http://google.com/index.html");
245  std::vector<GURL> alias_urls;
246  alias_urls.push_back(alias_url1);
247  alias_urls.push_back(alias_url2);
248  DummyPrerenderContents* pc =
249      new DummyPrerenderContents(prerender_manager_.get(), url, alias_urls,
250                                 FINAL_STATUS_USED);
251  // Test that all of the aliases work, but nont_an_alias_url does not.
252  prerender_manager_->SetNextPrerenderContents(pc);
253  EXPECT_TRUE(prerender_manager_->AddPreload(url, alias_urls, GURL()));
254  ASSERT_EQ(NULL, prerender_manager_->GetEntry(not_an_alias_url));
255  ASSERT_EQ(pc, prerender_manager_->GetEntry(alias_url1));
256  prerender_manager_->SetNextPrerenderContents(pc);
257  EXPECT_TRUE(prerender_manager_->AddPreload(url, alias_urls, GURL()));
258  ASSERT_EQ(pc, prerender_manager_->GetEntry(alias_url2));
259  prerender_manager_->SetNextPrerenderContents(pc);
260  EXPECT_TRUE(prerender_manager_->AddPreload(url, alias_urls, GURL()));
261  ASSERT_EQ(pc, prerender_manager_->GetEntry(url));
262
263  // Test that alias URLs can not be added.
264  prerender_manager_->SetNextPrerenderContents(pc);
265  EXPECT_TRUE(prerender_manager_->AddPreload(url, alias_urls, GURL()));
266  EXPECT_FALSE(prerender_manager_->AddSimplePreload(url));
267  EXPECT_FALSE(prerender_manager_->AddSimplePreload(alias_url1));
268  EXPECT_FALSE(prerender_manager_->AddSimplePreload(alias_url2));
269  ASSERT_EQ(pc, prerender_manager_->GetEntry(url));
270
271  pc->set_final_status(FINAL_STATUS_USED);
272  delete pc;
273}
274
275}  // naemspace prerender
276