diff options
Diffstat (limited to 'webkit/browser/appcache/appcache_group_unittest.cc')
-rw-r--r-- | webkit/browser/appcache/appcache_group_unittest.cc | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/webkit/browser/appcache/appcache_group_unittest.cc b/webkit/browser/appcache/appcache_group_unittest.cc new file mode 100644 index 0000000..24dad4d --- /dev/null +++ b/webkit/browser/appcache/appcache_group_unittest.cc @@ -0,0 +1,302 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "base/message_loop.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/browser/appcache/appcache.h" +#include "webkit/browser/appcache/appcache_group.h" +#include "webkit/browser/appcache/appcache_host.h" +#include "webkit/browser/appcache/appcache_update_job.h" +#include "webkit/browser/appcache/mock_appcache_service.h" +#include "webkit/common/appcache/appcache_interfaces.h" + +namespace { + +class TestAppCacheFrontend : public appcache::AppCacheFrontend { + public: + TestAppCacheFrontend() + : last_host_id_(-1), last_cache_id_(-1), + last_status_(appcache::OBSOLETE) { + } + + virtual void OnCacheSelected( + int host_id, const appcache::AppCacheInfo& info) OVERRIDE { + last_host_id_ = host_id; + last_cache_id_ = info.cache_id; + last_status_ = info.status; + } + + virtual void OnStatusChanged(const std::vector<int>& host_ids, + appcache::Status status) OVERRIDE { + } + + virtual void OnEventRaised(const std::vector<int>& host_ids, + appcache::EventID event_id) OVERRIDE { + } + + virtual void OnErrorEventRaised(const std::vector<int>& host_ids, + const std::string& message) OVERRIDE { + } + + virtual void OnProgressEventRaised(const std::vector<int>& host_ids, + const GURL& url, + int num_total, int num_complete) OVERRIDE { + } + + virtual void OnLogMessage(int host_id, appcache::LogLevel log_level, + const std::string& message) OVERRIDE { + } + + virtual void OnContentBlocked(int host_id, + const GURL& manifest_url) OVERRIDE { + } + + int last_host_id_; + int64 last_cache_id_; + appcache::Status last_status_; +}; + +} // namespace anon + +namespace appcache { + +class TestUpdateObserver : public AppCacheGroup::UpdateObserver { + public: + TestUpdateObserver() : update_completed_(false), group_has_cache_(false) { + } + + virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE { + update_completed_ = true; + group_has_cache_ = group->HasCache(); + } + + virtual void OnContentBlocked(AppCacheGroup* group) { + } + + bool update_completed_; + bool group_has_cache_; +}; + +class TestAppCacheHost : public AppCacheHost { + public: + TestAppCacheHost(int host_id, AppCacheFrontend* frontend, + AppCacheService* service) + : AppCacheHost(host_id, frontend, service), + update_completed_(false) { + } + + virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE { + update_completed_ = true; + } + + bool update_completed_; +}; + +class AppCacheGroupTest : public testing::Test { + private: + base::MessageLoop message_loop_; +}; + +TEST_F(AppCacheGroupTest, AddRemoveCache) { + MockAppCacheService service; + scoped_refptr<AppCacheGroup> group( + new AppCacheGroup(service.storage(), GURL("http://foo.com"), 111)); + + base::Time now = base::Time::Now(); + + scoped_refptr<AppCache> cache1(new AppCache(service.storage(), 111)); + cache1->set_complete(true); + cache1->set_update_time(now); + group->AddCache(cache1.get()); + EXPECT_EQ(cache1, group->newest_complete_cache()); + + // Adding older cache does not change newest complete cache. + scoped_refptr<AppCache> cache2(new AppCache(service.storage(), 222)); + cache2->set_complete(true); + cache2->set_update_time(now - base::TimeDelta::FromDays(1)); + group->AddCache(cache2.get()); + EXPECT_EQ(cache1, group->newest_complete_cache()); + + // Adding newer cache does change newest complete cache. + scoped_refptr<AppCache> cache3(new AppCache(service.storage(), 333)); + cache3->set_complete(true); + cache3->set_update_time(now + base::TimeDelta::FromDays(1)); + group->AddCache(cache3.get()); + EXPECT_EQ(cache3, group->newest_complete_cache()); + + // Adding cache with same update time uses one with larger ID. + scoped_refptr<AppCache> cache4(new AppCache(service.storage(), 444)); + cache4->set_complete(true); + cache4->set_update_time(now + base::TimeDelta::FromDays(1)); // same as 3 + group->AddCache(cache4.get()); + EXPECT_EQ(cache4, group->newest_complete_cache()); + + // smaller id + scoped_refptr<AppCache> cache5(new AppCache(service.storage(), 55)); + cache5->set_complete(true); + cache5->set_update_time(now + base::TimeDelta::FromDays(1)); // same as 4 + group->AddCache(cache5.get()); + EXPECT_EQ(cache4, group->newest_complete_cache()); // no change + + // Old caches can always be removed. + group->RemoveCache(cache1.get()); + EXPECT_FALSE(cache1->owning_group()); + EXPECT_EQ(cache4, group->newest_complete_cache()); // newest unchanged + + // Remove rest of caches. + group->RemoveCache(cache2.get()); + EXPECT_FALSE(cache2->owning_group()); + EXPECT_EQ(cache4, group->newest_complete_cache()); // newest unchanged + group->RemoveCache(cache3.get()); + EXPECT_FALSE(cache3->owning_group()); + EXPECT_EQ(cache4, group->newest_complete_cache()); // newest unchanged + group->RemoveCache(cache5.get()); + EXPECT_FALSE(cache5->owning_group()); + EXPECT_EQ(cache4, group->newest_complete_cache()); // newest unchanged + group->RemoveCache(cache4.get()); // newest removed + EXPECT_FALSE(cache4->owning_group()); + EXPECT_FALSE(group->newest_complete_cache()); // no more newest cache + + // Can remove newest cache if there are older caches. + group->AddCache(cache1.get()); + EXPECT_EQ(cache1, group->newest_complete_cache()); + group->AddCache(cache4.get()); + EXPECT_EQ(cache4, group->newest_complete_cache()); + group->RemoveCache(cache4.get()); // remove newest + EXPECT_FALSE(cache4->owning_group()); + EXPECT_FALSE(group->newest_complete_cache()); // newest removed +} + +TEST_F(AppCacheGroupTest, CleanupUnusedGroup) { + MockAppCacheService service; + TestAppCacheFrontend frontend; + AppCacheGroup* group = + new AppCacheGroup(service.storage(), GURL("http://foo.com"), 111); + + AppCacheHost host1(1, &frontend, &service); + AppCacheHost host2(2, &frontend, &service); + + base::Time now = base::Time::Now(); + + AppCache* cache1 = new AppCache(service.storage(), 111); + cache1->set_complete(true); + cache1->set_update_time(now); + group->AddCache(cache1); + EXPECT_EQ(cache1, group->newest_complete_cache()); + + host1.AssociateCompleteCache(cache1); + EXPECT_EQ(frontend.last_host_id_, host1.host_id()); + EXPECT_EQ(frontend.last_cache_id_, cache1->cache_id()); + EXPECT_EQ(frontend.last_status_, appcache::IDLE); + + host2.AssociateCompleteCache(cache1); + EXPECT_EQ(frontend.last_host_id_, host2.host_id()); + EXPECT_EQ(frontend.last_cache_id_, cache1->cache_id()); + EXPECT_EQ(frontend.last_status_, appcache::IDLE); + + AppCache* cache2 = new AppCache(service.storage(), 222); + cache2->set_complete(true); + cache2->set_update_time(now + base::TimeDelta::FromDays(1)); + group->AddCache(cache2); + EXPECT_EQ(cache2, group->newest_complete_cache()); + + // Unassociate all hosts from older cache. + host1.AssociateNoCache(GURL()); + host2.AssociateNoCache(GURL()); + EXPECT_EQ(frontend.last_host_id_, host2.host_id()); + EXPECT_EQ(frontend.last_cache_id_, appcache::kNoCacheId); + EXPECT_EQ(frontend.last_status_, appcache::UNCACHED); +} + +TEST_F(AppCacheGroupTest, StartUpdate) { + MockAppCacheService service; + scoped_refptr<AppCacheGroup> group( + new AppCacheGroup(service.storage(), GURL("http://foo.com"), 111)); + + // Set state to checking to prevent update job from executing fetches. + group->update_status_ = AppCacheGroup::CHECKING; + group->StartUpdate(); + AppCacheUpdateJob* update = group->update_job_; + EXPECT_TRUE(update != NULL); + + // Start another update, check that same update job is in use. + group->StartUpdateWithHost(NULL); + EXPECT_EQ(update, group->update_job_); + + // Deleting the update should restore the group to IDLE. + delete update; + EXPECT_TRUE(group->update_job_ == NULL); + EXPECT_EQ(AppCacheGroup::IDLE, group->update_status()); +} + +TEST_F(AppCacheGroupTest, CancelUpdate) { + MockAppCacheService service; + scoped_refptr<AppCacheGroup> group( + new AppCacheGroup(service.storage(), GURL("http://foo.com"), 111)); + + // Set state to checking to prevent update job from executing fetches. + group->update_status_ = AppCacheGroup::CHECKING; + group->StartUpdate(); + AppCacheUpdateJob* update = group->update_job_; + EXPECT_TRUE(update != NULL); + + // Deleting the group should cancel the update. + TestUpdateObserver observer; + group->AddUpdateObserver(&observer); + group = NULL; // causes group to be deleted + EXPECT_TRUE(observer.update_completed_); + EXPECT_FALSE(observer.group_has_cache_); +} + +TEST_F(AppCacheGroupTest, QueueUpdate) { + MockAppCacheService service; + scoped_refptr<AppCacheGroup> group( + new AppCacheGroup(service.storage(), GURL("http://foo.com"), 111)); + + // Set state to checking to prevent update job from executing fetches. + group->update_status_ = AppCacheGroup::CHECKING; + group->StartUpdate(); + EXPECT_TRUE(group->update_job_); + + // Pretend group's update job is terminating so that next update is queued. + group->update_job_->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST; + EXPECT_TRUE(group->update_job_->IsTerminating()); + + TestAppCacheFrontend frontend; + TestAppCacheHost host(1, &frontend, &service); + host.new_master_entry_url_ = GURL("http://foo.com/bar.txt"); + group->StartUpdateWithNewMasterEntry(&host, host.new_master_entry_url_); + EXPECT_FALSE(group->queued_updates_.empty()); + + group->AddUpdateObserver(&host); + EXPECT_FALSE(group->FindObserver(&host, group->observers_)); + EXPECT_TRUE(group->FindObserver(&host, group->queued_observers_)); + + // Delete update to cause it to complete. Verify no update complete notice + // sent to host. + delete group->update_job_; + EXPECT_EQ(AppCacheGroup::IDLE, group->update_status_); + EXPECT_FALSE(group->restart_update_task_.IsCancelled()); + EXPECT_FALSE(host.update_completed_); + + // Start another update. Cancels task and will run queued updates. + group->update_status_ = AppCacheGroup::CHECKING; // prevent actual fetches + group->StartUpdate(); + EXPECT_TRUE(group->update_job_); + EXPECT_TRUE(group->restart_update_task_.IsCancelled()); + EXPECT_TRUE(group->queued_updates_.empty()); + EXPECT_FALSE(group->update_job_->pending_master_entries_.empty()); + EXPECT_FALSE(group->FindObserver(&host, group->queued_observers_)); + EXPECT_TRUE(group->FindObserver(&host, group->observers_)); + + // Delete update to cause it to complete. Verify host is notified. + delete group->update_job_; + EXPECT_EQ(AppCacheGroup::IDLE, group->update_status_); + EXPECT_TRUE(group->restart_update_task_.IsCancelled()); + EXPECT_TRUE(host.update_completed_); +} + +} // namespace appcache |