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/run_loop.h" 6 #include "testing/gtest/include/gtest/gtest.h" 7 #include "webkit/browser/appcache/appcache.h" 8 #include "webkit/browser/appcache/appcache_group.h" 9 #include "webkit/browser/appcache/appcache_response.h" 10 #include "webkit/browser/appcache/appcache_storage.h" 11 #include "webkit/browser/appcache/mock_appcache_service.h" 12 13 namespace appcache { 14 15 class MockAppCacheStorageTest : public testing::Test { 16 public: 17 class MockStorageDelegate : public AppCacheStorage::Delegate { 18 public: 19 explicit MockStorageDelegate() 20 : loaded_cache_id_(0), stored_group_success_(false), 21 obsoleted_success_(false), found_cache_id_(kNoCacheId) { 22 } 23 24 virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) OVERRIDE { 25 loaded_cache_ = cache; 26 loaded_cache_id_ = cache_id; 27 } 28 29 virtual void OnGroupLoaded(AppCacheGroup* group, 30 const GURL& manifest_url) OVERRIDE { 31 loaded_group_ = group; 32 loaded_manifest_url_ = manifest_url; 33 } 34 35 virtual void OnGroupAndNewestCacheStored( 36 AppCacheGroup* group, AppCache* newest_cache, bool success, 37 bool would_exceed_quota) OVERRIDE { 38 stored_group_ = group; 39 stored_group_success_ = success; 40 } 41 42 virtual void OnGroupMadeObsolete(AppCacheGroup* group, 43 bool success) OVERRIDE { 44 obsoleted_group_ = group; 45 obsoleted_success_ = success; 46 } 47 48 virtual void OnMainResponseFound(const GURL& url, 49 const AppCacheEntry& entry, 50 const GURL& fallback_url, 51 const AppCacheEntry& fallback_entry, 52 int64 cache_id, 53 int64 group_id, 54 const GURL& manifest_url) OVERRIDE { 55 found_url_ = url; 56 found_entry_ = entry; 57 found_fallback_url_ = fallback_url; 58 found_fallback_entry_ = fallback_entry; 59 found_cache_id_ = cache_id; 60 found_manifest_url_ = manifest_url; 61 } 62 63 scoped_refptr<AppCache> loaded_cache_; 64 int64 loaded_cache_id_; 65 scoped_refptr<AppCacheGroup> loaded_group_; 66 GURL loaded_manifest_url_; 67 scoped_refptr<AppCacheGroup> stored_group_; 68 bool stored_group_success_; 69 scoped_refptr<AppCacheGroup> obsoleted_group_; 70 bool obsoleted_success_; 71 GURL found_url_; 72 AppCacheEntry found_entry_; 73 GURL found_fallback_url_; 74 AppCacheEntry found_fallback_entry_; 75 int64 found_cache_id_; 76 GURL found_manifest_url_; 77 }; 78 79 private: 80 base::MessageLoop message_loop_; 81 }; 82 83 TEST_F(MockAppCacheStorageTest, LoadCache_Miss) { 84 // Attempt to load a cache that doesn't exist. Should 85 // complete asyncly. 86 MockAppCacheService service; 87 MockStorageDelegate delegate; 88 service.storage()->LoadCache(111, &delegate); 89 EXPECT_NE(111, delegate.loaded_cache_id_); 90 base::RunLoop().RunUntilIdle(); // Do async task execution. 91 EXPECT_EQ(111, delegate.loaded_cache_id_); 92 EXPECT_FALSE(delegate.loaded_cache_.get()); 93 } 94 95 TEST_F(MockAppCacheStorageTest, LoadCache_NearHit) { 96 // Attempt to load a cache that is currently in use 97 // and does not require loading from disk. This 98 // load should complete syncly. 99 MockAppCacheService service; 100 101 // Setup some preconditions. Make an 'unstored' cache for 102 // us to load. The ctor should put it in the working set. 103 int64 cache_id = service.storage()->NewCacheId(); 104 scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); 105 106 // Conduct the test. 107 MockStorageDelegate delegate; 108 service.storage()->LoadCache(cache_id, &delegate); 109 EXPECT_EQ(cache_id, delegate.loaded_cache_id_); 110 EXPECT_EQ(cache.get(), delegate.loaded_cache_.get()); 111 } 112 113 TEST_F(MockAppCacheStorageTest, CreateGroup) { 114 // Attempt to load/create a group that doesn't exist. 115 // Should complete asyncly. 116 MockAppCacheService service; 117 MockAppCacheStorage* storage = 118 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 119 MockStorageDelegate delegate; 120 GURL manifest_url("http://blah/"); 121 service.storage()->LoadOrCreateGroup(manifest_url, &delegate); 122 EXPECT_NE(manifest_url, delegate.loaded_manifest_url_); 123 EXPECT_FALSE(delegate.loaded_group_.get()); 124 base::RunLoop().RunUntilIdle(); // Do async task execution. 125 EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_); 126 EXPECT_TRUE(delegate.loaded_group_.get()); 127 EXPECT_TRUE(delegate.loaded_group_->HasOneRef()); 128 EXPECT_FALSE(delegate.loaded_group_->newest_complete_cache()); 129 EXPECT_TRUE(storage->stored_groups_.empty()); 130 } 131 132 TEST_F(MockAppCacheStorageTest, LoadGroup_NearHit) { 133 // Attempt to load a group that is currently in use 134 // and does not require loading from disk. This 135 // load should complete syncly. 136 MockAppCacheService service; 137 MockStorageDelegate delegate; 138 139 // Setup some preconditions. Create a group that appears 140 // to be "unstored" and "currently in use". 141 GURL manifest_url("http://blah/"); 142 service.storage()->LoadOrCreateGroup(manifest_url, &delegate); 143 base::RunLoop().RunUntilIdle(); // Do async task execution. 144 EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_); 145 EXPECT_TRUE(delegate.loaded_group_.get()); 146 147 // Reset our delegate, and take a reference to the new group. 148 scoped_refptr<AppCacheGroup> group; 149 group.swap(delegate.loaded_group_); 150 delegate.loaded_manifest_url_ = GURL(); 151 152 // Conduct the test. 153 service.storage()->LoadOrCreateGroup(manifest_url, &delegate); 154 EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_); 155 EXPECT_EQ(group.get(), delegate.loaded_group_.get()); 156 } 157 158 TEST_F(MockAppCacheStorageTest, LoadGroupAndCache_FarHit) { 159 // Attempt to load a cache that is not currently in use 160 // and does require loading from disk. This 161 // load should complete asyncly. 162 MockAppCacheService service; 163 MockAppCacheStorage* storage = 164 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 165 166 // Setup some preconditions. Create a group and newest cache that 167 // appears to be "stored" and "not currently in use". 168 GURL manifest_url("http://blah/"); 169 scoped_refptr<AppCacheGroup> group( 170 new AppCacheGroup(service.storage(), manifest_url, 111)); 171 int64 cache_id = storage->NewCacheId(); 172 scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); 173 cache->set_complete(true); 174 group->AddCache(cache.get()); 175 storage->AddStoredGroup(group.get()); 176 storage->AddStoredCache(cache.get()); 177 178 // Drop the references from above so the only refs to these 179 // objects are from within the storage class. This is to make 180 // these objects appear as "not currently in use". 181 AppCache* cache_ptr = cache.get(); 182 AppCacheGroup* group_ptr = group.get(); 183 cache = NULL; 184 group = NULL; 185 186 // Setup a delegate to receive completion callbacks. 187 MockStorageDelegate delegate; 188 189 // Conduct the cache load test. 190 EXPECT_NE(cache_id, delegate.loaded_cache_id_); 191 EXPECT_NE(cache_ptr, delegate.loaded_cache_.get()); 192 storage->LoadCache(cache_id, &delegate); 193 EXPECT_NE(cache_id, delegate.loaded_cache_id_); 194 EXPECT_NE(cache_ptr, delegate.loaded_cache_.get()); 195 base::RunLoop().RunUntilIdle(); // Do async task execution. 196 EXPECT_EQ(cache_id, delegate.loaded_cache_id_); 197 EXPECT_EQ(cache_ptr, delegate.loaded_cache_.get()); 198 delegate.loaded_cache_ = NULL; 199 200 // Conduct the group load test. 201 EXPECT_NE(manifest_url, delegate.loaded_manifest_url_); 202 EXPECT_FALSE(delegate.loaded_group_.get()); 203 storage->LoadOrCreateGroup(manifest_url, &delegate); 204 EXPECT_NE(manifest_url, delegate.loaded_manifest_url_); 205 EXPECT_FALSE(delegate.loaded_group_.get()); 206 base::RunLoop().RunUntilIdle(); // Do async task execution. 207 EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_); 208 EXPECT_EQ(group_ptr, delegate.loaded_group_.get()); 209 } 210 211 TEST_F(MockAppCacheStorageTest, StoreNewGroup) { 212 // Store a group and its newest cache. Should complete asyncly. 213 MockAppCacheService service; 214 MockAppCacheStorage* storage = 215 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 216 217 // Setup some preconditions. Create a group and newest cache that 218 // appears to be "unstored". 219 GURL manifest_url("http://blah/"); 220 scoped_refptr<AppCacheGroup> group( 221 new AppCacheGroup(service.storage(), manifest_url, 111)); 222 int64 cache_id = storage->NewCacheId(); 223 scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); 224 // Hold a ref to the cache simulate the UpdateJob holding that ref, 225 // and hold a ref to the group to simulate the CacheHost holding that ref. 226 227 // Conduct the store test. 228 MockStorageDelegate delegate; 229 EXPECT_TRUE(storage->stored_caches_.empty()); 230 EXPECT_TRUE(storage->stored_groups_.empty()); 231 storage->StoreGroupAndNewestCache(group.get(), cache.get(), &delegate); 232 EXPECT_FALSE(delegate.stored_group_success_); 233 EXPECT_TRUE(storage->stored_caches_.empty()); 234 EXPECT_TRUE(storage->stored_groups_.empty()); 235 base::RunLoop().RunUntilIdle(); // Do async task execution. 236 EXPECT_TRUE(delegate.stored_group_success_); 237 EXPECT_FALSE(storage->stored_caches_.empty()); 238 EXPECT_FALSE(storage->stored_groups_.empty()); 239 EXPECT_EQ(cache, group->newest_complete_cache()); 240 EXPECT_TRUE(cache->is_complete()); 241 } 242 243 TEST_F(MockAppCacheStorageTest, StoreExistingGroup) { 244 // Store a group and its newest cache. Should complete asyncly. 245 MockAppCacheService service; 246 MockAppCacheStorage* storage = 247 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 248 249 // Setup some preconditions. Create a group and old complete cache 250 // that appear to be "stored", and a newest unstored complete cache. 251 GURL manifest_url("http://blah/"); 252 scoped_refptr<AppCacheGroup> group( 253 new AppCacheGroup(service.storage(), manifest_url, 111)); 254 int64 old_cache_id = storage->NewCacheId(); 255 scoped_refptr<AppCache> old_cache( 256 new AppCache(service.storage(), old_cache_id)); 257 old_cache->set_complete(true); 258 group->AddCache(old_cache.get()); 259 storage->AddStoredGroup(group.get()); 260 storage->AddStoredCache(old_cache.get()); 261 int64 new_cache_id = storage->NewCacheId(); 262 scoped_refptr<AppCache> new_cache( 263 new AppCache(service.storage(), new_cache_id)); 264 // Hold our refs to simulate the UpdateJob holding these refs. 265 266 // Conduct the test. 267 MockStorageDelegate delegate; 268 EXPECT_EQ(size_t(1), storage->stored_caches_.size()); 269 EXPECT_EQ(size_t(1), storage->stored_groups_.size()); 270 EXPECT_TRUE(storage->IsCacheStored(old_cache.get())); 271 EXPECT_FALSE(storage->IsCacheStored(new_cache.get())); 272 storage->StoreGroupAndNewestCache(group.get(), new_cache.get(), &delegate); 273 EXPECT_FALSE(delegate.stored_group_success_); 274 EXPECT_EQ(size_t(1), storage->stored_caches_.size()); 275 EXPECT_EQ(size_t(1), storage->stored_groups_.size()); 276 EXPECT_TRUE(storage->IsCacheStored(old_cache.get())); 277 EXPECT_FALSE(storage->IsCacheStored(new_cache.get())); 278 base::RunLoop().RunUntilIdle(); // Do async task execution. 279 EXPECT_TRUE(delegate.stored_group_success_); 280 EXPECT_EQ(size_t(1), storage->stored_caches_.size()); 281 EXPECT_EQ(size_t(1), storage->stored_groups_.size()); 282 EXPECT_FALSE(storage->IsCacheStored(old_cache.get())); 283 EXPECT_TRUE(storage->IsCacheStored(new_cache.get())); 284 EXPECT_EQ(new_cache.get(), group->newest_complete_cache()); 285 EXPECT_TRUE(new_cache->is_complete()); 286 } 287 288 TEST_F(MockAppCacheStorageTest, StoreExistingGroupExistingCache) { 289 // Store a group with updates to its existing newest complete cache. 290 MockAppCacheService service; 291 MockAppCacheStorage* storage = 292 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 293 294 // Setup some preconditions. Create a group and a complete cache that 295 // appear to be "stored". 296 GURL manifest_url("http://blah"); 297 scoped_refptr<AppCacheGroup> group( 298 new AppCacheGroup(service.storage(), manifest_url, 111)); 299 int64 cache_id = storage->NewCacheId(); 300 scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); 301 cache->set_complete(true); 302 group->AddCache(cache.get()); 303 storage->AddStoredGroup(group.get()); 304 storage->AddStoredCache(cache.get()); 305 // Hold our refs to simulate the UpdateJob holding these refs. 306 307 // Change the group's newest cache. 308 EXPECT_EQ(cache, group->newest_complete_cache()); 309 GURL entry_url("http://blah/blah"); 310 cache->AddEntry(entry_url, AppCacheEntry(AppCacheEntry::MASTER)); 311 312 // Conduct the test. 313 MockStorageDelegate delegate; 314 EXPECT_EQ(size_t(1), storage->stored_caches_.size()); 315 EXPECT_EQ(size_t(1), storage->stored_groups_.size()); 316 EXPECT_TRUE(storage->IsCacheStored(cache.get())); 317 storage->StoreGroupAndNewestCache(group.get(), cache.get(), &delegate); 318 EXPECT_FALSE(delegate.stored_group_success_); 319 EXPECT_EQ(size_t(1), storage->stored_caches_.size()); 320 EXPECT_EQ(size_t(1), storage->stored_groups_.size()); 321 base::RunLoop().RunUntilIdle(); // Do async task execution. 322 EXPECT_TRUE(delegate.stored_group_success_); 323 EXPECT_EQ(size_t(1), storage->stored_caches_.size()); 324 EXPECT_EQ(size_t(1), storage->stored_groups_.size()); 325 EXPECT_TRUE(storage->IsCacheStored(cache.get())); 326 EXPECT_EQ(cache, group->newest_complete_cache()); 327 EXPECT_TRUE(cache->GetEntry(entry_url)); 328 } 329 330 TEST_F(MockAppCacheStorageTest, MakeGroupObsolete) { 331 // Make a group obsolete, should complete asyncly. 332 MockAppCacheService service; 333 MockAppCacheStorage* storage = 334 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 335 336 // Setup some preconditions. Create a group and newest cache that 337 // appears to be "stored" and "currently in use". 338 GURL manifest_url("http://blah/"); 339 scoped_refptr<AppCacheGroup> group( 340 new AppCacheGroup(service.storage(), manifest_url, 111)); 341 int64 cache_id = storage->NewCacheId(); 342 scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); 343 cache->set_complete(true); 344 group->AddCache(cache.get()); 345 storage->AddStoredGroup(group.get()); 346 storage->AddStoredCache(cache.get()); 347 // Hold our refs to simulate the UpdateJob holding these refs. 348 349 // Conduct the test. 350 MockStorageDelegate delegate; 351 EXPECT_FALSE(group->is_obsolete()); 352 EXPECT_EQ(size_t(1), storage->stored_caches_.size()); 353 EXPECT_EQ(size_t(1), storage->stored_groups_.size()); 354 EXPECT_FALSE(cache->HasOneRef()); 355 EXPECT_FALSE(group->HasOneRef()); 356 storage->MakeGroupObsolete(group.get(), &delegate); 357 EXPECT_FALSE(group->is_obsolete()); 358 EXPECT_EQ(size_t(1), storage->stored_caches_.size()); 359 EXPECT_EQ(size_t(1), storage->stored_groups_.size()); 360 EXPECT_FALSE(cache->HasOneRef()); 361 EXPECT_FALSE(group->HasOneRef()); 362 base::RunLoop().RunUntilIdle(); // Do async task execution. 363 EXPECT_TRUE(delegate.obsoleted_success_); 364 EXPECT_EQ(group.get(), delegate.obsoleted_group_.get()); 365 EXPECT_TRUE(group->is_obsolete()); 366 EXPECT_TRUE(storage->stored_caches_.empty()); 367 EXPECT_TRUE(storage->stored_groups_.empty()); 368 EXPECT_TRUE(cache->HasOneRef()); 369 EXPECT_FALSE(group->HasOneRef()); 370 delegate.obsoleted_group_ = NULL; 371 cache = NULL; 372 EXPECT_TRUE(group->HasOneRef()); 373 } 374 375 TEST_F(MockAppCacheStorageTest, MarkEntryAsForeign) { 376 // Should complete syncly. 377 MockAppCacheService service; 378 MockAppCacheStorage* storage = 379 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 380 381 // Setup some preconditions. Create a cache with an entry. 382 GURL entry_url("http://blah/entry"); 383 int64 cache_id = storage->NewCacheId(); 384 scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); 385 cache->AddEntry(entry_url, AppCacheEntry(AppCacheEntry::EXPLICIT)); 386 387 // Conduct the test. 388 MockStorageDelegate delegate; 389 EXPECT_FALSE(cache->GetEntry(entry_url)->IsForeign()); 390 storage->MarkEntryAsForeign(entry_url, cache_id); 391 EXPECT_TRUE(cache->GetEntry(entry_url)->IsForeign()); 392 EXPECT_TRUE(cache->GetEntry(entry_url)->IsExplicit()); 393 } 394 395 TEST_F(MockAppCacheStorageTest, FindNoMainResponse) { 396 // Should complete asyncly. 397 MockAppCacheService service; 398 MockAppCacheStorage* storage = 399 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 400 401 // Conduct the test. 402 MockStorageDelegate delegate; 403 GURL url("http://blah/some_url"); 404 EXPECT_NE(url, delegate.found_url_); 405 storage->FindResponseForMainRequest(url, GURL(), &delegate); 406 EXPECT_NE(url, delegate.found_url_); 407 base::RunLoop().RunUntilIdle(); // Do async task execution. 408 EXPECT_EQ(url, delegate.found_url_); 409 EXPECT_TRUE(delegate.found_manifest_url_.is_empty()); 410 EXPECT_EQ(kNoCacheId, delegate.found_cache_id_); 411 EXPECT_EQ(kNoResponseId, delegate.found_entry_.response_id()); 412 EXPECT_EQ(kNoResponseId, delegate.found_fallback_entry_.response_id()); 413 EXPECT_TRUE(delegate.found_fallback_url_.is_empty()); 414 EXPECT_EQ(0, delegate.found_entry_.types()); 415 EXPECT_EQ(0, delegate.found_fallback_entry_.types()); 416 } 417 418 TEST_F(MockAppCacheStorageTest, BasicFindMainResponse) { 419 // Should complete asyncly. 420 MockAppCacheService service; 421 MockAppCacheStorage* storage = 422 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 423 424 // Setup some preconditions. Create a complete cache with an entry. 425 const int64 kCacheId = storage->NewCacheId(); 426 const GURL kEntryUrl("http://blah/entry"); 427 const GURL kManifestUrl("http://blah/manifest"); 428 const int64 kResponseId = 1; 429 scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId)); 430 cache->AddEntry( 431 kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId)); 432 cache->set_complete(true); 433 scoped_refptr<AppCacheGroup> group( 434 new AppCacheGroup(service.storage(), kManifestUrl, 111)); 435 group->AddCache(cache.get()); 436 storage->AddStoredGroup(group.get()); 437 storage->AddStoredCache(cache.get()); 438 439 // Conduct the test. 440 MockStorageDelegate delegate; 441 EXPECT_NE(kEntryUrl, delegate.found_url_); 442 storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate); 443 EXPECT_NE(kEntryUrl, delegate.found_url_); 444 base::RunLoop().RunUntilIdle(); // Do async task execution. 445 EXPECT_EQ(kEntryUrl, delegate.found_url_); 446 EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_); 447 EXPECT_EQ(kCacheId, delegate.found_cache_id_); 448 EXPECT_EQ(kResponseId, delegate.found_entry_.response_id()); 449 EXPECT_TRUE(delegate.found_entry_.IsExplicit()); 450 EXPECT_FALSE(delegate.found_fallback_entry_.has_response_id()); 451 } 452 453 TEST_F(MockAppCacheStorageTest, BasicFindMainFallbackResponse) { 454 // Should complete asyncly. 455 MockAppCacheService service; 456 MockAppCacheStorage* storage = 457 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 458 459 // Setup some preconditions. Create a complete cache with a 460 // fallback namespace and entry. 461 const int64 kCacheId = storage->NewCacheId(); 462 const GURL kFallbackEntryUrl1("http://blah/fallback_entry1"); 463 const GURL kFallbackNamespaceUrl1("http://blah/fallback_namespace/"); 464 const GURL kFallbackEntryUrl2("http://blah/fallback_entry2"); 465 const GURL kFallbackNamespaceUrl2("http://blah/fallback_namespace/longer"); 466 const GURL kManifestUrl("http://blah/manifest"); 467 const int64 kResponseId1 = 1; 468 const int64 kResponseId2 = 2; 469 470 Manifest manifest; 471 manifest.fallback_namespaces.push_back( 472 Namespace(FALLBACK_NAMESPACE, kFallbackNamespaceUrl1, 473 kFallbackEntryUrl1, false)); 474 manifest.fallback_namespaces.push_back( 475 Namespace(FALLBACK_NAMESPACE, kFallbackNamespaceUrl2, 476 kFallbackEntryUrl2, false)); 477 478 scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId)); 479 cache->InitializeWithManifest(&manifest); 480 cache->AddEntry(kFallbackEntryUrl1, 481 AppCacheEntry(AppCacheEntry::FALLBACK, kResponseId1)); 482 cache->AddEntry(kFallbackEntryUrl2, 483 AppCacheEntry(AppCacheEntry::FALLBACK, kResponseId2)); 484 cache->set_complete(true); 485 486 scoped_refptr<AppCacheGroup> group( 487 new AppCacheGroup(service.storage(), kManifestUrl, 111)); 488 group->AddCache(cache.get()); 489 storage->AddStoredGroup(group.get()); 490 storage->AddStoredCache(cache.get()); 491 492 // The test url is in both fallback namespace urls, but should match 493 // the longer of the two. 494 const GURL kTestUrl("http://blah/fallback_namespace/longer/test"); 495 496 // Conduct the test. 497 MockStorageDelegate delegate; 498 EXPECT_NE(kTestUrl, delegate.found_url_); 499 storage->FindResponseForMainRequest(kTestUrl, GURL(), &delegate); 500 EXPECT_NE(kTestUrl, delegate.found_url_); 501 base::RunLoop().RunUntilIdle(); // Do async task execution. 502 EXPECT_EQ(kTestUrl, delegate.found_url_); 503 EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_); 504 EXPECT_EQ(kCacheId, delegate.found_cache_id_); 505 EXPECT_FALSE(delegate.found_entry_.has_response_id()); 506 EXPECT_EQ(kResponseId2, delegate.found_fallback_entry_.response_id()); 507 EXPECT_EQ(kFallbackEntryUrl2, delegate.found_fallback_url_); 508 EXPECT_TRUE(delegate.found_fallback_entry_.IsFallback()); 509 } 510 511 TEST_F(MockAppCacheStorageTest, FindMainResponseWithMultipleCandidates) { 512 // Should complete asyncly. 513 MockAppCacheService service; 514 MockAppCacheStorage* storage = 515 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 516 517 // Setup some preconditions. Create 2 complete caches with an entry 518 // for the same url. 519 520 const GURL kEntryUrl("http://blah/entry"); 521 const int64 kCacheId1 = storage->NewCacheId(); 522 const int64 kCacheId2 = storage->NewCacheId(); 523 const GURL kManifestUrl1("http://blah/manifest1"); 524 const GURL kManifestUrl2("http://blah/manifest2"); 525 const int64 kResponseId1 = 1; 526 const int64 kResponseId2 = 2; 527 528 // The first cache. 529 scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId1)); 530 cache->AddEntry( 531 kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId1)); 532 cache->set_complete(true); 533 scoped_refptr<AppCacheGroup> group( 534 new AppCacheGroup(service.storage(), kManifestUrl1, 111)); 535 group->AddCache(cache.get()); 536 storage->AddStoredGroup(group.get()); 537 storage->AddStoredCache(cache.get()); 538 // Drop our references to cache1 so it appears as "not in use". 539 cache = NULL; 540 group = NULL; 541 542 // The second cache. 543 cache = new AppCache(service.storage(), kCacheId2); 544 cache->AddEntry( 545 kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId2)); 546 cache->set_complete(true); 547 group = new AppCacheGroup(service.storage(), kManifestUrl2, 222); 548 group->AddCache(cache.get()); 549 storage->AddStoredGroup(group.get()); 550 storage->AddStoredCache(cache.get()); 551 552 // Conduct the test, we should find the response from the second cache 553 // since it's "in use". 554 MockStorageDelegate delegate; 555 EXPECT_NE(kEntryUrl, delegate.found_url_); 556 storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate); 557 EXPECT_NE(kEntryUrl, delegate.found_url_); 558 base::RunLoop().RunUntilIdle(); // Do async task execution. 559 EXPECT_EQ(kEntryUrl, delegate.found_url_); 560 EXPECT_EQ(kManifestUrl2, delegate.found_manifest_url_); 561 EXPECT_EQ(kCacheId2, delegate.found_cache_id_); 562 EXPECT_EQ(kResponseId2, delegate.found_entry_.response_id()); 563 EXPECT_TRUE(delegate.found_entry_.IsExplicit()); 564 EXPECT_FALSE(delegate.found_fallback_entry_.has_response_id()); 565 } 566 567 TEST_F(MockAppCacheStorageTest, FindMainResponseExclusions) { 568 // Should complete asyncly. 569 MockAppCacheService service; 570 MockAppCacheStorage* storage = 571 reinterpret_cast<MockAppCacheStorage*>(service.storage()); 572 573 // Setup some preconditions. Create a complete cache with a 574 // foreign entry and an online namespace. 575 576 const int64 kCacheId = storage->NewCacheId(); 577 const GURL kEntryUrl("http://blah/entry"); 578 const GURL kManifestUrl("http://blah/manifest"); 579 const GURL kOnlineNamespaceUrl("http://blah/online_namespace"); 580 const int64 kResponseId = 1; 581 582 Manifest manifest; 583 manifest.online_whitelist_namespaces.push_back( 584 Namespace(NETWORK_NAMESPACE, kOnlineNamespaceUrl, 585 GURL(), false)); 586 scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId)); 587 cache->InitializeWithManifest(&manifest); 588 cache->AddEntry( 589 kEntryUrl, 590 AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN, 591 kResponseId)); 592 cache->set_complete(true); 593 scoped_refptr<AppCacheGroup> group( 594 new AppCacheGroup(service.storage(), kManifestUrl, 111)); 595 group->AddCache(cache.get()); 596 storage->AddStoredGroup(group.get()); 597 storage->AddStoredCache(cache.get()); 598 599 MockStorageDelegate delegate; 600 601 // We should not find anything for the foreign entry. 602 EXPECT_NE(kEntryUrl, delegate.found_url_); 603 storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate); 604 EXPECT_NE(kEntryUrl, delegate.found_url_); 605 base::RunLoop().RunUntilIdle(); // Do async task execution. 606 EXPECT_EQ(kEntryUrl, delegate.found_url_); 607 EXPECT_TRUE(delegate.found_manifest_url_.is_empty()); 608 EXPECT_EQ(kNoCacheId, delegate.found_cache_id_); 609 EXPECT_EQ(kNoResponseId, delegate.found_entry_.response_id()); 610 EXPECT_EQ(kNoResponseId, delegate.found_fallback_entry_.response_id()); 611 EXPECT_TRUE(delegate.found_fallback_url_.is_empty()); 612 EXPECT_EQ(0, delegate.found_entry_.types()); 613 EXPECT_EQ(0, delegate.found_fallback_entry_.types()); 614 615 // We should not find anything for the online namespace. 616 EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_); 617 storage->FindResponseForMainRequest(kOnlineNamespaceUrl, GURL(), &delegate); 618 EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_); 619 base::RunLoop().RunUntilIdle(); // Do async task execution. 620 EXPECT_EQ(kOnlineNamespaceUrl, delegate.found_url_); 621 EXPECT_TRUE(delegate.found_manifest_url_.is_empty()); 622 EXPECT_EQ(kNoCacheId, delegate.found_cache_id_); 623 EXPECT_EQ(kNoResponseId, delegate.found_entry_.response_id()); 624 EXPECT_EQ(kNoResponseId, delegate.found_fallback_entry_.response_id()); 625 EXPECT_TRUE(delegate.found_fallback_url_.is_empty()); 626 EXPECT_EQ(0, delegate.found_entry_.types()); 627 EXPECT_EQ(0, delegate.found_fallback_entry_.types()); 628 } 629 630 } // namespace appcache 631