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: 15 InstantLoaderDelegateImpl() {} 16 17 virtual void InstantStatusChanged(InstantLoader* loader) OVERRIDE {} 18 19 virtual void SetSuggestedTextFor(InstantLoader* loader, 20 const string16& text, 21 InstantCompleteBehavior behavior) OVERRIDE {} 22 23 virtual gfx::Rect GetInstantBounds() OVERRIDE { 24 return gfx::Rect(); 25 } 26 27 virtual bool ShouldCommitInstantOnMouseUp() OVERRIDE { 28 return false; 29 } 30 31 virtual void CommitInstantLoader(InstantLoader* loader) OVERRIDE { 32 } 33 34 virtual void InstantLoaderDoesntSupportInstant( 35 InstantLoader* loader) OVERRIDE { 36 } 37 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: 50 InstantLoaderManagerTest() {} 51 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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