| Index: webkit/appcache/appcache_storage_impl_unittest.cc
|
| ===================================================================
|
| --- webkit/appcache/appcache_storage_impl_unittest.cc (revision 88615)
|
| +++ webkit/appcache/appcache_storage_impl_unittest.cc (working copy)
|
| @@ -16,6 +16,7 @@
|
| #include "webkit/appcache/appcache_policy.h"
|
| #include "webkit/appcache/appcache_service.h"
|
| #include "webkit/appcache/appcache_storage_impl.h"
|
| +#include "webkit/quota/quota_manager.h"
|
| #include "webkit/tools/test_shell/simple_appcache_system.h"
|
|
|
| namespace appcache {
|
| @@ -34,10 +35,17 @@
|
| const GURL kOnlineNamespace("http://blah/online_namespace");
|
| const GURL kOnlineNamespaceWithinFallback(
|
| "http://blah/fallback_namespace/online/");
|
| +const GURL kOrigin(kManifestUrl.GetOrigin());
|
|
|
| const int kManifestEntryIdOffset = 100;
|
| const int kFallbackEntryIdOffset = 1000;
|
|
|
| +const GURL kDefaultEntryUrl("http://blah/makecacheandgroup_default_entry");
|
| +const int kDefaultEntrySize = 10;
|
| +const int kDefaultEntryIdOffset = 12345;
|
| +
|
| +const int kMockQuota = 5000;
|
| +
|
| // For the duration of this test case, we hijack the AppCacheThread API
|
| // calls and implement them in terms of the io and db threads created here.
|
|
|
| @@ -176,6 +184,80 @@
|
| AppCacheStorageImplTest* test_;
|
| };
|
|
|
| + class MockQuotaManager : public quota::QuotaManager {
|
| + public:
|
| + MockQuotaManager()
|
| + : QuotaManager(true /* is_incognito */, FilePath(),
|
| + io_thread->message_loop_proxy(),
|
| + db_thread->message_loop_proxy(),
|
| + NULL),
|
| + async_(false) {}
|
| +
|
| + virtual void GetUsageAndQuota(
|
| + const GURL& origin, quota::StorageType type,
|
| + GetUsageAndQuotaCallback* callback) {
|
| + EXPECT_EQ(kOrigin, origin);
|
| + EXPECT_EQ(quota::kStorageTypeTemporary, type);
|
| + if (async_) {
|
| + MessageLoop::current()->PostTask(FROM_HERE,
|
| + NewRunnableMethod(this, &MockQuotaManager::CallCallbackAndDelete,
|
| + callback));
|
| + return;
|
| + }
|
| + CallCallbackAndDelete(callback);
|
| + }
|
| +
|
| + void CallCallbackAndDelete(GetUsageAndQuotaCallback* callback) {
|
| + callback->Run(quota::kQuotaStatusOk, 0, kMockQuota);
|
| + delete callback;
|
| + }
|
| +
|
| + bool async_;
|
| + };
|
| +
|
| + class MockQuotaManagerProxy : public quota::QuotaManagerProxy {
|
| + public:
|
| + MockQuotaManagerProxy()
|
| + : QuotaManagerProxy(NULL, NULL),
|
| + notify_storage_accessed_count_(0),
|
| + notify_storage_modified_count_(0),
|
| + last_delta_(0),
|
| + mock_manager_(new MockQuotaManager) {
|
| + manager_ = mock_manager_;
|
| + }
|
| +
|
| + virtual void NotifyStorageAccessed(quota::QuotaClient::ID client_id,
|
| + const GURL& origin,
|
| + quota::StorageType type) {
|
| + EXPECT_EQ(quota::QuotaClient::kAppcache, client_id);
|
| + EXPECT_EQ(quota::kStorageTypeTemporary, type);
|
| + ++notify_storage_accessed_count_;
|
| + last_origin_ = origin;
|
| + }
|
| +
|
| + virtual void NotifyStorageModified(quota::QuotaClient::ID client_id,
|
| + const GURL& origin,
|
| + quota::StorageType type,
|
| + int64 delta) {
|
| + EXPECT_EQ(quota::QuotaClient::kAppcache, client_id);
|
| + EXPECT_EQ(quota::kStorageTypeTemporary, type);
|
| + ++notify_storage_modified_count_;
|
| + last_origin_ = origin;
|
| + last_delta_ = delta;
|
| + }
|
| +
|
| + // Not needed for our tests.
|
| + virtual void RegisterClient(quota::QuotaClient* client) {}
|
| + virtual void NotifyOriginInUse(const GURL& origin) {}
|
| + virtual void NotifyOriginNoLongerInUse(const GURL& origin) {}
|
| +
|
| + int notify_storage_accessed_count_;
|
| + int notify_storage_modified_count_;
|
| + GURL last_origin_;
|
| + int last_delta_;
|
| + scoped_refptr<MockQuotaManager> mock_manager_;
|
| + };
|
| +
|
| // Helper class run a test on our io_thread. The io_thread
|
| // is spun up once and reused for all tests.
|
| template <class Method>
|
| @@ -243,6 +325,8 @@
|
| DCHECK(MessageLoop::current() == io_thread->message_loop());
|
| service_.reset(new AppCacheService(NULL));
|
| service_->Initialize(FilePath(), NULL);
|
| + mock_quota_manager_proxy_ = new MockQuotaManagerProxy();
|
| + service_->quota_manager_proxy_ = mock_quota_manager_proxy_;
|
| delegate_.reset(new MockStorageDelegate(this));
|
| }
|
|
|
| @@ -252,6 +336,7 @@
|
| group_ = NULL;
|
| cache_ = NULL;
|
| cache2_ = NULL;
|
| + mock_quota_manager_proxy_ = NULL;
|
| delegate_.reset();
|
| service_.reset();
|
| FlushDbThreadTasks();
|
| @@ -312,6 +397,8 @@
|
| void Verify_LoadCache_Miss() {
|
| EXPECT_EQ(111, delegate()->loaded_cache_id_);
|
| EXPECT_FALSE(delegate()->loaded_cache_);
|
| + EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
|
| + EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
|
| TestFinished();
|
| }
|
|
|
| @@ -331,6 +418,8 @@
|
| storage()->LoadCache(cache_id, delegate());
|
| EXPECT_EQ(cache_id, delegate()->loaded_cache_id_);
|
| EXPECT_EQ(cache.get(), delegate()->loaded_cache_.get());
|
| + EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
|
| + EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
|
| TestFinished();
|
| }
|
|
|
| @@ -354,7 +443,7 @@
|
|
|
| // Since the origin has groups, storage class will have to
|
| // consult the database and completion will be async.
|
| - storage()->origins_with_groups_.insert(kManifestUrl.GetOrigin());
|
| + storage()->usage_map_[kOrigin] = kDefaultEntrySize;
|
|
|
| storage()->LoadOrCreateGroup(kManifestUrl, delegate());
|
| EXPECT_FALSE(delegate()->loaded_group_.get());
|
| @@ -371,6 +460,9 @@
|
| EXPECT_FALSE(database()->FindGroup(
|
| delegate()->loaded_group_->group_id(), &record));
|
|
|
| + EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
|
| + EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
|
| +
|
| TestFinished();
|
| }
|
|
|
| @@ -403,6 +495,9 @@
|
| EXPECT_TRUE(delegate()->loaded_cache_->owning_group()->HasOneRef());
|
| EXPECT_EQ(1, delegate()->loaded_cache_->owning_group()->group_id());
|
|
|
| + EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_accessed_count_);
|
| + EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
|
| +
|
| // Drop things from the working set.
|
| delegate()->loaded_cache_ = NULL;
|
| EXPECT_FALSE(delegate()->loaded_group_);
|
| @@ -420,6 +515,8 @@
|
| EXPECT_TRUE(delegate()->loaded_group_->newest_complete_cache());
|
| delegate()->loaded_groups_newest_cache_ = NULL;
|
| EXPECT_TRUE(delegate()->loaded_group_->HasOneRef());
|
| + EXPECT_EQ(2, mock_quota_manager_proxy_->notify_storage_accessed_count_);
|
| + EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
|
| TestFinished();
|
| }
|
|
|
| @@ -435,9 +532,14 @@
|
| group_ = new AppCacheGroup(
|
| service(), kManifestUrl, storage()->NewGroupId());
|
| cache_ = new AppCache(service(), storage()->NewCacheId());
|
| + cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, 1,
|
| + kDefaultEntrySize));
|
| // Hold a ref to the cache simulate the UpdateJob holding that ref,
|
| // and hold a ref to the group to simulate the CacheHost holding that ref.
|
|
|
| + // Have the quota manager retrun asyncly for this test.
|
| + mock_quota_manager_proxy_->mock_manager_->async_ = true;
|
| +
|
| // Conduct the store test.
|
| storage()->StoreGroupAndNewestCache(group_, cache_, delegate());
|
| EXPECT_FALSE(delegate()->stored_group_success_);
|
| @@ -454,6 +556,13 @@
|
| AppCacheDatabase::CacheRecord cache_record;
|
| EXPECT_TRUE(database()->FindGroup(group_->group_id(), &group_record));
|
| EXPECT_TRUE(database()->FindCache(cache_->cache_id(), &cache_record));
|
| +
|
| + // Verify quota bookkeeping
|
| + EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
|
| + EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
|
| + EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
|
| + EXPECT_EQ(kDefaultEntrySize, mock_quota_manager_proxy_->last_delta_);
|
| +
|
| TestFinished();
|
| }
|
|
|
| @@ -467,9 +576,12 @@
|
| // Setup some preconditions. Create a group and old complete cache
|
| // that appear to be "stored"
|
| MakeCacheAndGroup(kManifestUrl, 1, 1, true);
|
| + EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
|
|
|
| // And a newest unstored complete cache.
|
| cache2_ = new AppCache(service(), 2);
|
| + cache2_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::MASTER, 1,
|
| + kDefaultEntrySize + 100));
|
|
|
| // Conduct the test.
|
| storage()->StoreGroupAndNewestCache(group_, cache2_, delegate());
|
| @@ -490,6 +602,13 @@
|
|
|
| // The old cache should have been deleted
|
| EXPECT_FALSE(database()->FindCache(1, &cache_record));
|
| +
|
| + // Verify quota bookkeeping
|
| + EXPECT_EQ(kDefaultEntrySize + 100, storage()->usage_map_[kOrigin]);
|
| + EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
|
| + EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
|
| + EXPECT_EQ(100, mock_quota_manager_proxy_->last_delta_);
|
| +
|
| TestFinished();
|
| }
|
|
|
| @@ -503,6 +622,7 @@
|
| // Setup some preconditions. Create a group and old complete cache
|
| // that appear to be "stored"
|
| MakeCacheAndGroup(kManifestUrl, 1, 1, true);
|
| + EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
|
|
|
| // Change the cache.
|
| base::Time now = base::Time::Now();
|
| @@ -530,17 +650,25 @@
|
| EXPECT_EQ(1, cache_record.group_id);
|
| EXPECT_FALSE(cache_record.online_wildcard);
|
| EXPECT_TRUE(expected_update_time == cache_record.update_time);
|
| - EXPECT_EQ(100, cache_record.cache_size);
|
| + EXPECT_EQ(100 + kDefaultEntrySize, cache_record.cache_size);
|
|
|
| std::vector<AppCacheDatabase::EntryRecord> entry_records;
|
| EXPECT_TRUE(database()->FindEntriesForCache(1, &entry_records));
|
| - EXPECT_EQ(1U, entry_records.size());
|
| + EXPECT_EQ(2U, entry_records.size());
|
| + if (entry_records[0].url == kDefaultEntryUrl)
|
| + entry_records.erase(entry_records.begin());
|
| EXPECT_EQ(1 , entry_records[0].cache_id);
|
| EXPECT_EQ(kEntryUrl, entry_records[0].url);
|
| EXPECT_EQ(AppCacheEntry::MASTER, entry_records[0].flags);
|
| EXPECT_EQ(1, entry_records[0].response_id);
|
| EXPECT_EQ(100, entry_records[0].response_size);
|
|
|
| + // Verify quota bookkeeping
|
| + EXPECT_EQ(100 + kDefaultEntrySize, storage()->usage_map_[kOrigin]);
|
| + EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
|
| + EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
|
| + EXPECT_EQ(100, mock_quota_manager_proxy_->last_delta_);
|
| +
|
| TestFinished();
|
| }
|
|
|
| @@ -577,6 +705,9 @@
|
| EXPECT_FALSE(database()->FindGroup(group_->group_id(), &group_record));
|
| EXPECT_FALSE(database()->FindCache(cache_->cache_id(), &cache_record));
|
|
|
| + EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
|
| + EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
|
| +
|
| TestFinished();
|
| }
|
|
|
| @@ -590,7 +721,7 @@
|
| // Setup some preconditions. Create a group and newest cache that
|
| // appears to be "stored" and "currently in use".
|
| MakeCacheAndGroup(kManifestUrl, 1, 1, true);
|
| - EXPECT_FALSE(storage()->origins_with_groups_.empty());
|
| + EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
|
|
|
| // Also insert some related records.
|
| AppCacheDatabase::EntryRecord entry_record;
|
| @@ -622,7 +753,7 @@
|
| EXPECT_TRUE(delegate()->obsoleted_success_);
|
| EXPECT_EQ(group_.get(), delegate()->obsoleted_group_.get());
|
| EXPECT_TRUE(group_->is_obsolete());
|
| - EXPECT_TRUE(storage()->origins_with_groups_.empty());
|
| + EXPECT_TRUE(storage()->usage_map_.empty());
|
|
|
| // The cache and group have been deleted from the database.
|
| AppCacheDatabase::GroupRecord group_record;
|
| @@ -641,6 +772,12 @@
|
| database()->FindOnlineWhiteListForCache(1, &whitelist_records);
|
| EXPECT_TRUE(whitelist_records.empty());
|
|
|
| + // Verify quota bookkeeping
|
| + EXPECT_TRUE(storage()->usage_map_.empty());
|
| + EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
|
| + EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
|
| + EXPECT_EQ(-kDefaultEntrySize, mock_quota_manager_proxy_->last_delta_);
|
| +
|
| TestFinished();
|
| }
|
|
|
| @@ -836,7 +973,16 @@
|
| std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
|
| cache_->ToDatabaseRecords(group_,
|
| &cache_record, &entries, &fallbacks, &whitelists);
|
| - EXPECT_TRUE(database()->InsertEntryRecords(entries));
|
| +
|
| + std::vector<AppCacheDatabase::EntryRecord>::const_iterator iter =
|
| + entries.begin();
|
| + while (iter != entries.end()) {
|
| + // MakeCacheAndGroup has inserted the default entry record already
|
| + if (iter->url != kDefaultEntryUrl)
|
| + EXPECT_TRUE(database()->InsertEntry(&(*iter)));
|
| + ++iter;
|
| + }
|
| +
|
| EXPECT_TRUE(database()->InsertFallbackNameSpaceRecords(fallbacks));
|
| EXPECT_TRUE(database()->InsertOnlineWhiteListRecords(whitelists));
|
| if (drop_from_working_set) {
|
| @@ -1125,8 +1271,12 @@
|
| void MakeCacheAndGroup(
|
| const GURL& manifest_url, int64 group_id, int64 cache_id,
|
| bool add_to_database) {
|
| + AppCacheEntry default_entry(
|
| + AppCacheEntry::EXPLICIT, cache_id + kDefaultEntryIdOffset,
|
| + kDefaultEntrySize);
|
| group_ = new AppCacheGroup(service(), manifest_url, group_id);
|
| cache_ = new AppCache(service(), cache_id);
|
| + cache_->AddEntry(kDefaultEntryUrl, default_entry);
|
| cache_->set_complete(true);
|
| group_->AddCache(cache_);
|
| if (add_to_database) {
|
| @@ -1140,8 +1290,18 @@
|
| cache_record.group_id = group_id;
|
| cache_record.online_wildcard = false;
|
| cache_record.update_time = kZeroTime;
|
| + cache_record.cache_size = kDefaultEntrySize;
|
| EXPECT_TRUE(database()->InsertCache(&cache_record));
|
| - storage()->origins_with_groups_.insert(manifest_url.GetOrigin());
|
| + AppCacheDatabase::EntryRecord entry_record;
|
| + entry_record.cache_id = cache_id;
|
| + entry_record.url = kDefaultEntryUrl;
|
| + entry_record.flags = default_entry.types();
|
| + entry_record.response_id = default_entry.response_id();
|
| + entry_record.response_size = default_entry.response_size();
|
| + EXPECT_TRUE(database()->InsertEntry(&entry_record));
|
| +
|
| + storage()->usage_map_[manifest_url.GetOrigin()] =
|
| + default_entry.response_size();
|
| }
|
| }
|
|
|
| @@ -1152,6 +1312,7 @@
|
| MockAppCachePolicy policy_;
|
| scoped_ptr<AppCacheService> service_;
|
| scoped_ptr<MockStorageDelegate> delegate_;
|
| + scoped_refptr<MockQuotaManagerProxy> mock_quota_manager_proxy_;
|
| scoped_refptr<AppCacheGroup> group_;
|
| scoped_refptr<AppCache> cache_;
|
| scoped_refptr<AppCache> cache2_;
|
|
|