Home | History | Annotate | Download | only in appcache
      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 <stack>
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/callback.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/synchronization/waitable_event.h"
     12 #include "base/threading/thread.h"
     13 #include "net/base/net_errors.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 #include "webkit/browser/appcache/appcache.h"
     16 #include "webkit/browser/appcache/appcache_database.h"
     17 #include "webkit/browser/appcache/appcache_entry.h"
     18 #include "webkit/browser/appcache/appcache_group.h"
     19 #include "webkit/browser/appcache/appcache_service.h"
     20 #include "webkit/browser/appcache/appcache_storage_impl.h"
     21 #include "webkit/browser/quota/quota_manager.h"
     22 
     23 namespace appcache {
     24 
     25 namespace {
     26 
     27 const base::Time kZeroTime;
     28 const GURL kManifestUrl("http://blah/manifest");
     29 const GURL kManifestUrl2("http://blah/manifest2");
     30 const GURL kManifestUrl3("http://blah/manifest3");
     31 const GURL kEntryUrl("http://blah/entry");
     32 const GURL kEntryUrl2("http://blah/entry2");
     33 const GURL kFallbackNamespace("http://blah/fallback_namespace/");
     34 const GURL kFallbackNamespace2("http://blah/fallback_namespace/longer");
     35 const GURL kFallbackTestUrl("http://blah/fallback_namespace/longer/test");
     36 const GURL kOnlineNamespace("http://blah/online_namespace");
     37 const GURL kOnlineNamespaceWithinFallback(
     38     "http://blah/fallback_namespace/online/");
     39 const GURL kInterceptNamespace("http://blah/intercept_namespace/");
     40 const GURL kInterceptNamespace2("http://blah/intercept_namespace/longer/");
     41 const GURL kInterceptTestUrl("http://blah/intercept_namespace/longer/test");
     42 const GURL kInterceptPatternNamespace("http://blah/intercept_pattern/*/bar");
     43 const GURL kInterceptPatternTestPositiveUrl(
     44     "http://blah/intercept_pattern/foo/bar");
     45 const GURL kInterceptPatternTestNegativeUrl(
     46     "http://blah/intercept_pattern/foo/not_bar");
     47 const GURL kFallbackPatternNamespace("http://blah/fallback_pattern/*/bar");
     48 const GURL kFallbackPatternTestPositiveUrl(
     49     "http://blah/fallback_pattern/foo/bar");
     50 const GURL kFallbackPatternTestNegativeUrl(
     51     "http://blah/fallback_pattern/foo/not_bar");
     52 const GURL kOrigin(kManifestUrl.GetOrigin());
     53 
     54 const int kManifestEntryIdOffset = 100;
     55 const int kFallbackEntryIdOffset = 1000;
     56 
     57 const GURL kDefaultEntryUrl("http://blah/makecacheandgroup_default_entry");
     58 const int kDefaultEntrySize = 10;
     59 const int kDefaultEntryIdOffset = 12345;
     60 
     61 const int kMockQuota = 5000;
     62 
     63 scoped_ptr<base::Thread> io_thread;
     64 scoped_ptr<base::Thread> db_thread;
     65 
     66 }  // namespace
     67 
     68 class AppCacheStorageImplTest : public testing::Test {
     69  public:
     70   class MockStorageDelegate : public AppCacheStorage::Delegate {
     71    public:
     72     explicit MockStorageDelegate(AppCacheStorageImplTest* test)
     73         : loaded_cache_id_(0), stored_group_success_(false),
     74           would_exceed_quota_(false), obsoleted_success_(false),
     75           found_cache_id_(kNoCacheId), test_(test) {
     76     }
     77 
     78     virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) OVERRIDE {
     79       loaded_cache_ = cache;
     80       loaded_cache_id_ = cache_id;
     81       test_->ScheduleNextTask();
     82     }
     83 
     84     virtual void OnGroupLoaded(AppCacheGroup* group,
     85                                const GURL& manifest_url) OVERRIDE {
     86       loaded_group_ = group;
     87       loaded_manifest_url_ = manifest_url;
     88       loaded_groups_newest_cache_ = group ? group->newest_complete_cache()
     89                                           : NULL;
     90       test_->ScheduleNextTask();
     91     }
     92 
     93     virtual void OnGroupAndNewestCacheStored(
     94         AppCacheGroup* group, AppCache* newest_cache, bool success,
     95         bool would_exceed_quota) OVERRIDE {
     96       stored_group_ = group;
     97       stored_group_success_ = success;
     98       would_exceed_quota_ = would_exceed_quota;
     99       test_->ScheduleNextTask();
    100     }
    101 
    102     virtual void OnGroupMadeObsolete(AppCacheGroup* group,
    103                                      bool success) OVERRIDE {
    104       obsoleted_group_ = group;
    105       obsoleted_success_ = success;
    106       test_->ScheduleNextTask();
    107     }
    108 
    109     virtual void OnMainResponseFound(const GURL& url,
    110                                      const AppCacheEntry& entry,
    111                                      const GURL& namespace_entry_url,
    112                                      const AppCacheEntry& fallback_entry,
    113                                      int64 cache_id,
    114                                      int64 group_id,
    115                                      const GURL& manifest_url) OVERRIDE {
    116       found_url_ = url;
    117       found_entry_ = entry;
    118       found_namespace_entry_url_ = namespace_entry_url;
    119       found_fallback_entry_ = fallback_entry;
    120       found_cache_id_ = cache_id;
    121       found_group_id_ = group_id;
    122       found_manifest_url_ = manifest_url;
    123       test_->ScheduleNextTask();
    124     }
    125 
    126     scoped_refptr<AppCache> loaded_cache_;
    127     int64 loaded_cache_id_;
    128     scoped_refptr<AppCacheGroup> loaded_group_;
    129     GURL loaded_manifest_url_;
    130     scoped_refptr<AppCache> loaded_groups_newest_cache_;
    131     scoped_refptr<AppCacheGroup> stored_group_;
    132     bool stored_group_success_;
    133     bool would_exceed_quota_;
    134     scoped_refptr<AppCacheGroup> obsoleted_group_;
    135     bool obsoleted_success_;
    136     GURL found_url_;
    137     AppCacheEntry found_entry_;
    138     GURL found_namespace_entry_url_;
    139     AppCacheEntry found_fallback_entry_;
    140     int64 found_cache_id_;
    141     int64 found_group_id_;
    142     GURL found_manifest_url_;
    143     AppCacheStorageImplTest* test_;
    144   };
    145 
    146   class MockQuotaManager : public quota::QuotaManager {
    147    public:
    148     MockQuotaManager()
    149         : QuotaManager(true /* is_incognito */,
    150                        base::FilePath(),
    151                        io_thread->message_loop_proxy().get(),
    152                        db_thread->message_loop_proxy().get(),
    153                        NULL),
    154           async_(false) {}
    155 
    156     virtual void GetUsageAndQuota(
    157         const GURL& origin,
    158         quota::StorageType type,
    159         const GetUsageAndQuotaCallback& callback) OVERRIDE {
    160       EXPECT_EQ(kOrigin, origin);
    161       EXPECT_EQ(quota::kStorageTypeTemporary, type);
    162       if (async_) {
    163         base::MessageLoop::current()->PostTask(
    164             FROM_HERE,
    165             base::Bind(&MockQuotaManager::CallCallback,
    166                        base::Unretained(this),
    167                        callback));
    168         return;
    169       }
    170       CallCallback(callback);
    171     }
    172 
    173     void CallCallback(const GetUsageAndQuotaCallback& callback) {
    174       callback.Run(quota::kQuotaStatusOk, 0, kMockQuota);
    175     }
    176 
    177     bool async_;
    178 
    179    protected:
    180     virtual ~MockQuotaManager() {}
    181   };
    182 
    183   class MockQuotaManagerProxy : public quota::QuotaManagerProxy {
    184    public:
    185     MockQuotaManagerProxy()
    186         : QuotaManagerProxy(NULL, NULL),
    187           notify_storage_accessed_count_(0),
    188           notify_storage_modified_count_(0),
    189           last_delta_(0),
    190           mock_manager_(new MockQuotaManager) {
    191       manager_ = mock_manager_.get();
    192     }
    193 
    194     virtual void NotifyStorageAccessed(quota::QuotaClient::ID client_id,
    195                                        const GURL& origin,
    196                                        quota::StorageType type) OVERRIDE {
    197       EXPECT_EQ(quota::QuotaClient::kAppcache, client_id);
    198       EXPECT_EQ(quota::kStorageTypeTemporary, type);
    199       ++notify_storage_accessed_count_;
    200       last_origin_ = origin;
    201     }
    202 
    203     virtual void NotifyStorageModified(quota::QuotaClient::ID client_id,
    204                                        const GURL& origin,
    205                                        quota::StorageType type,
    206                                        int64 delta) OVERRIDE {
    207       EXPECT_EQ(quota::QuotaClient::kAppcache, client_id);
    208       EXPECT_EQ(quota::kStorageTypeTemporary, type);
    209       ++notify_storage_modified_count_;
    210       last_origin_ = origin;
    211       last_delta_ = delta;
    212     }
    213 
    214     // Not needed for our tests.
    215     virtual void RegisterClient(quota::QuotaClient* client) OVERRIDE {}
    216     virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {}
    217     virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {}
    218 
    219     int notify_storage_accessed_count_;
    220     int notify_storage_modified_count_;
    221     GURL last_origin_;
    222     int last_delta_;
    223     scoped_refptr<MockQuotaManager> mock_manager_;
    224 
    225    protected:
    226     virtual ~MockQuotaManagerProxy() {}
    227   };
    228 
    229   template <class Method>
    230   void RunMethod(Method method) {
    231     (this->*method)();
    232   }
    233 
    234   // Helper callback to run a test on our io_thread. The io_thread is spun up
    235   // once and reused for all tests.
    236   template <class Method>
    237   void MethodWrapper(Method method) {
    238     SetUpTest();
    239 
    240     // Ensure InitTask execution prior to conducting a test.
    241     FlushDbThreadTasks();
    242 
    243     // We also have to wait for InitTask completion call to be performed
    244     // on the IO thread prior to running the test. Its guaranteed to be
    245     // queued by this time.
    246     base::MessageLoop::current()->PostTask(
    247         FROM_HERE,
    248         base::Bind(&AppCacheStorageImplTest::RunMethod<Method>,
    249                    base::Unretained(this),
    250                    method));
    251   }
    252 
    253   static void SetUpTestCase() {
    254     io_thread.reset(new base::Thread("AppCacheTest.IOThread"));
    255     base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
    256     ASSERT_TRUE(io_thread->StartWithOptions(options));
    257 
    258     db_thread.reset(new base::Thread("AppCacheTest::DBThread"));
    259     ASSERT_TRUE(db_thread->Start());
    260   }
    261 
    262   static void TearDownTestCase() {
    263     io_thread.reset(NULL);
    264     db_thread.reset(NULL);
    265   }
    266 
    267   // Test harness --------------------------------------------------
    268 
    269   AppCacheStorageImplTest() {
    270   }
    271 
    272   template <class Method>
    273   void RunTestOnIOThread(Method method) {
    274     test_finished_event_ .reset(new base::WaitableEvent(false, false));
    275     io_thread->message_loop()->PostTask(
    276         FROM_HERE, base::Bind(&AppCacheStorageImplTest::MethodWrapper<Method>,
    277                               base::Unretained(this), method));
    278     test_finished_event_->Wait();
    279   }
    280 
    281   void SetUpTest() {
    282     DCHECK(base::MessageLoop::current() == io_thread->message_loop());
    283     service_.reset(new AppCacheService(NULL));
    284     service_->Initialize(
    285         base::FilePath(), db_thread->message_loop_proxy().get(), NULL);
    286     mock_quota_manager_proxy_ = new MockQuotaManagerProxy();
    287     service_->quota_manager_proxy_ = mock_quota_manager_proxy_;
    288     delegate_.reset(new MockStorageDelegate(this));
    289   }
    290 
    291   void TearDownTest() {
    292     DCHECK(base::MessageLoop::current() == io_thread->message_loop());
    293     storage()->CancelDelegateCallbacks(delegate());
    294     group_ = NULL;
    295     cache_ = NULL;
    296     cache2_ = NULL;
    297     mock_quota_manager_proxy_ = NULL;
    298     delegate_.reset();
    299     service_.reset();
    300     FlushDbThreadTasks();
    301   }
    302 
    303   void TestFinished() {
    304     // We unwind the stack prior to finishing up to let stack
    305     // based objects get deleted.
    306     DCHECK(base::MessageLoop::current() == io_thread->message_loop());
    307     base::MessageLoop::current()->PostTask(
    308         FROM_HERE,
    309         base::Bind(&AppCacheStorageImplTest::TestFinishedUnwound,
    310                    base::Unretained(this)));
    311   }
    312 
    313   void TestFinishedUnwound() {
    314     TearDownTest();
    315     test_finished_event_->Signal();
    316   }
    317 
    318   void PushNextTask(const base::Closure& task) {
    319     task_stack_.push(task);
    320   }
    321 
    322   void ScheduleNextTask() {
    323     DCHECK(base::MessageLoop::current() == io_thread->message_loop());
    324     if (task_stack_.empty()) {
    325       return;
    326     }
    327     base::MessageLoop::current()->PostTask(FROM_HERE, task_stack_.top());
    328     task_stack_.pop();
    329   }
    330 
    331   static void SignalEvent(base::WaitableEvent* event) {
    332     event->Signal();
    333   }
    334 
    335   void FlushDbThreadTasks() {
    336     // We pump a task thru the db thread to ensure any tasks previously
    337     // scheduled on that thread have been performed prior to return.
    338     base::WaitableEvent event(false, false);
    339     db_thread->message_loop()->PostTask(
    340         FROM_HERE, base::Bind(&AppCacheStorageImplTest::SignalEvent, &event));
    341     event.Wait();
    342   }
    343 
    344   // LoadCache_Miss ----------------------------------------------------
    345 
    346   void LoadCache_Miss() {
    347     // Attempt to load a cache that doesn't exist. Should
    348     // complete asynchronously.
    349     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_LoadCache_Miss,
    350                             base::Unretained(this)));
    351 
    352     storage()->LoadCache(111, delegate());
    353     EXPECT_NE(111, delegate()->loaded_cache_id_);
    354   }
    355 
    356   void Verify_LoadCache_Miss() {
    357     EXPECT_EQ(111, delegate()->loaded_cache_id_);
    358     EXPECT_FALSE(delegate()->loaded_cache_.get());
    359     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    360     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    361     TestFinished();
    362   }
    363 
    364   // LoadCache_NearHit -------------------------------------------------
    365 
    366   void LoadCache_NearHit() {
    367     // Attempt to load a cache that is currently in use
    368     // and does not require loading from storage. This
    369     // load should complete syncly.
    370 
    371     // Setup some preconditions. Make an 'unstored' cache for
    372     // us to load. The ctor should put it in the working set.
    373     int64 cache_id = storage()->NewCacheId();
    374     scoped_refptr<AppCache> cache(new AppCache(storage(), cache_id));
    375 
    376     // Conduct the test.
    377     storage()->LoadCache(cache_id, delegate());
    378     EXPECT_EQ(cache_id, delegate()->loaded_cache_id_);
    379     EXPECT_EQ(cache.get(), delegate()->loaded_cache_.get());
    380     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    381     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    382     TestFinished();
    383   }
    384 
    385   // CreateGroup  --------------------------------------------
    386 
    387   void CreateGroupInEmptyOrigin() {
    388     // Attempt to load a group that doesn't exist, one should
    389     // be created for us, but not stored.
    390 
    391     // Since the origin has no groups, the storage class will respond
    392     // syncly.
    393     storage()->LoadOrCreateGroup(kManifestUrl, delegate());
    394     Verify_CreateGroup();
    395   }
    396 
    397   void CreateGroupInPopulatedOrigin() {
    398     // Attempt to load a group that doesn't exist, one should
    399     // be created for us, but not stored.
    400     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_CreateGroup,
    401                             base::Unretained(this)));
    402 
    403     // Since the origin has groups, storage class will have to
    404     // consult the database and completion will be async.
    405     storage()->usage_map_[kOrigin] = kDefaultEntrySize;
    406 
    407     storage()->LoadOrCreateGroup(kManifestUrl, delegate());
    408     EXPECT_FALSE(delegate()->loaded_group_.get());
    409   }
    410 
    411   void Verify_CreateGroup() {
    412     EXPECT_EQ(kManifestUrl, delegate()->loaded_manifest_url_);
    413     EXPECT_TRUE(delegate()->loaded_group_.get());
    414     EXPECT_TRUE(delegate()->loaded_group_->HasOneRef());
    415     EXPECT_FALSE(delegate()->loaded_group_->newest_complete_cache());
    416 
    417     // Should not have been stored in the database.
    418     AppCacheDatabase::GroupRecord record;
    419     EXPECT_FALSE(database()->FindGroup(
    420         delegate()->loaded_group_->group_id(), &record));
    421 
    422     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    423     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    424 
    425     TestFinished();
    426   }
    427 
    428   // LoadGroupAndCache_FarHit  --------------------------------------
    429 
    430   void LoadGroupAndCache_FarHit() {
    431     // Attempt to load a cache that is not currently in use
    432     // and does require loading from disk. This
    433     // load should complete asynchronously.
    434     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_LoadCache_Far_Hit,
    435                             base::Unretained(this)));
    436 
    437     // Setup some preconditions. Create a group and newest cache that
    438     // appear to be "stored" and "not currently in use".
    439     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    440     group_ = NULL;
    441     cache_ = NULL;
    442 
    443     // Conduct the cache load test, completes async
    444     storage()->LoadCache(1, delegate());
    445   }
    446 
    447   void Verify_LoadCache_Far_Hit() {
    448     EXPECT_TRUE(delegate()->loaded_cache_.get());
    449     EXPECT_TRUE(delegate()->loaded_cache_->HasOneRef());
    450     EXPECT_EQ(1, delegate()->loaded_cache_id_);
    451 
    452     // The group should also have been loaded.
    453     EXPECT_TRUE(delegate()->loaded_cache_->owning_group());
    454     EXPECT_TRUE(delegate()->loaded_cache_->owning_group()->HasOneRef());
    455     EXPECT_EQ(1, delegate()->loaded_cache_->owning_group()->group_id());
    456 
    457     EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    458     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    459 
    460     // Drop things from the working set.
    461     delegate()->loaded_cache_ = NULL;
    462     EXPECT_FALSE(delegate()->loaded_group_.get());
    463 
    464     // Conduct the group load test, also complete asynchronously.
    465     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_LoadGroup_Far_Hit,
    466                             base::Unretained(this)));
    467 
    468     storage()->LoadOrCreateGroup(kManifestUrl, delegate());
    469   }
    470 
    471   void Verify_LoadGroup_Far_Hit() {
    472     EXPECT_TRUE(delegate()->loaded_group_.get());
    473     EXPECT_EQ(kManifestUrl, delegate()->loaded_manifest_url_);
    474     EXPECT_TRUE(delegate()->loaded_group_->newest_complete_cache());
    475     delegate()->loaded_groups_newest_cache_ = NULL;
    476     EXPECT_TRUE(delegate()->loaded_group_->HasOneRef());
    477     EXPECT_EQ(2, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    478     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    479     TestFinished();
    480   }
    481 
    482   // StoreNewGroup  --------------------------------------
    483 
    484   void StoreNewGroup() {
    485     // Store a group and its newest cache. Should complete asynchronously.
    486     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_StoreNewGroup,
    487                             base::Unretained(this)));
    488 
    489     // Setup some preconditions. Create a group and newest cache that
    490     // appear to be "unstored".
    491     group_ = new AppCacheGroup(
    492         storage(), kManifestUrl, storage()->NewGroupId());
    493     cache_ = new AppCache(storage(), storage()->NewCacheId());
    494     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, 1,
    495                                               kDefaultEntrySize));
    496     // Hold a ref to the cache simulate the UpdateJob holding that ref,
    497     // and hold a ref to the group to simulate the CacheHost holding that ref.
    498 
    499     // Have the quota manager retrun asynchronously for this test.
    500     mock_quota_manager_proxy_->mock_manager_->async_ = true;
    501 
    502     // Conduct the store test.
    503     storage()->StoreGroupAndNewestCache(group_.get(), cache_.get(), delegate());
    504     EXPECT_FALSE(delegate()->stored_group_success_);
    505   }
    506 
    507   void Verify_StoreNewGroup() {
    508     EXPECT_TRUE(delegate()->stored_group_success_);
    509     EXPECT_EQ(group_.get(), delegate()->stored_group_.get());
    510     EXPECT_EQ(cache_.get(), group_->newest_complete_cache());
    511     EXPECT_TRUE(cache_->is_complete());
    512 
    513     // Should have been stored in the database.
    514     AppCacheDatabase::GroupRecord group_record;
    515     AppCacheDatabase::CacheRecord cache_record;
    516     EXPECT_TRUE(database()->FindGroup(group_->group_id(), &group_record));
    517     EXPECT_TRUE(database()->FindCache(cache_->cache_id(), &cache_record));
    518 
    519     // Verify quota bookkeeping
    520     EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
    521     EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
    522     EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
    523     EXPECT_EQ(kDefaultEntrySize, mock_quota_manager_proxy_->last_delta_);
    524 
    525     TestFinished();
    526   }
    527 
    528   // StoreExistingGroup  --------------------------------------
    529 
    530   void StoreExistingGroup() {
    531     // Store a group and its newest cache. Should complete asynchronously.
    532     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_StoreExistingGroup,
    533                             base::Unretained(this)));
    534 
    535     // Setup some preconditions. Create a group and old complete cache
    536     // that appear to be "stored"
    537     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    538     EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
    539 
    540     // And a newest unstored complete cache.
    541     cache2_ = new AppCache(storage(), 2);
    542     cache2_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::MASTER, 1,
    543                                                kDefaultEntrySize + 100));
    544 
    545     // Conduct the test.
    546     storage()->StoreGroupAndNewestCache(
    547         group_.get(), cache2_.get(), delegate());
    548     EXPECT_FALSE(delegate()->stored_group_success_);
    549   }
    550 
    551   void Verify_StoreExistingGroup() {
    552     EXPECT_TRUE(delegate()->stored_group_success_);
    553     EXPECT_EQ(group_.get(), delegate()->stored_group_.get());
    554     EXPECT_EQ(cache2_.get(), group_->newest_complete_cache());
    555     EXPECT_TRUE(cache2_->is_complete());
    556 
    557     // The new cache should have been stored in the database.
    558     AppCacheDatabase::GroupRecord group_record;
    559     AppCacheDatabase::CacheRecord cache_record;
    560     EXPECT_TRUE(database()->FindGroup(1, &group_record));
    561     EXPECT_TRUE(database()->FindCache(2, &cache_record));
    562 
    563     // The old cache should have been deleted
    564     EXPECT_FALSE(database()->FindCache(1, &cache_record));
    565 
    566     // Verify quota bookkeeping
    567     EXPECT_EQ(kDefaultEntrySize + 100, storage()->usage_map_[kOrigin]);
    568     EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
    569     EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
    570     EXPECT_EQ(100, mock_quota_manager_proxy_->last_delta_);
    571 
    572     TestFinished();
    573   }
    574 
    575   // StoreExistingGroupExistingCache  -------------------------------
    576 
    577   void StoreExistingGroupExistingCache() {
    578     // Store a group with updates to its existing newest complete cache.
    579     // Setup some preconditions. Create a group and a complete cache that
    580     // appear to be "stored".
    581 
    582     // Setup some preconditions. Create a group and old complete cache
    583     // that appear to be "stored"
    584     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    585     EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
    586 
    587     // Change the cache.
    588     base::Time now = base::Time::Now();
    589     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::MASTER, 1, 100));
    590     cache_->set_update_time(now);
    591 
    592     PushNextTask(base::Bind(
    593         &AppCacheStorageImplTest::Verify_StoreExistingGroupExistingCache,
    594         base::Unretained(this), now));
    595 
    596     // Conduct the test.
    597     EXPECT_EQ(cache_, group_->newest_complete_cache());
    598     storage()->StoreGroupAndNewestCache(group_.get(), cache_.get(), delegate());
    599     EXPECT_FALSE(delegate()->stored_group_success_);
    600   }
    601 
    602   void Verify_StoreExistingGroupExistingCache(
    603       base::Time expected_update_time) {
    604     EXPECT_TRUE(delegate()->stored_group_success_);
    605     EXPECT_EQ(cache_, group_->newest_complete_cache());
    606 
    607     AppCacheDatabase::CacheRecord cache_record;
    608     EXPECT_TRUE(database()->FindCache(1, &cache_record));
    609     EXPECT_EQ(1, cache_record.cache_id);
    610     EXPECT_EQ(1, cache_record.group_id);
    611     EXPECT_FALSE(cache_record.online_wildcard);
    612     EXPECT_TRUE(expected_update_time == cache_record.update_time);
    613     EXPECT_EQ(100 + kDefaultEntrySize, cache_record.cache_size);
    614 
    615     std::vector<AppCacheDatabase::EntryRecord> entry_records;
    616     EXPECT_TRUE(database()->FindEntriesForCache(1, &entry_records));
    617     EXPECT_EQ(2U, entry_records.size());
    618     if (entry_records[0].url == kDefaultEntryUrl)
    619       entry_records.erase(entry_records.begin());
    620     EXPECT_EQ(1 , entry_records[0].cache_id);
    621     EXPECT_EQ(kEntryUrl, entry_records[0].url);
    622     EXPECT_EQ(AppCacheEntry::MASTER, entry_records[0].flags);
    623     EXPECT_EQ(1, entry_records[0].response_id);
    624     EXPECT_EQ(100, entry_records[0].response_size);
    625 
    626     // Verify quota bookkeeping
    627     EXPECT_EQ(100 + kDefaultEntrySize, storage()->usage_map_[kOrigin]);
    628     EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
    629     EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
    630     EXPECT_EQ(100, mock_quota_manager_proxy_->last_delta_);
    631 
    632     TestFinished();
    633   }
    634 
    635   // FailStoreGroup  --------------------------------------
    636 
    637   void FailStoreGroup() {
    638     // Store a group and its newest cache. Should complete asynchronously.
    639     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_FailStoreGroup,
    640                             base::Unretained(this)));
    641 
    642     // Setup some preconditions. Create a group and newest cache that
    643     // appear to be "unstored" and big enough to exceed the 5M limit.
    644     const int64 kTooBig = 10 * 1024 * 1024;  // 10M
    645     group_ = new AppCacheGroup(
    646         storage(), kManifestUrl, storage()->NewGroupId());
    647     cache_ = new AppCache(storage(), storage()->NewCacheId());
    648     cache_->AddEntry(kManifestUrl,
    649                      AppCacheEntry(AppCacheEntry::MANIFEST, 1, kTooBig));
    650     // Hold a ref to the cache simulate the UpdateJob holding that ref,
    651     // and hold a ref to the group to simulate the CacheHost holding that ref.
    652 
    653     // Conduct the store test.
    654     storage()->StoreGroupAndNewestCache(group_.get(), cache_.get(), delegate());
    655     EXPECT_FALSE(delegate()->stored_group_success_);  // Expected to be async.
    656   }
    657 
    658   void Verify_FailStoreGroup() {
    659     EXPECT_FALSE(delegate()->stored_group_success_);
    660     EXPECT_TRUE(delegate()->would_exceed_quota_);
    661 
    662     // Should not have been stored in the database.
    663     AppCacheDatabase::GroupRecord group_record;
    664     AppCacheDatabase::CacheRecord cache_record;
    665     EXPECT_FALSE(database()->FindGroup(group_->group_id(), &group_record));
    666     EXPECT_FALSE(database()->FindCache(cache_->cache_id(), &cache_record));
    667 
    668     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    669     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    670 
    671     TestFinished();
    672   }
    673 
    674   // MakeGroupObsolete  -------------------------------
    675 
    676   void MakeGroupObsolete() {
    677     // Make a group obsolete, should complete asynchronously.
    678     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_MakeGroupObsolete,
    679                             base::Unretained(this)));
    680 
    681     // Setup some preconditions. Create a group and newest cache that
    682     // appears to be "stored" and "currently in use".
    683     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    684     EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
    685 
    686     // Also insert some related records.
    687     AppCacheDatabase::EntryRecord entry_record;
    688     entry_record.cache_id = 1;
    689     entry_record.flags = AppCacheEntry::FALLBACK;
    690     entry_record.response_id = 1;
    691     entry_record.url = kEntryUrl;
    692     EXPECT_TRUE(database()->InsertEntry(&entry_record));
    693 
    694     AppCacheDatabase::NamespaceRecord fallback_namespace_record;
    695     fallback_namespace_record.cache_id = 1;
    696     fallback_namespace_record.namespace_.target_url = kEntryUrl;
    697     fallback_namespace_record.namespace_.namespace_url = kFallbackNamespace;
    698     fallback_namespace_record.origin = kManifestUrl.GetOrigin();
    699     EXPECT_TRUE(database()->InsertNamespace(&fallback_namespace_record));
    700 
    701     AppCacheDatabase::OnlineWhiteListRecord online_whitelist_record;
    702     online_whitelist_record.cache_id = 1;
    703     online_whitelist_record.namespace_url = kOnlineNamespace;
    704     EXPECT_TRUE(database()->InsertOnlineWhiteList(&online_whitelist_record));
    705 
    706     // Conduct the test.
    707     storage()->MakeGroupObsolete(group_.get(), delegate());
    708     EXPECT_FALSE(group_->is_obsolete());
    709   }
    710 
    711   void Verify_MakeGroupObsolete() {
    712     EXPECT_TRUE(delegate()->obsoleted_success_);
    713     EXPECT_EQ(group_.get(), delegate()->obsoleted_group_.get());
    714     EXPECT_TRUE(group_->is_obsolete());
    715     EXPECT_TRUE(storage()->usage_map_.empty());
    716 
    717     // The cache and group have been deleted from the database.
    718     AppCacheDatabase::GroupRecord group_record;
    719     AppCacheDatabase::CacheRecord cache_record;
    720     EXPECT_FALSE(database()->FindGroup(1, &group_record));
    721     EXPECT_FALSE(database()->FindCache(1, &cache_record));
    722 
    723     // The related records should have been deleted too.
    724     std::vector<AppCacheDatabase::EntryRecord> entry_records;
    725     database()->FindEntriesForCache(1, &entry_records);
    726     EXPECT_TRUE(entry_records.empty());
    727     std::vector<AppCacheDatabase::NamespaceRecord> intercept_records;
    728     std::vector<AppCacheDatabase::NamespaceRecord> fallback_records;
    729     database()->FindNamespacesForCache(
    730         1, &intercept_records, &fallback_records);
    731     EXPECT_TRUE(fallback_records.empty());
    732     std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelist_records;
    733     database()->FindOnlineWhiteListForCache(1, &whitelist_records);
    734     EXPECT_TRUE(whitelist_records.empty());
    735 
    736     // Verify quota bookkeeping
    737     EXPECT_TRUE(storage()->usage_map_.empty());
    738     EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
    739     EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
    740     EXPECT_EQ(-kDefaultEntrySize, mock_quota_manager_proxy_->last_delta_);
    741 
    742     TestFinished();
    743   }
    744 
    745   // MarkEntryAsForeign  -------------------------------
    746 
    747   void MarkEntryAsForeign() {
    748     // Setup some preconditions. Create a cache with an entry
    749     // in storage and in the working set.
    750     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    751     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT));
    752     AppCacheDatabase::EntryRecord entry_record;
    753     entry_record.cache_id = 1;
    754     entry_record.url = kEntryUrl;
    755     entry_record.flags = AppCacheEntry::EXPLICIT;
    756     entry_record.response_id = 0;
    757     EXPECT_TRUE(database()->InsertEntry(&entry_record));
    758     EXPECT_FALSE(cache_->GetEntry(kEntryUrl)->IsForeign());
    759 
    760     // Conduct the test.
    761     storage()->MarkEntryAsForeign(kEntryUrl, 1);
    762 
    763     // The entry in the working set should have been updated syncly.
    764     EXPECT_TRUE(cache_->GetEntry(kEntryUrl)->IsForeign());
    765     EXPECT_TRUE(cache_->GetEntry(kEntryUrl)->IsExplicit());
    766 
    767     // And the entry in storage should also be updated, but that
    768     // happens asynchronously on the db thread.
    769     FlushDbThreadTasks();
    770     AppCacheDatabase::EntryRecord entry_record2;
    771     EXPECT_TRUE(database()->FindEntry(1, kEntryUrl, &entry_record2));
    772     EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN,
    773               entry_record2.flags);
    774     TestFinished();
    775   }
    776 
    777   // MarkEntryAsForeignWithLoadInProgress  -------------------------------
    778 
    779   void MarkEntryAsForeignWithLoadInProgress() {
    780     PushNextTask(base::Bind(
    781        &AppCacheStorageImplTest::Verify_MarkEntryAsForeignWithLoadInProgress,
    782        base::Unretained(this)));
    783 
    784     // Setup some preconditions. Create a cache with an entry
    785     // in storage, but not in the working set.
    786     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    787     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT));
    788     AppCacheDatabase::EntryRecord entry_record;
    789     entry_record.cache_id = 1;
    790     entry_record.url = kEntryUrl;
    791     entry_record.flags = AppCacheEntry::EXPLICIT;
    792     entry_record.response_id = 0;
    793     EXPECT_TRUE(database()->InsertEntry(&entry_record));
    794     EXPECT_FALSE(cache_->GetEntry(kEntryUrl)->IsForeign());
    795     EXPECT_TRUE(cache_->HasOneRef());
    796     cache_ = NULL;
    797     group_ = NULL;
    798 
    799     // Conduct the test, start a cache load, and prior to completion
    800     // of that load, mark the entry as foreign.
    801     storage()->LoadCache(1, delegate());
    802     storage()->MarkEntryAsForeign(kEntryUrl, 1);
    803   }
    804 
    805   void Verify_MarkEntryAsForeignWithLoadInProgress() {
    806     EXPECT_EQ(1, delegate()->loaded_cache_id_);
    807     EXPECT_TRUE(delegate()->loaded_cache_.get());
    808 
    809     // The entry in the working set should have been updated upon load.
    810     EXPECT_TRUE(delegate()->loaded_cache_->GetEntry(kEntryUrl)->IsForeign());
    811     EXPECT_TRUE(delegate()->loaded_cache_->GetEntry(kEntryUrl)->IsExplicit());
    812 
    813     // And the entry in storage should also be updated.
    814     FlushDbThreadTasks();
    815     AppCacheDatabase::EntryRecord entry_record;
    816     EXPECT_TRUE(database()->FindEntry(1, kEntryUrl, &entry_record));
    817     EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN,
    818               entry_record.flags);
    819     TestFinished();
    820   }
    821 
    822   // FindNoMainResponse  -------------------------------
    823 
    824   void FindNoMainResponse() {
    825     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_FindNoMainResponse,
    826                             base::Unretained(this)));
    827 
    828     // Conduct the test.
    829     storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
    830     EXPECT_NE(kEntryUrl, delegate()->found_url_);
    831   }
    832 
    833   void Verify_FindNoMainResponse() {
    834     EXPECT_EQ(kEntryUrl, delegate()->found_url_);
    835     EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
    836     EXPECT_EQ(kNoCacheId, delegate()->found_cache_id_);
    837     EXPECT_EQ(kNoResponseId, delegate()->found_entry_.response_id());
    838     EXPECT_EQ(kNoResponseId, delegate()->found_fallback_entry_.response_id());
    839     EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
    840     EXPECT_EQ(0, delegate()->found_entry_.types());
    841     EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
    842     TestFinished();
    843   }
    844 
    845   // BasicFindMainResponse  -------------------------------
    846 
    847   void BasicFindMainResponseInDatabase() {
    848     BasicFindMainResponse(true);
    849   }
    850 
    851   void BasicFindMainResponseInWorkingSet() {
    852     BasicFindMainResponse(false);
    853   }
    854 
    855   void BasicFindMainResponse(bool drop_from_working_set) {
    856     PushNextTask(base::Bind(
    857         &AppCacheStorageImplTest::Verify_BasicFindMainResponse,
    858         base::Unretained(this)));
    859 
    860     // Setup some preconditions. Create a complete cache with an entry
    861     // in storage.
    862     MakeCacheAndGroup(kManifestUrl, 2, 1, true);
    863     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, 1));
    864     AppCacheDatabase::EntryRecord entry_record;
    865     entry_record.cache_id = 1;
    866     entry_record.url = kEntryUrl;
    867     entry_record.flags = AppCacheEntry::EXPLICIT;
    868     entry_record.response_id = 1;
    869     EXPECT_TRUE(database()->InsertEntry(&entry_record));
    870 
    871     // Optionally drop the cache/group pair from the working set.
    872     if (drop_from_working_set) {
    873       EXPECT_TRUE(cache_->HasOneRef());
    874       cache_ = NULL;
    875       EXPECT_TRUE(group_->HasOneRef());
    876       group_ = NULL;
    877     }
    878 
    879     // Conduct the test.
    880     storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
    881     EXPECT_NE(kEntryUrl,  delegate()->found_url_);
    882   }
    883 
    884   void Verify_BasicFindMainResponse() {
    885     EXPECT_EQ(kEntryUrl, delegate()->found_url_);
    886     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
    887     EXPECT_EQ(1, delegate()->found_cache_id_);
    888     EXPECT_EQ(2, delegate()->found_group_id_);
    889     EXPECT_EQ(1, delegate()->found_entry_.response_id());
    890     EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
    891     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
    892     TestFinished();
    893   }
    894 
    895   // BasicFindMainFallbackResponse  -------------------------------
    896 
    897   void BasicFindMainFallbackResponseInDatabase() {
    898     BasicFindMainFallbackResponse(true);
    899   }
    900 
    901   void BasicFindMainFallbackResponseInWorkingSet() {
    902     BasicFindMainFallbackResponse(false);
    903   }
    904 
    905   void BasicFindMainFallbackResponse(bool drop_from_working_set) {
    906     PushNextTask(base::Bind(
    907         &AppCacheStorageImplTest::Verify_BasicFindMainFallbackResponse,
    908         base::Unretained(this)));
    909 
    910     // Setup some preconditions. Create a complete cache with a
    911     // fallback namespace and entry.
    912     MakeCacheAndGroup(kManifestUrl, 2, 1, true);
    913     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::FALLBACK, 1));
    914     cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::FALLBACK, 2));
    915     cache_->fallback_namespaces_.push_back(
    916         Namespace(FALLBACK_NAMESPACE, kFallbackNamespace2, kEntryUrl2, false));
    917     cache_->fallback_namespaces_.push_back(
    918         Namespace(FALLBACK_NAMESPACE, kFallbackNamespace, kEntryUrl, false));
    919     AppCacheDatabase::CacheRecord cache_record;
    920     std::vector<AppCacheDatabase::EntryRecord> entries;
    921     std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
    922     std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
    923     std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
    924     cache_->ToDatabaseRecords(group_.get(),
    925                               &cache_record,
    926                               &entries,
    927                               &intercepts,
    928                               &fallbacks,
    929                               &whitelists);
    930 
    931     std::vector<AppCacheDatabase::EntryRecord>::const_iterator iter =
    932         entries.begin();
    933     while (iter != entries.end()) {
    934       // MakeCacheAndGroup has inserted the default entry record already.
    935       if (iter->url != kDefaultEntryUrl)
    936         EXPECT_TRUE(database()->InsertEntry(&(*iter)));
    937       ++iter;
    938     }
    939 
    940     EXPECT_TRUE(database()->InsertNamespaceRecords(fallbacks));
    941     EXPECT_TRUE(database()->InsertOnlineWhiteListRecords(whitelists));
    942     if (drop_from_working_set) {
    943       EXPECT_TRUE(cache_->HasOneRef());
    944       cache_ = NULL;
    945       EXPECT_TRUE(group_->HasOneRef());
    946       group_ = NULL;
    947     }
    948 
    949     // Conduct the test. The test url is in both fallback namespace urls,
    950     // but should match the longer of the two.
    951     storage()->FindResponseForMainRequest(kFallbackTestUrl, GURL(), delegate());
    952     EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
    953   }
    954 
    955   void Verify_BasicFindMainFallbackResponse() {
    956     EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
    957     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
    958     EXPECT_EQ(1, delegate()->found_cache_id_);
    959     EXPECT_EQ(2, delegate()->found_group_id_);
    960     EXPECT_FALSE(delegate()->found_entry_.has_response_id());
    961     EXPECT_EQ(2, delegate()->found_fallback_entry_.response_id());
    962     EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
    963     EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
    964     TestFinished();
    965   }
    966 
    967   // BasicFindMainInterceptResponse  -------------------------------
    968 
    969   void BasicFindMainInterceptResponseInDatabase() {
    970     BasicFindMainInterceptResponse(true);
    971   }
    972 
    973   void BasicFindMainInterceptResponseInWorkingSet() {
    974     BasicFindMainInterceptResponse(false);
    975   }
    976 
    977   void BasicFindMainInterceptResponse(bool drop_from_working_set) {
    978     PushNextTask(base::Bind(
    979         &AppCacheStorageImplTest::Verify_BasicFindMainInterceptResponse,
    980         base::Unretained(this)));
    981 
    982     // Setup some preconditions. Create a complete cache with an
    983     // intercept namespace and entry.
    984     MakeCacheAndGroup(kManifestUrl, 2, 1, true);
    985     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::INTERCEPT, 1));
    986     cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::INTERCEPT, 2));
    987     cache_->intercept_namespaces_.push_back(
    988         Namespace(INTERCEPT_NAMESPACE, kInterceptNamespace2,
    989                   kEntryUrl2, false));
    990     cache_->intercept_namespaces_.push_back(
    991         Namespace(INTERCEPT_NAMESPACE, kInterceptNamespace,
    992                   kEntryUrl, false));
    993     AppCacheDatabase::CacheRecord cache_record;
    994     std::vector<AppCacheDatabase::EntryRecord> entries;
    995     std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
    996     std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
    997     std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
    998     cache_->ToDatabaseRecords(group_.get(),
    999                               &cache_record,
   1000                               &entries,
   1001                               &intercepts,
   1002                               &fallbacks,
   1003                               &whitelists);
   1004 
   1005     std::vector<AppCacheDatabase::EntryRecord>::const_iterator iter =
   1006         entries.begin();
   1007     while (iter != entries.end()) {
   1008       // MakeCacheAndGroup has inserted  the default entry record already
   1009       if (iter->url != kDefaultEntryUrl)
   1010         EXPECT_TRUE(database()->InsertEntry(&(*iter)));
   1011       ++iter;
   1012     }
   1013 
   1014     EXPECT_TRUE(database()->InsertNamespaceRecords(intercepts));
   1015     EXPECT_TRUE(database()->InsertOnlineWhiteListRecords(whitelists));
   1016     if (drop_from_working_set) {
   1017       EXPECT_TRUE(cache_->HasOneRef());
   1018       cache_ = NULL;
   1019       EXPECT_TRUE(group_->HasOneRef());
   1020       group_ = NULL;
   1021     }
   1022 
   1023     // Conduct the test. The test url is in both intercept namespaces,
   1024     // but should match the longer of the two.
   1025     storage()->FindResponseForMainRequest(
   1026         kInterceptTestUrl, GURL(), delegate());
   1027     EXPECT_NE(kInterceptTestUrl, delegate()->found_url_);
   1028   }
   1029 
   1030   void Verify_BasicFindMainInterceptResponse() {
   1031     EXPECT_EQ(kInterceptTestUrl, delegate()->found_url_);
   1032     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
   1033     EXPECT_EQ(1, delegate()->found_cache_id_);
   1034     EXPECT_EQ(2, delegate()->found_group_id_);
   1035     EXPECT_EQ(2, delegate()->found_entry_.response_id());
   1036     EXPECT_TRUE(delegate()->found_entry_.IsIntercept());
   1037     EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
   1038     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
   1039     TestFinished();
   1040   }
   1041 
   1042   // FindInterceptPatternMatch ----------------------------------------
   1043 
   1044   void FindInterceptPatternMatchInDatabase() {
   1045     FindInterceptPatternMatch(true);
   1046   }
   1047 
   1048   void FindInterceptPatternMatchInWorkingSet() {
   1049     FindInterceptPatternMatch(false);
   1050   }
   1051 
   1052   void FindInterceptPatternMatch(bool drop_from_working_set) {
   1053     // Setup some preconditions. Create a complete cache with an
   1054     // pattern matching intercept namespace and entry.
   1055     MakeCacheAndGroup(kManifestUrl, 2, 1, true);
   1056     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::INTERCEPT, 1));
   1057     cache_->intercept_namespaces_.push_back(
   1058         Namespace(INTERCEPT_NAMESPACE, kInterceptPatternNamespace,
   1059                   kEntryUrl, true));
   1060     AppCacheDatabase::CacheRecord cache_record;
   1061     std::vector<AppCacheDatabase::EntryRecord> entries;
   1062     std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
   1063     std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
   1064     std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
   1065     cache_->ToDatabaseRecords(group_.get(),
   1066                               &cache_record,
   1067                               &entries,
   1068                               &intercepts,
   1069                               &fallbacks,
   1070                               &whitelists);
   1071 
   1072     std::vector<AppCacheDatabase::EntryRecord>::const_iterator iter =
   1073         entries.begin();
   1074     while (iter != entries.end()) {
   1075       // MakeCacheAndGroup has inserted  the default entry record already
   1076       if (iter->url != kDefaultEntryUrl)
   1077         EXPECT_TRUE(database()->InsertEntry(&(*iter)));
   1078       ++iter;
   1079     }
   1080 
   1081     EXPECT_TRUE(database()->InsertNamespaceRecords(intercepts));
   1082     if (drop_from_working_set) {
   1083       EXPECT_TRUE(cache_->HasOneRef());
   1084       cache_ = NULL;
   1085       EXPECT_TRUE(group_->HasOneRef());
   1086       group_ = NULL;
   1087     }
   1088 
   1089     // First test something that does not match the pattern.
   1090     PushNextTask(base::Bind(
   1091         &AppCacheStorageImplTest::Verify_FindInterceptPatternMatchNegative,
   1092         base::Unretained(this)));
   1093     storage()->FindResponseForMainRequest(
   1094         kInterceptPatternTestNegativeUrl, GURL(), delegate());
   1095     EXPECT_EQ(GURL(), delegate()->found_url_);  // Is always async.
   1096   }
   1097 
   1098   void Verify_FindInterceptPatternMatchNegative() {
   1099     EXPECT_EQ(kInterceptPatternTestNegativeUrl, delegate()->found_url_);
   1100     EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
   1101     EXPECT_EQ(kNoCacheId, delegate()->found_cache_id_);
   1102     EXPECT_EQ(kNoResponseId, delegate()->found_entry_.response_id());
   1103     EXPECT_EQ(kNoResponseId, delegate()->found_fallback_entry_.response_id());
   1104     EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
   1105     EXPECT_EQ(0, delegate()->found_entry_.types());
   1106     EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
   1107 
   1108     // Then test something that matches.
   1109     PushNextTask(base::Bind(
   1110         &AppCacheStorageImplTest::Verify_FindInterceptPatternMatchPositive,
   1111         base::Unretained(this)));
   1112     storage()->FindResponseForMainRequest(
   1113         kInterceptPatternTestPositiveUrl, GURL(), delegate());
   1114   }
   1115 
   1116   void Verify_FindInterceptPatternMatchPositive() {
   1117     EXPECT_EQ(kInterceptPatternTestPositiveUrl, delegate()->found_url_);
   1118     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
   1119     EXPECT_EQ(1, delegate()->found_cache_id_);
   1120     EXPECT_EQ(2, delegate()->found_group_id_);
   1121     EXPECT_EQ(1, delegate()->found_entry_.response_id());
   1122     EXPECT_TRUE(delegate()->found_entry_.IsIntercept());
   1123     EXPECT_EQ(kEntryUrl, delegate()->found_namespace_entry_url_);
   1124     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
   1125     TestFinished();
   1126   }
   1127 
   1128   // FindFallbackPatternMatch  -------------------------------
   1129 
   1130   void FindFallbackPatternMatchInDatabase() {
   1131     FindFallbackPatternMatch(true);
   1132   }
   1133 
   1134   void FindFallbackPatternMatchInWorkingSet() {
   1135     FindFallbackPatternMatch(false);
   1136   }
   1137 
   1138   void FindFallbackPatternMatch(bool drop_from_working_set) {
   1139     // Setup some preconditions. Create a complete cache with a
   1140     // pattern matching fallback namespace and entry.
   1141     MakeCacheAndGroup(kManifestUrl, 2, 1, true);
   1142     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::FALLBACK, 1));
   1143     cache_->fallback_namespaces_.push_back(
   1144         Namespace(FALLBACK_NAMESPACE, kFallbackPatternNamespace,
   1145                   kEntryUrl, true));
   1146     AppCacheDatabase::CacheRecord cache_record;
   1147     std::vector<AppCacheDatabase::EntryRecord> entries;
   1148     std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
   1149     std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
   1150     std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
   1151     cache_->ToDatabaseRecords(group_.get(),
   1152                               &cache_record,
   1153                               &entries,
   1154                               &intercepts,
   1155                               &fallbacks,
   1156                               &whitelists);
   1157 
   1158     std::vector<AppCacheDatabase::EntryRecord>::const_iterator iter =
   1159         entries.begin();
   1160     while (iter != entries.end()) {
   1161       // MakeCacheAndGroup has inserted the default entry record already.
   1162       if (iter->url != kDefaultEntryUrl)
   1163         EXPECT_TRUE(database()->InsertEntry(&(*iter)));
   1164       ++iter;
   1165     }
   1166 
   1167     EXPECT_TRUE(database()->InsertNamespaceRecords(fallbacks));
   1168     if (drop_from_working_set) {
   1169       EXPECT_TRUE(cache_->HasOneRef());
   1170       cache_ = NULL;
   1171       EXPECT_TRUE(group_->HasOneRef());
   1172       group_ = NULL;
   1173     }
   1174 
   1175     // First test something that does not match the pattern.
   1176     PushNextTask(base::Bind(
   1177         &AppCacheStorageImplTest::Verify_FindFallbackPatternMatchNegative,
   1178         base::Unretained(this)));
   1179     storage()->FindResponseForMainRequest(
   1180         kFallbackPatternTestNegativeUrl, GURL(), delegate());
   1181     EXPECT_EQ(GURL(), delegate()->found_url_);  // Is always async.
   1182   }
   1183 
   1184   void Verify_FindFallbackPatternMatchNegative() {
   1185     EXPECT_EQ(kFallbackPatternTestNegativeUrl, delegate()->found_url_);
   1186       EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
   1187       EXPECT_EQ(kNoCacheId, delegate()->found_cache_id_);
   1188       EXPECT_EQ(kNoResponseId, delegate()->found_entry_.response_id());
   1189       EXPECT_EQ(kNoResponseId, delegate()->found_fallback_entry_.response_id());
   1190       EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
   1191       EXPECT_EQ(0, delegate()->found_entry_.types());
   1192       EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
   1193 
   1194       // Then test something that matches.
   1195       PushNextTask(base::Bind(
   1196           &AppCacheStorageImplTest::Verify_FindFallbackPatternMatchPositive,
   1197           base::Unretained(this)));
   1198       storage()->FindResponseForMainRequest(
   1199           kFallbackPatternTestPositiveUrl, GURL(), delegate());
   1200   }
   1201 
   1202   void Verify_FindFallbackPatternMatchPositive() {
   1203     EXPECT_EQ(kFallbackPatternTestPositiveUrl, delegate()->found_url_);
   1204     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
   1205     EXPECT_EQ(1, delegate()->found_cache_id_);
   1206     EXPECT_EQ(2, delegate()->found_group_id_);
   1207     EXPECT_EQ(1, delegate()->found_fallback_entry_.response_id());
   1208     EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
   1209     EXPECT_EQ(kEntryUrl, delegate()->found_namespace_entry_url_);
   1210     EXPECT_FALSE(delegate()->found_entry_.has_response_id());
   1211     TestFinished();
   1212   }
   1213 
   1214   // FindMainResponseWithMultipleHits  -------------------------------
   1215 
   1216   void FindMainResponseWithMultipleHits() {
   1217     PushNextTask(base::Bind(
   1218         &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits,
   1219         base::Unretained(this)));
   1220 
   1221     // Setup some preconditions, create a few caches with an identical set
   1222     // of entries and fallback namespaces. Only the last one remains in
   1223     // the working set to simulate appearing as "in use".
   1224     MakeMultipleHitCacheAndGroup(kManifestUrl, 1);
   1225     MakeMultipleHitCacheAndGroup(kManifestUrl2, 2);
   1226     MakeMultipleHitCacheAndGroup(kManifestUrl3, 3);
   1227 
   1228     // Conduct the test, we should find the response from the last cache
   1229     // since it's "in use".
   1230     storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
   1231     EXPECT_NE(kEntryUrl, delegate()->found_url_);
   1232   }
   1233 
   1234   void MakeMultipleHitCacheAndGroup(const GURL& manifest_url, int id) {
   1235     MakeCacheAndGroup(manifest_url, id, id, true);
   1236     AppCacheDatabase::EntryRecord entry_record;
   1237 
   1238     // Add an entry for kEntryUrl
   1239     entry_record.cache_id = id;
   1240     entry_record.url = kEntryUrl;
   1241     entry_record.flags = AppCacheEntry::EXPLICIT;
   1242     entry_record.response_id = id;
   1243     EXPECT_TRUE(database()->InsertEntry(&entry_record));
   1244     cache_->AddEntry(
   1245         entry_record.url,
   1246         AppCacheEntry(entry_record.flags, entry_record.response_id));
   1247 
   1248     // Add an entry for the manifestUrl
   1249     entry_record.cache_id = id;
   1250     entry_record.url = manifest_url;
   1251     entry_record.flags = AppCacheEntry::MANIFEST;
   1252     entry_record.response_id = id + kManifestEntryIdOffset;
   1253     EXPECT_TRUE(database()->InsertEntry(&entry_record));
   1254     cache_->AddEntry(
   1255         entry_record.url,
   1256         AppCacheEntry(entry_record.flags, entry_record.response_id));
   1257 
   1258     // Add a fallback entry and namespace
   1259     entry_record.cache_id = id;
   1260     entry_record.url = kEntryUrl2;
   1261     entry_record.flags = AppCacheEntry::FALLBACK;
   1262     entry_record.response_id = id + kFallbackEntryIdOffset;
   1263     EXPECT_TRUE(database()->InsertEntry(&entry_record));
   1264     cache_->AddEntry(
   1265         entry_record.url,
   1266         AppCacheEntry(entry_record.flags, entry_record.response_id));
   1267     AppCacheDatabase::NamespaceRecord fallback_namespace_record;
   1268     fallback_namespace_record.cache_id = id;
   1269     fallback_namespace_record.namespace_.target_url = entry_record.url;
   1270     fallback_namespace_record.namespace_.namespace_url = kFallbackNamespace;
   1271     fallback_namespace_record.origin = manifest_url.GetOrigin();
   1272     EXPECT_TRUE(database()->InsertNamespace(&fallback_namespace_record));
   1273     cache_->fallback_namespaces_.push_back(
   1274         Namespace(FALLBACK_NAMESPACE, kFallbackNamespace, kEntryUrl2, false));
   1275   }
   1276 
   1277   void Verify_FindMainResponseWithMultipleHits() {
   1278     EXPECT_EQ(kEntryUrl, delegate()->found_url_);
   1279     EXPECT_EQ(kManifestUrl3, delegate()->found_manifest_url_);
   1280     EXPECT_EQ(3, delegate()->found_cache_id_);
   1281     EXPECT_EQ(3, delegate()->found_group_id_);
   1282     EXPECT_EQ(3, delegate()->found_entry_.response_id());
   1283     EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
   1284     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
   1285 
   1286     // Conduct another test perferring kManifestUrl
   1287     delegate_.reset(new MockStorageDelegate(this));
   1288     PushNextTask(base::Bind(
   1289         &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits2,
   1290         base::Unretained(this)));
   1291     storage()->FindResponseForMainRequest(kEntryUrl, kManifestUrl, delegate());
   1292     EXPECT_NE(kEntryUrl, delegate()->found_url_);
   1293   }
   1294 
   1295   void Verify_FindMainResponseWithMultipleHits2() {
   1296     EXPECT_EQ(kEntryUrl, delegate()->found_url_);
   1297     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
   1298     EXPECT_EQ(1, delegate()->found_cache_id_);
   1299     EXPECT_EQ(1, delegate()->found_group_id_);
   1300     EXPECT_EQ(1, delegate()->found_entry_.response_id());
   1301     EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
   1302     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
   1303 
   1304     // Conduct the another test perferring kManifestUrl2
   1305     delegate_.reset(new MockStorageDelegate(this));
   1306     PushNextTask(base::Bind(
   1307         &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits3,
   1308         base::Unretained(this)));
   1309     storage()->FindResponseForMainRequest(kEntryUrl, kManifestUrl2, delegate());
   1310     EXPECT_NE(kEntryUrl, delegate()->found_url_);
   1311   }
   1312 
   1313   void Verify_FindMainResponseWithMultipleHits3() {
   1314     EXPECT_EQ(kEntryUrl, delegate()->found_url_);
   1315     EXPECT_EQ(kManifestUrl2, delegate()->found_manifest_url_);
   1316     EXPECT_EQ(2, delegate()->found_cache_id_);
   1317     EXPECT_EQ(2, delegate()->found_group_id_);
   1318     EXPECT_EQ(2, delegate()->found_entry_.response_id());
   1319     EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
   1320     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
   1321 
   1322     // Conduct another test with no preferred manifest that hits the fallback.
   1323     delegate_.reset(new MockStorageDelegate(this));
   1324     PushNextTask(base::Bind(
   1325         &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits4,
   1326         base::Unretained(this)));
   1327     storage()->FindResponseForMainRequest(
   1328         kFallbackTestUrl, GURL(), delegate());
   1329     EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
   1330   }
   1331 
   1332   void Verify_FindMainResponseWithMultipleHits4() {
   1333     EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
   1334     EXPECT_EQ(kManifestUrl3, delegate()->found_manifest_url_);
   1335     EXPECT_EQ(3, delegate()->found_cache_id_);
   1336     EXPECT_EQ(3, delegate()->found_group_id_);
   1337     EXPECT_FALSE(delegate()->found_entry_.has_response_id());
   1338     EXPECT_EQ(3 + kFallbackEntryIdOffset,
   1339               delegate()->found_fallback_entry_.response_id());
   1340     EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
   1341     EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
   1342 
   1343     // Conduct another test preferring kManifestUrl2 that hits the fallback.
   1344     delegate_.reset(new MockStorageDelegate(this));
   1345     PushNextTask(base::Bind(
   1346         &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits5,
   1347         base::Unretained(this)));
   1348     storage()->FindResponseForMainRequest(
   1349         kFallbackTestUrl, kManifestUrl2, delegate());
   1350     EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
   1351   }
   1352 
   1353   void Verify_FindMainResponseWithMultipleHits5() {
   1354     EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
   1355     EXPECT_EQ(kManifestUrl2, delegate()->found_manifest_url_);
   1356     EXPECT_EQ(2, delegate()->found_cache_id_);
   1357     EXPECT_EQ(2, delegate()->found_group_id_);
   1358     EXPECT_FALSE(delegate()->found_entry_.has_response_id());
   1359     EXPECT_EQ(2 + kFallbackEntryIdOffset,
   1360               delegate()->found_fallback_entry_.response_id());
   1361     EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
   1362     EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
   1363 
   1364     TestFinished();
   1365   }
   1366 
   1367   // FindMainResponseExclusions  -------------------------------
   1368 
   1369   void FindMainResponseExclusionsInDatabase() {
   1370     FindMainResponseExclusions(true);
   1371   }
   1372 
   1373   void FindMainResponseExclusionsInWorkingSet() {
   1374     FindMainResponseExclusions(false);
   1375   }
   1376 
   1377   void FindMainResponseExclusions(bool drop_from_working_set) {
   1378     // Setup some preconditions. Create a complete cache with a
   1379     // foreign entry, an online namespace, and a second online
   1380     // namespace nested within a fallback namespace.
   1381     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
   1382     cache_->AddEntry(kEntryUrl,
   1383         AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN, 1));
   1384     cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::FALLBACK, 2));
   1385     cache_->fallback_namespaces_.push_back(
   1386         Namespace(FALLBACK_NAMESPACE, kFallbackNamespace, kEntryUrl2, false));
   1387     cache_->online_whitelist_namespaces_.push_back(
   1388         Namespace(NETWORK_NAMESPACE, kOnlineNamespace,
   1389                   GURL(), false));
   1390     cache_->online_whitelist_namespaces_.push_back(
   1391         Namespace(NETWORK_NAMESPACE, kOnlineNamespaceWithinFallback,
   1392                   GURL(), false));
   1393 
   1394     AppCacheDatabase::EntryRecord entry_record;
   1395     entry_record.cache_id = 1;
   1396     entry_record.url = kEntryUrl;
   1397     entry_record.flags = AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN;
   1398     entry_record.response_id = 1;
   1399     EXPECT_TRUE(database()->InsertEntry(&entry_record));
   1400     AppCacheDatabase::OnlineWhiteListRecord whitelist_record;
   1401     whitelist_record.cache_id = 1;
   1402     whitelist_record.namespace_url = kOnlineNamespace;
   1403     EXPECT_TRUE(database()->InsertOnlineWhiteList(&whitelist_record));
   1404     AppCacheDatabase::NamespaceRecord fallback_namespace_record;
   1405     fallback_namespace_record.cache_id = 1;
   1406     fallback_namespace_record.namespace_.target_url = kEntryUrl2;
   1407     fallback_namespace_record.namespace_.namespace_url = kFallbackNamespace;
   1408     fallback_namespace_record.origin = kManifestUrl.GetOrigin();
   1409     EXPECT_TRUE(database()->InsertNamespace(&fallback_namespace_record));
   1410     whitelist_record.cache_id = 1;
   1411     whitelist_record.namespace_url = kOnlineNamespaceWithinFallback;
   1412     EXPECT_TRUE(database()->InsertOnlineWhiteList(&whitelist_record));
   1413     if (drop_from_working_set) {
   1414       cache_ = NULL;
   1415       group_ = NULL;
   1416     }
   1417 
   1418     // We should not find anything for the foreign entry.
   1419     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_ExclusionNotFound,
   1420                             base::Unretained(this), kEntryUrl, 1));
   1421     storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
   1422   }
   1423 
   1424   void Verify_ExclusionNotFound(GURL expected_url, int phase) {
   1425     EXPECT_EQ(expected_url, delegate()->found_url_);
   1426     EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
   1427     EXPECT_EQ(kNoCacheId, delegate()->found_cache_id_);
   1428     EXPECT_EQ(0, delegate()->found_group_id_);
   1429     EXPECT_EQ(kNoResponseId, delegate()->found_entry_.response_id());
   1430     EXPECT_EQ(kNoResponseId, delegate()->found_fallback_entry_.response_id());
   1431     EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
   1432     EXPECT_EQ(0, delegate()->found_entry_.types());
   1433     EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
   1434 
   1435     if (phase == 1) {
   1436       // We should not find anything for the online namespace.
   1437       PushNextTask(
   1438           base::Bind(&AppCacheStorageImplTest::Verify_ExclusionNotFound,
   1439                      base::Unretained(this), kOnlineNamespace, 2));
   1440       storage()->FindResponseForMainRequest(
   1441           kOnlineNamespace, GURL(), delegate());
   1442       return;
   1443     }
   1444     if (phase == 2) {
   1445       // We should not find anything for the online namespace nested within
   1446       // the fallback namespace.
   1447       PushNextTask(base::Bind(
   1448           &AppCacheStorageImplTest::Verify_ExclusionNotFound,
   1449           base::Unretained(this), kOnlineNamespaceWithinFallback, 3));
   1450       storage()->FindResponseForMainRequest(
   1451           kOnlineNamespaceWithinFallback, GURL(), delegate());
   1452       return;
   1453     }
   1454 
   1455     TestFinished();
   1456   }
   1457 
   1458   // Test case helpers --------------------------------------------------
   1459 
   1460   AppCacheService* service() {
   1461     return service_.get();
   1462   }
   1463 
   1464   AppCacheStorageImpl* storage() {
   1465     return static_cast<AppCacheStorageImpl*>(service()->storage());
   1466   }
   1467 
   1468   AppCacheDatabase* database() {
   1469     return storage()->database_;
   1470   }
   1471 
   1472   MockStorageDelegate* delegate() {
   1473     return delegate_.get();
   1474   }
   1475 
   1476   void MakeCacheAndGroup(
   1477       const GURL& manifest_url, int64 group_id, int64 cache_id,
   1478       bool add_to_database) {
   1479     AppCacheEntry default_entry(
   1480         AppCacheEntry::EXPLICIT, cache_id + kDefaultEntryIdOffset,
   1481         kDefaultEntrySize);
   1482     group_ = new AppCacheGroup(storage(), manifest_url, group_id);
   1483     cache_ = new AppCache(storage(), cache_id);
   1484     cache_->AddEntry(kDefaultEntryUrl, default_entry);
   1485     cache_->set_complete(true);
   1486     group_->AddCache(cache_.get());
   1487     if (add_to_database) {
   1488       AppCacheDatabase::GroupRecord group_record;
   1489       group_record.group_id = group_id;
   1490       group_record.manifest_url = manifest_url;
   1491       group_record.origin = manifest_url.GetOrigin();
   1492       EXPECT_TRUE(database()->InsertGroup(&group_record));
   1493       AppCacheDatabase::CacheRecord cache_record;
   1494       cache_record.cache_id = cache_id;
   1495       cache_record.group_id = group_id;
   1496       cache_record.online_wildcard = false;
   1497       cache_record.update_time = kZeroTime;
   1498       cache_record.cache_size = kDefaultEntrySize;
   1499       EXPECT_TRUE(database()->InsertCache(&cache_record));
   1500       AppCacheDatabase::EntryRecord entry_record;
   1501       entry_record.cache_id = cache_id;
   1502       entry_record.url = kDefaultEntryUrl;
   1503       entry_record.flags = default_entry.types();
   1504       entry_record.response_id = default_entry.response_id();
   1505       entry_record.response_size = default_entry.response_size();
   1506       EXPECT_TRUE(database()->InsertEntry(&entry_record));
   1507 
   1508       storage()->usage_map_[manifest_url.GetOrigin()] =
   1509           default_entry.response_size();
   1510     }
   1511   }
   1512 
   1513   // Data members --------------------------------------------------
   1514 
   1515   scoped_ptr<base::WaitableEvent> test_finished_event_;
   1516   std::stack<base::Closure> task_stack_;
   1517   scoped_ptr<AppCacheService> service_;
   1518   scoped_ptr<MockStorageDelegate> delegate_;
   1519   scoped_refptr<MockQuotaManagerProxy> mock_quota_manager_proxy_;
   1520   scoped_refptr<AppCacheGroup> group_;
   1521   scoped_refptr<AppCache> cache_;
   1522   scoped_refptr<AppCache> cache2_;
   1523 };
   1524 
   1525 
   1526 TEST_F(AppCacheStorageImplTest, LoadCache_Miss) {
   1527   RunTestOnIOThread(&AppCacheStorageImplTest::LoadCache_Miss);
   1528 }
   1529 
   1530 TEST_F(AppCacheStorageImplTest, LoadCache_NearHit) {
   1531   RunTestOnIOThread(&AppCacheStorageImplTest::LoadCache_NearHit);
   1532 }
   1533 
   1534 TEST_F(AppCacheStorageImplTest, CreateGroupInEmptyOrigin) {
   1535   RunTestOnIOThread(&AppCacheStorageImplTest::CreateGroupInEmptyOrigin);
   1536 }
   1537 
   1538 TEST_F(AppCacheStorageImplTest, CreateGroupInPopulatedOrigin) {
   1539   RunTestOnIOThread(&AppCacheStorageImplTest::CreateGroupInPopulatedOrigin);
   1540 }
   1541 
   1542 TEST_F(AppCacheStorageImplTest, LoadGroupAndCache_FarHit) {
   1543   RunTestOnIOThread(&AppCacheStorageImplTest::LoadGroupAndCache_FarHit);
   1544 }
   1545 
   1546 TEST_F(AppCacheStorageImplTest, StoreNewGroup) {
   1547   RunTestOnIOThread(&AppCacheStorageImplTest::StoreNewGroup);
   1548 }
   1549 
   1550 TEST_F(AppCacheStorageImplTest, StoreExistingGroup) {
   1551   RunTestOnIOThread(&AppCacheStorageImplTest::StoreExistingGroup);
   1552 }
   1553 
   1554 TEST_F(AppCacheStorageImplTest, StoreExistingGroupExistingCache) {
   1555   RunTestOnIOThread(&AppCacheStorageImplTest::StoreExistingGroupExistingCache);
   1556 }
   1557 
   1558 TEST_F(AppCacheStorageImplTest, FailStoreGroup) {
   1559   RunTestOnIOThread(&AppCacheStorageImplTest::FailStoreGroup);
   1560 }
   1561 
   1562 TEST_F(AppCacheStorageImplTest, MakeGroupObsolete) {
   1563   RunTestOnIOThread(&AppCacheStorageImplTest::MakeGroupObsolete);
   1564 }
   1565 
   1566 TEST_F(AppCacheStorageImplTest, MarkEntryAsForeign) {
   1567   RunTestOnIOThread(&AppCacheStorageImplTest::MarkEntryAsForeign);
   1568 }
   1569 
   1570 TEST_F(AppCacheStorageImplTest, MarkEntryAsForeignWithLoadInProgress) {
   1571   RunTestOnIOThread(
   1572       &AppCacheStorageImplTest::MarkEntryAsForeignWithLoadInProgress);
   1573 }
   1574 
   1575 TEST_F(AppCacheStorageImplTest, FindNoMainResponse) {
   1576   RunTestOnIOThread(&AppCacheStorageImplTest::FindNoMainResponse);
   1577 }
   1578 
   1579 TEST_F(AppCacheStorageImplTest, BasicFindMainResponseInDatabase) {
   1580   RunTestOnIOThread(
   1581       &AppCacheStorageImplTest::BasicFindMainResponseInDatabase);
   1582 }
   1583 
   1584 TEST_F(AppCacheStorageImplTest, BasicFindMainResponseInWorkingSet) {
   1585   RunTestOnIOThread(
   1586       &AppCacheStorageImplTest::BasicFindMainResponseInWorkingSet);
   1587 }
   1588 
   1589 TEST_F(AppCacheStorageImplTest, BasicFindMainFallbackResponseInDatabase) {
   1590   RunTestOnIOThread(
   1591       &AppCacheStorageImplTest::BasicFindMainFallbackResponseInDatabase);
   1592 }
   1593 
   1594 TEST_F(AppCacheStorageImplTest, BasicFindMainFallbackResponseInWorkingSet) {
   1595   RunTestOnIOThread(
   1596       &AppCacheStorageImplTest::BasicFindMainFallbackResponseInWorkingSet);
   1597 }
   1598 
   1599 TEST_F(AppCacheStorageImplTest, BasicFindMainInterceptResponseInDatabase) {
   1600   RunTestOnIOThread(
   1601       &AppCacheStorageImplTest::BasicFindMainInterceptResponseInDatabase);
   1602 }
   1603 
   1604 TEST_F(AppCacheStorageImplTest, BasicFindMainInterceptResponseInWorkingSet) {
   1605   RunTestOnIOThread(
   1606       &AppCacheStorageImplTest::BasicFindMainInterceptResponseInWorkingSet);
   1607 }
   1608 
   1609 TEST_F(AppCacheStorageImplTest, FindMainResponseWithMultipleHits) {
   1610   RunTestOnIOThread(
   1611       &AppCacheStorageImplTest::FindMainResponseWithMultipleHits);
   1612 }
   1613 
   1614 TEST_F(AppCacheStorageImplTest, FindMainResponseExclusionsInDatabase) {
   1615   RunTestOnIOThread(
   1616       &AppCacheStorageImplTest::FindMainResponseExclusionsInDatabase);
   1617 }
   1618 
   1619 TEST_F(AppCacheStorageImplTest, FindMainResponseExclusionsInWorkingSet) {
   1620   RunTestOnIOThread(
   1621       &AppCacheStorageImplTest::FindMainResponseExclusionsInWorkingSet);
   1622 }
   1623 
   1624 TEST_F(AppCacheStorageImplTest, FindInterceptPatternMatchInWorkingSet) {
   1625   RunTestOnIOThread(
   1626       &AppCacheStorageImplTest::FindInterceptPatternMatchInWorkingSet);
   1627 }
   1628 
   1629 TEST_F(AppCacheStorageImplTest, FindInterceptPatternMatchInDatabase) {
   1630   RunTestOnIOThread(
   1631       &AppCacheStorageImplTest::FindInterceptPatternMatchInDatabase);
   1632 }
   1633 
   1634 TEST_F(AppCacheStorageImplTest, FindFallbackPatternMatchInWorkingSet) {
   1635   RunTestOnIOThread(
   1636       &AppCacheStorageImplTest::FindFallbackPatternMatchInWorkingSet);
   1637 }
   1638 
   1639 TEST_F(AppCacheStorageImplTest, FindFallbackPatternMatchInDatabase) {
   1640   RunTestOnIOThread(
   1641       &AppCacheStorageImplTest::FindFallbackPatternMatchInDatabase);
   1642 }
   1643 
   1644 // That's all folks!
   1645 
   1646 }  // namespace appcache
   1647