1 // Copyright (c) 2011 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/scoped_ptr.h"
6 #include "chrome/browser/instant/instant_loader.h"
7 #include "chrome/browser/instant/instant_loader_delegate.h"
8 #include "chrome/browser/instant/instant_loader_manager.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace {
12
13 class InstantLoaderDelegateImpl : public InstantLoaderDelegate {
14 public:
InstantLoaderDelegateImpl()15 InstantLoaderDelegateImpl() {}
16
InstantStatusChanged(InstantLoader * loader)17 virtual void InstantStatusChanged(InstantLoader* loader) OVERRIDE {}
18
SetSuggestedTextFor(InstantLoader * loader,const string16 & text,InstantCompleteBehavior behavior)19 virtual void SetSuggestedTextFor(InstantLoader* loader,
20 const string16& text,
21 InstantCompleteBehavior behavior) OVERRIDE {}
22
GetInstantBounds()23 virtual gfx::Rect GetInstantBounds() OVERRIDE {
24 return gfx::Rect();
25 }
26
ShouldCommitInstantOnMouseUp()27 virtual bool ShouldCommitInstantOnMouseUp() OVERRIDE {
28 return false;
29 }
30
CommitInstantLoader(InstantLoader * loader)31 virtual void CommitInstantLoader(InstantLoader* loader) OVERRIDE {
32 }
33
InstantLoaderDoesntSupportInstant(InstantLoader * loader)34 virtual void InstantLoaderDoesntSupportInstant(
35 InstantLoader* loader) OVERRIDE {
36 }
37
AddToBlacklist(InstantLoader * loader,const GURL & url)38 virtual void AddToBlacklist(InstantLoader* loader,
39 const GURL& url) OVERRIDE {
40 }
41
42 private:
43 DISALLOW_COPY_AND_ASSIGN(InstantLoaderDelegateImpl);
44 };
45
46 }
47
48 class InstantLoaderManagerTest : public testing::Test {
49 public:
InstantLoaderManagerTest()50 InstantLoaderManagerTest() {}
51
MarkReady(InstantLoader * loader)52 void MarkReady(InstantLoader* loader) {
53 loader->ready_ = true;
54 }
55
56 private:
57 DISALLOW_COPY_AND_ASSIGN(InstantLoaderManagerTest);
58 };
59
60 // Makes sure UpdateLoader works when invoked once.
TEST_F(InstantLoaderManagerTest,Basic)61 TEST_F(InstantLoaderManagerTest, Basic) {
62 InstantLoaderDelegateImpl delegate;
63 InstantLoaderManager manager(&delegate);
64 scoped_ptr<InstantLoader> loader;
65 manager.UpdateLoader(0, &loader);
66 EXPECT_EQ(NULL, loader.get());
67 EXPECT_TRUE(manager.current_loader());
68 EXPECT_EQ(NULL, manager.pending_loader());
69 EXPECT_EQ(0, manager.current_loader()->template_url_id());
70 }
71
72 // Make sure invoking update twice for non-instant results keeps the same
73 // loader.
TEST_F(InstantLoaderManagerTest,UpdateTwice)74 TEST_F(InstantLoaderManagerTest, UpdateTwice) {
75 InstantLoaderDelegateImpl delegate;
76 InstantLoaderManager manager(&delegate);
77 scoped_ptr<InstantLoader> loader;
78 manager.UpdateLoader(0, &loader);
79 InstantLoader* current_loader = manager.current_loader();
80 manager.UpdateLoader(0, &loader);
81 EXPECT_EQ(NULL, loader.get());
82 EXPECT_EQ(current_loader, manager.current_loader());
83 EXPECT_EQ(NULL, manager.pending_loader());
84 }
85
86 // Make sure invoking update twice for instant results keeps the same loader.
TEST_F(InstantLoaderManagerTest,UpdateInstantTwice)87 TEST_F(InstantLoaderManagerTest, UpdateInstantTwice) {
88 InstantLoaderDelegateImpl delegate;
89 InstantLoaderManager manager(&delegate);
90 scoped_ptr<InstantLoader> loader;
91 manager.UpdateLoader(1, &loader);
92 InstantLoader* current_loader = manager.current_loader();
93 manager.UpdateLoader(1, &loader);
94 EXPECT_EQ(NULL, loader.get());
95 EXPECT_EQ(current_loader, manager.current_loader());
96 EXPECT_EQ(NULL, manager.pending_loader());
97 EXPECT_EQ(1u, manager.num_instant_loaders());
98 }
99
100 // Makes sure transitioning from non-instant to instant works.
TEST_F(InstantLoaderManagerTest,NonInstantToInstant)101 TEST_F(InstantLoaderManagerTest, NonInstantToInstant) {
102 InstantLoaderDelegateImpl delegate;
103 InstantLoaderManager manager(&delegate);
104 scoped_ptr<InstantLoader> loader;
105 manager.UpdateLoader(0, &loader);
106 InstantLoader* current_loader = manager.current_loader();
107 manager.UpdateLoader(1, &loader);
108 EXPECT_TRUE(loader.get() != NULL);
109 EXPECT_NE(current_loader, manager.current_loader());
110 EXPECT_EQ(NULL, manager.pending_loader());
111 EXPECT_EQ(1u, manager.num_instant_loaders());
112 }
113
114 // Makes sure instant loaders aren't deleted when invoking update with different
115 // ids.
TEST_F(InstantLoaderManagerTest,DontDeleteInstantLoaders)116 TEST_F(InstantLoaderManagerTest, DontDeleteInstantLoaders) {
117 InstantLoaderDelegateImpl delegate;
118 InstantLoaderManager manager(&delegate);
119 scoped_ptr<InstantLoader> loader;
120 manager.UpdateLoader(1, &loader);
121 InstantLoader* current_loader = manager.current_loader();
122 manager.UpdateLoader(2, &loader);
123 EXPECT_EQ(NULL, loader.get());
124 EXPECT_NE(current_loader, manager.current_loader());
125 EXPECT_EQ(NULL, manager.pending_loader());
126 EXPECT_EQ(2u, manager.num_instant_loaders());
127 }
128
129 // Makes sure a new loader is created and assigned to secondary when
130 // transitioning from a ready non-instant to instant.
TEST_F(InstantLoaderManagerTest,CreateSecondaryWhenReady)131 TEST_F(InstantLoaderManagerTest, CreateSecondaryWhenReady) {
132 InstantLoaderDelegateImpl delegate;
133 InstantLoaderManager manager(&delegate);
134 scoped_ptr<InstantLoader> loader;
135 manager.UpdateLoader(0, &loader);
136 InstantLoader* current_loader = manager.current_loader();
137 ASSERT_TRUE(current_loader);
138 MarkReady(current_loader);
139
140 manager.UpdateLoader(1, &loader);
141 EXPECT_EQ(NULL, loader.get());
142 EXPECT_EQ(current_loader, manager.current_loader());
143 EXPECT_TRUE(manager.pending_loader());
144 EXPECT_NE(current_loader, manager.pending_loader());
145 EXPECT_EQ(1u, manager.num_instant_loaders());
146
147 // Make the pending loader current.
148 InstantLoader* pending_loader = manager.pending_loader();
149 manager.MakePendingCurrent(&loader);
150 EXPECT_TRUE(loader.get());
151 EXPECT_EQ(pending_loader, manager.current_loader());
152 EXPECT_EQ(NULL, manager.pending_loader());
153 EXPECT_EQ(1u, manager.num_instant_loaders());
154 }
155
156 // Makes sure releasing an instant updates maps currectly.
TEST_F(InstantLoaderManagerTest,ReleaseInstant)157 TEST_F(InstantLoaderManagerTest, ReleaseInstant) {
158 InstantLoaderDelegateImpl delegate;
159 InstantLoaderManager manager(&delegate);
160 scoped_ptr<InstantLoader> loader;
161 manager.UpdateLoader(1, &loader);
162 scoped_ptr<InstantLoader> current_loader(manager.ReleaseCurrentLoader());
163 EXPECT_TRUE(current_loader.get());
164 EXPECT_EQ(NULL, manager.current_loader());
165 EXPECT_EQ(0u, manager.num_instant_loaders());
166 }
167
168 // Tests transitioning from a non-instant ready loader to an instant ready
169 // loader is immediate.
TEST_F(InstantLoaderManagerTest,NonInstantToInstantWhenReady)170 TEST_F(InstantLoaderManagerTest, NonInstantToInstantWhenReady) {
171 InstantLoaderDelegateImpl delegate;
172 InstantLoaderManager manager(&delegate);
173 scoped_ptr<InstantLoader> loader;
174 manager.UpdateLoader(1, &loader);
175 ASSERT_TRUE(manager.current_loader());
176 EXPECT_EQ(1, manager.current_loader()->template_url_id());
177 InstantLoader* instant_loader = manager.current_loader();
178
179 manager.UpdateLoader(0, &loader);
180 InstantLoader* non_instant_loader = manager.current_loader();
181 ASSERT_TRUE(non_instant_loader);
182 MarkReady(non_instant_loader);
183 EXPECT_NE(non_instant_loader, instant_loader);
184
185 MarkReady(instant_loader);
186 manager.UpdateLoader(1, &loader);
187 EXPECT_EQ(non_instant_loader, loader.get());
188 EXPECT_EQ(instant_loader, manager.current_loader());
189 EXPECT_EQ(NULL, manager.pending_loader());
190 EXPECT_EQ(1u, manager.num_instant_loaders());
191 }
192
193 // Tests transitioning between 3 instant loaders, all ready.
TEST_F(InstantLoaderManagerTest,ThreeInstant)194 TEST_F(InstantLoaderManagerTest, ThreeInstant) {
195 InstantLoaderDelegateImpl delegate;
196 InstantLoaderManager manager(&delegate);
197 scoped_ptr<InstantLoader> loader;
198 manager.UpdateLoader(1, &loader);
199 ASSERT_TRUE(manager.current_loader());
200 EXPECT_EQ(1, manager.current_loader()->template_url_id());
201 InstantLoader* instant_loader1 = manager.current_loader();
202 MarkReady(instant_loader1);
203
204 manager.UpdateLoader(2, &loader);
205 InstantLoader* instant_loader2 = manager.pending_loader();
206 ASSERT_TRUE(instant_loader2);
207 EXPECT_EQ(2, instant_loader2->template_url_id());
208 EXPECT_NE(instant_loader1, instant_loader2);
209 EXPECT_EQ(instant_loader1, manager.current_loader());
210
211 manager.UpdateLoader(3, &loader);
212 InstantLoader* instant_loader3 = manager.pending_loader();
213 ASSERT_TRUE(instant_loader3);
214 EXPECT_EQ(3, instant_loader3->template_url_id());
215 EXPECT_NE(instant_loader1, instant_loader3);
216 EXPECT_NE(instant_loader2, instant_loader3);
217 EXPECT_EQ(instant_loader1, manager.current_loader());
218 }
219
220 // Tests DestroyLoader with an instant loader.
TEST_F(InstantLoaderManagerTest,DestroyInstantLoader)221 TEST_F(InstantLoaderManagerTest, DestroyInstantLoader) {
222 InstantLoaderDelegateImpl delegate;
223 InstantLoaderManager manager(&delegate);
224 scoped_ptr<InstantLoader> loader;
225 manager.UpdateLoader(1, &loader);
226 ASSERT_TRUE(manager.current_loader());
227 EXPECT_EQ(1, manager.current_loader()->template_url_id());
228 // Now destroy it.
229 manager.DestroyLoader(manager.current_loader());
230
231 // There should be no current, pending and 0 instant loaders.
232 ASSERT_EQ(NULL, manager.current_loader());
233 ASSERT_EQ(NULL, manager.pending_loader());
234 EXPECT_EQ(0u, manager.num_instant_loaders());
235 }
236
237 // Tests DestroyLoader when the loader is pending.
TEST_F(InstantLoaderManagerTest,DestroyPendingLoader)238 TEST_F(InstantLoaderManagerTest, DestroyPendingLoader) {
239 InstantLoaderDelegateImpl delegate;
240 InstantLoaderManager manager(&delegate);
241 scoped_ptr<InstantLoader> loader;
242 manager.UpdateLoader(1, &loader);
243 InstantLoader* first_loader = manager.active_loader();
244 MarkReady(first_loader);
245
246 // Create another loader.
247 manager.UpdateLoader(0, &loader);
248 InstantLoader* second_loader = manager.pending_loader();
249 ASSERT_TRUE(second_loader);
250 ASSERT_NE(second_loader, first_loader);
251
252 // Destroy it.
253 manager.DestroyLoader(second_loader);
254 EXPECT_EQ(NULL, manager.pending_loader());
255 EXPECT_EQ(first_loader, manager.current_loader());
256 }
257
258 // Makes sure WillUpateChangeActiveLoader works.
TEST_F(InstantLoaderManagerTest,WillUpateChangeActiveLoader)259 TEST_F(InstantLoaderManagerTest, WillUpateChangeActiveLoader) {
260 InstantLoaderDelegateImpl delegate;
261 InstantLoaderManager manager(&delegate);
262 scoped_ptr<InstantLoader> loader;
263
264 // When there is no loader WillUpateChangeActiveLoader should return true.
265 EXPECT_TRUE(manager.WillUpateChangeActiveLoader(0));
266 EXPECT_TRUE(manager.WillUpateChangeActiveLoader(1));
267
268 // Add a loder with id 0 and test again.
269 manager.UpdateLoader(0, &loader);
270 EXPECT_FALSE(manager.WillUpateChangeActiveLoader(0));
271 EXPECT_TRUE(manager.WillUpateChangeActiveLoader(1));
272 ASSERT_TRUE(manager.active_loader());
273 MarkReady(manager.active_loader());
274
275 // Add a loader with id 1 and test again.
276 manager.UpdateLoader(1, &loader);
277 EXPECT_TRUE(manager.WillUpateChangeActiveLoader(0));
278 EXPECT_FALSE(manager.WillUpateChangeActiveLoader(1));
279 }
280
281 // Makes sure UpdateLoader doesn't schedule a loader for deletion when asked
282 // to update and the pending loader is ready.
TEST_F(InstantLoaderManagerTest,UpdateWithReadyPending)283 TEST_F(InstantLoaderManagerTest, UpdateWithReadyPending) {
284 InstantLoaderDelegateImpl delegate;
285 InstantLoaderManager manager(&delegate);
286
287 {
288 scoped_ptr<InstantLoader> loader;
289 manager.UpdateLoader(1, &loader);
290 }
291 InstantLoader* instant_loader = manager.current_loader();
292 ASSERT_TRUE(instant_loader);
293 MarkReady(instant_loader);
294
295 {
296 scoped_ptr<InstantLoader> loader;
297 manager.UpdateLoader(0, &loader);
298 }
299 InstantLoader* non_instant_loader = manager.active_loader();
300 ASSERT_TRUE(non_instant_loader);
301 ASSERT_NE(instant_loader, non_instant_loader);
302 MarkReady(non_instant_loader);
303
304 // This makes the non_instant_loader the current loader since it was ready.
305 scoped_ptr<InstantLoader> loader;
306 manager.UpdateLoader(0, &loader);
307 ASSERT_NE(loader.get(), non_instant_loader);
308 }
309