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