diff options
Diffstat (limited to 'webkit/appcache/appcache_update_job_unittest.cc')
-rw-r--r-- | webkit/appcache/appcache_update_job_unittest.cc | 1172 |
1 files changed, 1172 insertions, 0 deletions
diff --git a/webkit/appcache/appcache_update_job_unittest.cc b/webkit/appcache/appcache_update_job_unittest.cc new file mode 100644 index 0000000..9fda1c6 --- /dev/null +++ b/webkit/appcache/appcache_update_job_unittest.cc @@ -0,0 +1,1172 @@ +// Copyright (c) 2009 The Chromium Authos. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/gtest/include/gtest/gtest.h" + +#include "base/stl_util-inl.h" +#include "base/thread.h" +#include "base/waitable_event.h" +#include "net/url_request/url_request_test_job.h" +#include "net/url_request/url_request_unittest.h" +#include "webkit/appcache/appcache_group.h" +#include "webkit/appcache/appcache_host.h" +#include "webkit/appcache/appcache_service.h" +#include "webkit/appcache/appcache_update_job.h" + +namespace appcache { +class AppCacheUpdateJobTest; + +const wchar_t kDocRoot[] = L"webkit/appcache/data/appcache_unittest"; + +class MockFrontend : public AppCacheFrontend { + public: + virtual void OnCacheSelected(int host_id, int64 cache_id, + Status status) { + } + + virtual void OnStatusChanged(const std::vector<int>& host_ids, + Status status) { + } + + virtual void OnEventRaised(const std::vector<int>& host_ids, + EventID event_id) { + raised_events_.push_back(RaisedEvent(host_ids, event_id)); + } + + void AddExpectedEvent(const std::vector<int>& host_ids, EventID event_id) { + expected_events_.push_back(RaisedEvent(host_ids, event_id)); + } + + typedef std::vector<int> HostIds; + typedef std::pair<HostIds, EventID> RaisedEvent; + typedef std::vector<RaisedEvent> RaisedEvents; + RaisedEvents raised_events_; + + // Set the expected events if verification needs to happen asynchronously. + RaisedEvents expected_events_; +}; + +// Helper class to let us call methods of AppCacheUpdateJobTest on a +// thread of our choice. +template <class Method> +class WrapperTask : public Task { + public: + WrapperTask(AppCacheUpdateJobTest* test, Method method) + : test_(test), + method_(method) { + } + + virtual void Run() { + (test_->*method_)( ); + } + + private: + AppCacheUpdateJobTest* test_; + Method method_; +}; + +// Helper factories to simulate redirected URL responses for tests. +static URLRequestJob* RedirectFactory(URLRequest* request, + const std::string& scheme) { + return new URLRequestTestJob(request, + URLRequestTestJob::test_redirect_headers(), + URLRequestTestJob::test_data_1(), + true); +} + +class AppCacheUpdateJobTest : public testing::Test, + public AppCacheGroup::Observer { + public: + AppCacheUpdateJobTest() + : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), + do_checks_after_update_finished_(false), + expect_group_obsolete_(false), + expect_group_has_cache_(false), + expect_old_cache_(NULL), + expect_newest_cache_(NULL), + tested_manifest_(NONE) { + } + + static void SetUpTestCase() { + io_thread_.reset(new base::Thread("AppCacheUpdateJob IO test thread")); + base::Thread::Options options(MessageLoop::TYPE_IO, 0); + io_thread_->StartWithOptions(options); + + http_server_ = + HTTPTestServer::CreateServer(kDocRoot, io_thread_->message_loop()); + ASSERT_TRUE(http_server_); + } + + static void TearDownTestCase() { + http_server_ = NULL; + io_thread_.reset(NULL); + } + + // Use a separate IO thread to run a test. Thread will be destroyed + // when it goes out of scope. + template <class Method> + void RunTestOnIOThread(Method method) { + event_ .reset(new base::WaitableEvent(false, false)); + io_thread_->message_loop()->PostTask( + FROM_HERE, new WrapperTask<Method>(this, method)); + + // Wait until task is done before exiting the test. + event_->Wait(); + } + + void StartCacheAttemptTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup(service_.get(), GURL("http://failme")); + + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + MockFrontend mock_frontend; + AppCacheHost host(1, &mock_frontend, service_.get()); + + update->StartUpdate(&host, GURL::EmptyGURL()); + + // Verify state. + EXPECT_EQ(AppCacheUpdateJob::CACHE_ATTEMPT, update->update_type_); + EXPECT_EQ(AppCacheUpdateJob::FETCH_MANIFEST, update->internal_state_); + EXPECT_EQ(AppCacheGroup::CHECKING, group_->update_status()); + + // Verify notifications. + MockFrontend::RaisedEvents& events = mock_frontend.raised_events_; + size_t expected = 1; + EXPECT_EQ(expected, events.size()); + EXPECT_EQ(expected, events[0].first.size()); + EXPECT_EQ(host.host_id(), events[0].first[0]); + EXPECT_EQ(CHECKING_EVENT, events[0].second); + + // Abort as we're not testing actual URL fetches in this test. + delete update; + UpdateFinished(); + } + + void StartUpgradeAttemptTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + { + MakeService(); + group_ = new AppCacheGroup(service_.get(), GURL("http://failme")); + + // Give the group some existing caches. + AppCache* cache1 = MakeCacheForGroup(1); + AppCache* cache2 = MakeCacheForGroup(2); + + // Associate some hosts with caches in the group. + MockFrontend mock_frontend1; + MockFrontend mock_frontend2; + MockFrontend mock_frontend3; + + AppCacheHost host1(1, &mock_frontend1, service_.get()); + host1.AssociateCache(cache1); + + AppCacheHost host2(2, &mock_frontend2, service_.get()); + host2.AssociateCache(cache2); + + AppCacheHost host3(3, &mock_frontend1, service_.get()); + host3.AssociateCache(cache1); + + AppCacheHost host4(4, &mock_frontend3, service_.get()); + + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + update->StartUpdate(&host4, GURL::EmptyGURL()); + + // Verify state after starting an update. + EXPECT_EQ(AppCacheUpdateJob::UPGRADE_ATTEMPT, update->update_type_); + EXPECT_EQ(AppCacheUpdateJob::FETCH_MANIFEST, update->internal_state_); + EXPECT_EQ(AppCacheGroup::CHECKING, group_->update_status()); + + // Verify notifications. + MockFrontend::RaisedEvents& events = mock_frontend1.raised_events_; + size_t expected = 1; + EXPECT_EQ(expected, events.size()); + expected = 2; // 2 hosts using frontend1 + EXPECT_EQ(expected, events[0].first.size()); + MockFrontend::HostIds& host_ids = events[0].first; + EXPECT_TRUE(std::find(host_ids.begin(), host_ids.end(), host1.host_id()) + != host_ids.end()); + EXPECT_TRUE(std::find(host_ids.begin(), host_ids.end(), host3.host_id()) + != host_ids.end()); + EXPECT_EQ(CHECKING_EVENT, events[0].second); + + events = mock_frontend2.raised_events_; + expected = 1; + EXPECT_EQ(expected, events.size()); + EXPECT_EQ(expected, events[0].first.size()); // 1 host using frontend2 + EXPECT_EQ(host2.host_id(), events[0].first[0]); + EXPECT_EQ(CHECKING_EVENT, events[0].second); + + events = mock_frontend3.raised_events_; + EXPECT_TRUE(events.empty()); + + // Abort as we're not testing actual URL fetches in this test. + delete update; + } + UpdateFinished(); + } + + void CacheAttemptFetchManifestFailTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup(service_.get(), GURL("http://failme")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + MockFrontend* frontend = MakeMockFrontend(); + AppCacheHost* host = MakeHost(1, frontend); + update->StartUpdate(host, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + update->manifest_url_request_->SimulateError(-100); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = false; + frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()), + CHECKING_EVENT); + + WaitForUpdateToFinish(); + } + + void UpgradeFetchManifestFailTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup(service_.get(), GURL("http://failme")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + AppCache* cache = MakeCacheForGroup(1); + MockFrontend* frontend1 = MakeMockFrontend(); + MockFrontend* frontend2 = MakeMockFrontend(); + AppCacheHost* host1 = MakeHost(1, frontend1); + AppCacheHost* host2 = MakeHost(2, frontend2); + host1->AssociateCache(cache); + host2->AssociateCache(cache); + + update->StartUpdate(NULL, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + update->manifest_url_request_->SimulateError(-100); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = true; + expect_newest_cache_ = cache; // newest cache unaffected by update + MockFrontend::HostIds ids1(1, host1->host_id()); + frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); + frontend1->AddExpectedEvent(ids1, ERROR_EVENT); + MockFrontend::HostIds ids2(1, host2->host_id()); + frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); + frontend2->AddExpectedEvent(ids2, ERROR_EVENT); + + WaitForUpdateToFinish(); + } + + void ManifestRedirectTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + URLRequest::RegisterProtocolFactory("http", RedirectFactory); + + MakeService(); + group_ = new AppCacheGroup(service_.get(), GURL("http://testme")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + MockFrontend* frontend = MakeMockFrontend(); + AppCacheHost* host = MakeHost(1, frontend); + update->StartUpdate(host, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = false; // redirect is like a failed request + frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()), + CHECKING_EVENT); + + WaitForUpdateToFinish(); + } + + void ManifestWrongMimeTypeTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("defaultresponse")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + MockFrontend* frontend = MakeMockFrontend(); + AppCacheHost* host = MakeHost(1, frontend); + update->StartUpdate(host, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = false; // bad mime type is like a failed request + frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()), + CHECKING_EVENT); + + WaitForUpdateToFinish(); + } + + void ManifestNotFoundTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("files/nosuchfile")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + AppCache* cache = MakeCacheForGroup(1); + MockFrontend* frontend1 = MakeMockFrontend(); + MockFrontend* frontend2 = MakeMockFrontend(); + AppCacheHost* host1 = MakeHost(1, frontend1); + AppCacheHost* host2 = MakeHost(2, frontend2); + host1->AssociateCache(cache); + host2->AssociateCache(cache); + + update->StartUpdate(NULL, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = true; + expect_group_has_cache_ = true; + expect_newest_cache_ = cache; // newest cache unaffected by update + MockFrontend::HostIds ids1(1, host1->host_id()); + frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); + frontend1->AddExpectedEvent(ids1, OBSOLETE_EVENT); + MockFrontend::HostIds ids2(1, host2->host_id()); + frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); + frontend2->AddExpectedEvent(ids2, OBSOLETE_EVENT); + + WaitForUpdateToFinish(); + } + + void ManifestGoneTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("files/gone")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + MockFrontend* frontend = MakeMockFrontend(); + AppCacheHost* host = MakeHost(1, frontend); + update->StartUpdate(host, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = true; + expect_group_has_cache_ = false; + frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()), + CHECKING_EVENT); + + WaitForUpdateToFinish(); + } + + void CacheAttemptNotModifiedTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("files/notmodified")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + MockFrontend* frontend = MakeMockFrontend(); + AppCacheHost* host = MakeHost(1, frontend); + update->StartUpdate(host, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = false; // treated like cache failure + frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()), + CHECKING_EVENT); + + WaitForUpdateToFinish(); + } + + void UpgradeNotModifiedTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("files/notmodified")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + AppCache* cache = MakeCacheForGroup(1); + MockFrontend* frontend1 = MakeMockFrontend(); + MockFrontend* frontend2 = MakeMockFrontend(); + AppCacheHost* host1 = MakeHost(1, frontend1); + AppCacheHost* host2 = MakeHost(2, frontend2); + host1->AssociateCache(cache); + host2->AssociateCache(cache); + + update->StartUpdate(NULL, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = true; + expect_newest_cache_ = cache; // newest cache unaffected by update + MockFrontend::HostIds ids1(1, host1->host_id()); + frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); + frontend1->AddExpectedEvent(ids1, NO_UPDATE_EVENT); + MockFrontend::HostIds ids2(1, host2->host_id()); + frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); + frontend2->AddExpectedEvent(ids2, NO_UPDATE_EVENT); + + WaitForUpdateToFinish(); + } + + void UpgradeManifestDataUnchangedTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("files/manifest1")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + AppCache* cache = MakeCacheForGroup(1); + MockFrontend* frontend1 = MakeMockFrontend(); + MockFrontend* frontend2 = MakeMockFrontend(); + AppCacheHost* host1 = MakeHost(1, frontend1); + AppCacheHost* host2 = MakeHost(2, frontend2); + host1->AssociateCache(cache); + host2->AssociateCache(cache); + + // TODO(jennb): simulate this by mocking storage behavior instead + update->SimulateManifestChanged(false); // unchanged + + update->StartUpdate(NULL, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = true; + expect_newest_cache_ = cache; // newest cache unaffected by update + MockFrontend::HostIds ids1(1, host1->host_id()); + frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); + frontend1->AddExpectedEvent(ids1, NO_UPDATE_EVENT); + MockFrontend::HostIds ids2(1, host2->host_id()); + frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); + frontend2->AddExpectedEvent(ids2, NO_UPDATE_EVENT); + + WaitForUpdateToFinish(); + } + + void BasicCacheAttemptSuccessTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("files/manifest1")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + MockFrontend* frontend = MakeMockFrontend(); + AppCacheHost* host = MakeHost(1, frontend); + update->StartUpdate(host, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = true; + tested_manifest_ = MANIFEST1; + frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()), + CHECKING_EVENT); + + WaitForUpdateToFinish(); + } + + void BasicUpgradeSuccessTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("files/manifest1")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + AppCache* cache = MakeCacheForGroup(service_->NewCacheId()); + MockFrontend* frontend1 = MakeMockFrontend(); + MockFrontend* frontend2 = MakeMockFrontend(); + AppCacheHost* host1 = MakeHost(1, frontend1); + AppCacheHost* host2 = MakeHost(2, frontend2); + host1->AssociateCache(cache); + host2->AssociateCache(cache); + + // TODO(jennb): simulate this by mocking storage behavior instead + update->SimulateManifestChanged(true); // changed + + update->StartUpdate(NULL, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = true; + expect_old_cache_ = cache; + tested_manifest_ = MANIFEST1; + MockFrontend::HostIds ids1(1, host1->host_id()); + frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); + frontend1->AddExpectedEvent(ids1, DOWNLOADING_EVENT); + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); + frontend1->AddExpectedEvent(ids1, UPDATE_READY_EVENT); + MockFrontend::HostIds ids2(1, host2->host_id()); + frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); + frontend2->AddExpectedEvent(ids2, DOWNLOADING_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, UPDATE_READY_EVENT); + + WaitForUpdateToFinish(); + } + + void UpgradeSuccessMergedTypesTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup(service_.get(), + http_server_->TestServerPage("files/manifest-merged-types")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + AppCache* cache = MakeCacheForGroup(service_->NewCacheId()); + MockFrontend* frontend1 = MakeMockFrontend(); + MockFrontend* frontend2 = MakeMockFrontend(); + AppCacheHost* host1 = MakeHost(1, frontend1); + AppCacheHost* host2 = MakeHost(2, frontend2); + host1->AssociateCache(cache); + host2->AssociateCache(cache); + + // Give the newest cache a master entry that is also one of the explicit + // entries in the manifest. + cache->AddEntry(http_server_->TestServerPage("files/explicit1"), + AppCacheEntry(AppCacheEntry::MASTER)); + + // TODO(jennb): simulate this by mocking storage behavior instead + update->SimulateManifestChanged(true); // changed + + update->StartUpdate(NULL, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = true; + expect_old_cache_ = cache; + tested_manifest_ = MANIFEST_MERGED_TYPES; + MockFrontend::HostIds ids1(1, host1->host_id()); + frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); + frontend1->AddExpectedEvent(ids1, DOWNLOADING_EVENT); + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // explicit1 (load) + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // explicit1 (fetch) + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // manifest + frontend1->AddExpectedEvent(ids1, UPDATE_READY_EVENT); + MockFrontend::HostIds ids2(1, host2->host_id()); + frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); + frontend2->AddExpectedEvent(ids2, DOWNLOADING_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, UPDATE_READY_EVENT); + + WaitForUpdateToFinish(); + } + + void CacheAttemptFailUrlFetchTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("files/manifest-with-404")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + MockFrontend* frontend = MakeMockFrontend(); + AppCacheHost* host = MakeHost(1, frontend); + update->StartUpdate(host, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = false; // 404 explicit url is cache failure + frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()), + CHECKING_EVENT); + + WaitForUpdateToFinish(); + } + + void UpgradeFailUrlFetchTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("files/manifest-fb-404")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + AppCache* cache = MakeCacheForGroup(service_->NewCacheId()); + MockFrontend* frontend1 = MakeMockFrontend(); + MockFrontend* frontend2 = MakeMockFrontend(); + AppCacheHost* host1 = MakeHost(1, frontend1); + AppCacheHost* host2 = MakeHost(2, frontend2); + host1->AssociateCache(cache); + host2->AssociateCache(cache); + + // TODO(jennb): simulate this by mocking storage behavior instead + update->SimulateManifestChanged(true); // changed + + update->StartUpdate(NULL, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = true; + expect_newest_cache_ = cache; // newest cache unaffectd by failed update + MockFrontend::HostIds ids1(1, host1->host_id()); + frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); + frontend1->AddExpectedEvent(ids1, DOWNLOADING_EVENT); + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); + frontend1->AddExpectedEvent(ids1, ERROR_EVENT); + MockFrontend::HostIds ids2(1, host2->host_id()); + frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); + frontend2->AddExpectedEvent(ids2, DOWNLOADING_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, ERROR_EVENT); + + WaitForUpdateToFinish(); + } + + void UpgradeFailMasterUrlFetchTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("files/manifest1")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + AppCache* cache = MakeCacheForGroup(service_->NewCacheId()); + MockFrontend* frontend1 = MakeMockFrontend(); + MockFrontend* frontend2 = MakeMockFrontend(); + AppCacheHost* host1 = MakeHost(1, frontend1); + AppCacheHost* host2 = MakeHost(2, frontend2); + host1->AssociateCache(cache); + host2->AssociateCache(cache); + + // Give the newest cache some master entries; one will fail with a 404. + cache->AddEntry( + http_server_->TestServerPage("files/notfound"), + AppCacheEntry(AppCacheEntry::MASTER)); + cache->AddEntry( + http_server_->TestServerPage("files/explicit2"), + AppCacheEntry(AppCacheEntry::MASTER | AppCacheEntry::FOREIGN)); + cache->AddEntry( + http_server_->TestServerPage("files/servererror"), + AppCacheEntry(AppCacheEntry::MASTER)); + + // TODO(jennb): simulate this by mocking storage behavior instead + update->SimulateManifestChanged(true); // changed + + update->StartUpdate(NULL, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = true; + expect_old_cache_ = cache; + tested_manifest_ = MANIFEST1; + expect_extra_entries_.insert(AppCache::EntryMap::value_type( + http_server_->TestServerPage("files/explicit2"), + AppCacheEntry(AppCacheEntry::MASTER))); // foreign flag is dropped + expect_extra_entries_.insert(AppCache::EntryMap::value_type( + http_server_->TestServerPage("files/servererror"), + AppCacheEntry(AppCacheEntry::MASTER))); // foreign flag is dropped + MockFrontend::HostIds ids1(1, host1->host_id()); + frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); + frontend1->AddExpectedEvent(ids1, DOWNLOADING_EVENT); + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // explicit1 + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // fallback1a + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // notfound (load) + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // notfound (fetch) + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // explicit2 (load) + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // explicit2 (fetch) + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // servererror (load) + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // servererror (fetch) + frontend1->AddExpectedEvent(ids1, UPDATE_READY_EVENT); + MockFrontend::HostIds ids2(1, host2->host_id()); + frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); + frontend2->AddExpectedEvent(ids2, DOWNLOADING_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); + frontend2->AddExpectedEvent(ids2, UPDATE_READY_EVENT); + + WaitForUpdateToFinish(); + } + + void EmptyManifestTest() { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + MakeService(); + group_ = new AppCacheGroup( + service_.get(), http_server_->TestServerPage("files/empty-manifest")); + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + AppCache* cache = MakeCacheForGroup(service_->NewCacheId()); + MockFrontend* frontend1 = MakeMockFrontend(); + MockFrontend* frontend2 = MakeMockFrontend(); + AppCacheHost* host1 = MakeHost(1, frontend1); + AppCacheHost* host2 = MakeHost(2, frontend2); + host1->AssociateCache(cache); + host2->AssociateCache(cache); + + // TODO(jennb): simulate this by mocking storage behavior instead + update->SimulateManifestChanged(true); // changed + + update->StartUpdate(NULL, GURL::EmptyGURL()); + EXPECT_TRUE(update->manifest_url_request_ != NULL); + + // Set up checks for when update job finishes. + do_checks_after_update_finished_ = true; + expect_group_obsolete_ = false; + expect_group_has_cache_ = true; + expect_old_cache_ = cache; + tested_manifest_ = EMPTY_MANIFEST; + MockFrontend::HostIds ids1(1, host1->host_id()); + frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); + frontend1->AddExpectedEvent(ids1, DOWNLOADING_EVENT); + frontend1->AddExpectedEvent(ids1, UPDATE_READY_EVENT); + MockFrontend::HostIds ids2(1, host2->host_id()); + frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); + frontend2->AddExpectedEvent(ids2, DOWNLOADING_EVENT); + frontend2->AddExpectedEvent(ids2, UPDATE_READY_EVENT); + + WaitForUpdateToFinish(); + } + + void WaitForUpdateToFinish() { + if (group_->update_status() == AppCacheGroup::IDLE) + UpdateFinished(); + else + group_->AddObserver(this); + } + + void OnUpdateComplete(AppCacheGroup* group) { + ASSERT_EQ(group_, group); + + // Finish up outside of observer callback so that group can be deleted. + MessageLoop::current()->PostTask(FROM_HERE, + method_factory_.NewRunnableMethod( + &AppCacheUpdateJobTest::UpdateFinished)); + } + + void UpdateFinished() { + EXPECT_EQ(AppCacheGroup::IDLE, group_->update_status()); + EXPECT_TRUE(group_->update_job() == NULL); + if (do_checks_after_update_finished_) + VerifyExpectations(); + + // Clean up everything that was created on the IO thread. + group_ = NULL; + STLDeleteContainerPointers(hosts_.begin(), hosts_.end()); + STLDeleteContainerPointers(frontends_.begin(), frontends_.end()); + service_.reset(NULL); + URLRequest::RegisterProtocolFactory("http", NULL); + + event_->Signal(); + } + + void MakeService() { + service_.reset(new AppCacheService()); + request_context_ = new TestURLRequestContext(); + service_->set_request_context(request_context_); + } + + AppCache* MakeCacheForGroup(int64 cache_id) { + AppCache* cache = new AppCache(service_.get(), cache_id); + cache->set_complete(true); + cache->set_update_time(base::TimeTicks::Now()); + cache->set_owning_group(group_); + group_->AddCache(cache); + return cache; + } + + AppCacheHost* MakeHost(int host_id, AppCacheFrontend* frontend) { + AppCacheHost* host = new AppCacheHost(host_id, frontend, service_.get()); + hosts_.push_back(host); + return host; + } + + MockFrontend* MakeMockFrontend() { + MockFrontend* frontend = new MockFrontend(); + frontends_.push_back(frontend); + return frontend; + } + + // Verifies conditions about the group and notifications after an update + // has finished. Cannot verify update job internals as update is deleted. + void VerifyExpectations() { + EXPECT_EQ(expect_group_obsolete_, group_->is_obsolete()); + + if (expect_group_has_cache_) { + EXPECT_TRUE(group_->newest_complete_cache() != NULL); + if (expect_old_cache_) { + EXPECT_NE(expect_old_cache_, group_->newest_complete_cache()); + EXPECT_TRUE(group_->old_caches().end() != + std::find(group_->old_caches().begin(), + group_->old_caches().end(), expect_old_cache_)); + } + if (expect_newest_cache_) + EXPECT_EQ(expect_newest_cache_, group_->newest_complete_cache()); + switch (tested_manifest_) { + case MANIFEST1: + VerifyManifest1(group_->newest_complete_cache()); + break; + case MANIFEST_MERGED_TYPES: + VerifyManifestMergedTypes(group_->newest_complete_cache()); + break; + case EMPTY_MANIFEST: + VerifyEmptyManifest(group_->newest_complete_cache()); + break; + case NONE: + default: + break; + } + } else { + EXPECT_TRUE(group_->newest_complete_cache() == NULL); + } + + // Check expected events. + for (size_t i = 0; i < frontends_.size(); ++i) { + MockFrontend* frontend = frontends_[i]; + + MockFrontend::RaisedEvents& expected_events = frontend->expected_events_; + MockFrontend::RaisedEvents& actual_events = frontend->raised_events_; + EXPECT_EQ(expected_events.size(), actual_events.size()); + + // Check each expected event. + for (size_t j = 0; + j < expected_events.size() && j < actual_events.size(); ++j) { + EXPECT_EQ(expected_events[j].second, actual_events[j].second); + + MockFrontend::HostIds& expected_ids = expected_events[j].first; + MockFrontend::HostIds& actual_ids = actual_events[j].first; + EXPECT_EQ(expected_ids.size(), actual_ids.size()); + + for (size_t k = 0; k < expected_ids.size(); ++k) { + int id = expected_ids[k]; + EXPECT_TRUE(std::find(actual_ids.begin(), actual_ids.end(), id) != + actual_ids.end()); + } + } + } + } + + void VerifyManifest1(AppCache* cache) { + ASSERT_TRUE(cache != NULL); + EXPECT_EQ(group_, cache->owning_group()); + EXPECT_TRUE(cache->is_complete()); + + size_t expected = 3 + expect_extra_entries_.size(); + EXPECT_EQ(expected, cache->entries().size()); + AppCacheEntry* entry = + cache->GetEntry(http_server_->TestServerPage("files/manifest1")); + ASSERT_TRUE(entry); + EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types()); + entry = cache->GetEntry(http_server_->TestServerPage("files/explicit1")); + ASSERT_TRUE(entry); + EXPECT_EQ(AppCacheEntry::EXPLICIT, entry->types()); + entry = cache->GetEntry( + http_server_->TestServerPage("files/fallback1a")); + ASSERT_TRUE(entry); + EXPECT_EQ(AppCacheEntry::FALLBACK, entry->types()); + + for (AppCache::EntryMap::iterator i = expect_extra_entries_.begin(); + i != expect_extra_entries_.end(); ++i) { + entry = cache->GetEntry(i->first); + ASSERT_TRUE(entry); + EXPECT_EQ(i->second.types(), entry->types()); + // TODO(jennb): if copied, check storage id in entry is as expected + } + + expected = 1; + EXPECT_EQ(expected, cache->fallback_namespaces_.size()); + EXPECT_TRUE(cache->fallback_namespaces_.end() != + std::find(cache->fallback_namespaces_.begin(), + cache->fallback_namespaces_.end(), + FallbackNamespace( + http_server_->TestServerPage("files/fallback1"), + http_server_->TestServerPage("files/fallback1a")))); + + EXPECT_TRUE(cache->online_whitelist_namespaces_.empty()); + EXPECT_TRUE(cache->online_whitelist_all_); + + EXPECT_TRUE(cache->update_time_ > base::TimeTicks()); + } + + void VerifyManifestMergedTypes(AppCache* cache) { + ASSERT_TRUE(cache != NULL); + EXPECT_EQ(group_, cache->owning_group()); + EXPECT_TRUE(cache->is_complete()); + + size_t expected = 2; + EXPECT_EQ(expected, cache->entries().size()); + AppCacheEntry* entry = cache->GetEntry( + http_server_->TestServerPage("files/manifest-merged-types")); + ASSERT_TRUE(entry); + EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::MANIFEST, + entry->types()); + entry = cache->GetEntry(http_server_->TestServerPage("files/explicit1")); + ASSERT_TRUE(entry); + EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::FALLBACK | + AppCacheEntry::MASTER, entry->types()); + + expected = 1; + EXPECT_EQ(expected, cache->fallback_namespaces_.size()); + EXPECT_TRUE(cache->fallback_namespaces_.end() != + std::find(cache->fallback_namespaces_.begin(), + cache->fallback_namespaces_.end(), + FallbackNamespace( + http_server_->TestServerPage("files/fallback1"), + http_server_->TestServerPage("files/explicit1")))); + + EXPECT_EQ(expected, cache->online_whitelist_namespaces_.size()); + EXPECT_TRUE(cache->online_whitelist_namespaces_.end() != + std::find(cache->online_whitelist_namespaces_.begin(), + cache->online_whitelist_namespaces_.end(), + http_server_->TestServerPage("files/online1"))); + EXPECT_FALSE(cache->online_whitelist_all_); + + EXPECT_TRUE(cache->update_time_ > base::TimeTicks()); + } + + void VerifyEmptyManifest(AppCache* cache) { + ASSERT_TRUE(cache!= NULL); + EXPECT_EQ(group_, cache->owning_group()); + EXPECT_TRUE(cache->is_complete()); + + size_t expected = 1; + EXPECT_EQ(expected, cache->entries().size()); + AppCacheEntry* entry = cache->GetEntry( + http_server_->TestServerPage("files/empty-manifest")); + ASSERT_TRUE(entry); + EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types()); + + EXPECT_TRUE(cache->fallback_namespaces_.empty()); + EXPECT_TRUE(cache->online_whitelist_namespaces_.empty()); + EXPECT_FALSE(cache->online_whitelist_all_); + + EXPECT_TRUE(cache->update_time_ > base::TimeTicks()); + } + + private: + // Various manifest files used in this test. + enum TestedManifest { + NONE, + MANIFEST1, + MANIFEST_MERGED_TYPES, + EMPTY_MANIFEST, + }; + + static scoped_ptr<base::Thread> io_thread_; + static scoped_refptr<HTTPTestServer> http_server_; + + ScopedRunnableMethodFactory<AppCacheUpdateJobTest> method_factory_; + scoped_ptr<AppCacheService> service_; + scoped_refptr<TestURLRequestContext> request_context_; + scoped_refptr<AppCacheGroup> group_; + scoped_ptr<base::WaitableEvent> event_; + + // Hosts used by an async test that need to live until update job finishes. + // Otherwise, test can put host on the stack instead of here. + std::vector<AppCacheHost*> hosts_; + + // Flag indicating if test cares to verify the update after update finishes. + bool do_checks_after_update_finished_; + bool expect_group_obsolete_; + bool expect_group_has_cache_; + AppCache* expect_old_cache_; + AppCache* expect_newest_cache_; + std::vector<MockFrontend*> frontends_; // to check expected events + TestedManifest tested_manifest_; + AppCache::EntryMap expect_extra_entries_; +}; + +// static +scoped_ptr<base::Thread> AppCacheUpdateJobTest::io_thread_; +scoped_refptr<HTTPTestServer> AppCacheUpdateJobTest::http_server_; + +TEST_F(AppCacheUpdateJobTest, AlreadyChecking) { + AppCacheService service; + scoped_refptr<AppCacheGroup> group = + new AppCacheGroup(&service, GURL("http://manifesturl.com")); + + AppCacheUpdateJob update(&service, group); + + // Pretend group is in checking state. + group->update_job_ = &update; + group->update_status_ = AppCacheGroup::CHECKING; + + update.StartUpdate(NULL, GURL::EmptyGURL()); + EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status()); + + MockFrontend mock_frontend; + AppCacheHost host(1, &mock_frontend, &service); + update.StartUpdate(&host, GURL::EmptyGURL()); + + MockFrontend::RaisedEvents events = mock_frontend.raised_events_; + size_t expected = 1; + EXPECT_EQ(expected, events.size()); + EXPECT_EQ(expected, events[0].first.size()); + EXPECT_EQ(host.host_id(), events[0].first[0]); + EXPECT_EQ(CHECKING_EVENT, events[0].second); + EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status()); +} + +TEST_F(AppCacheUpdateJobTest, AlreadyDownloading) { + AppCacheService service; + scoped_refptr<AppCacheGroup> group = + new AppCacheGroup(&service, GURL("http://manifesturl.com")); + + AppCacheUpdateJob update(&service, group); + + // Pretend group is in downloading state. + group->update_job_ = &update; + group->update_status_ = AppCacheGroup::DOWNLOADING; + + update.StartUpdate(NULL, GURL::EmptyGURL()); + EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status()); + + MockFrontend mock_frontend; + AppCacheHost host(1, &mock_frontend, &service); + update.StartUpdate(&host, GURL::EmptyGURL()); + + MockFrontend::RaisedEvents events = mock_frontend.raised_events_; + size_t expected = 2; + EXPECT_EQ(expected, events.size()); + expected = 1; + EXPECT_EQ(expected, events[0].first.size()); + EXPECT_EQ(host.host_id(), events[0].first[0]); + EXPECT_EQ(CHECKING_EVENT, events[0].second); + + EXPECT_EQ(expected, events[1].first.size()); + EXPECT_EQ(host.host_id(), events[1].first[0]); + EXPECT_EQ(appcache::DOWNLOADING_EVENT, events[1].second); + + EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status()); +} + +TEST_F(AppCacheUpdateJobTest, StartCacheAttempt) { + RunTestOnIOThread(&AppCacheUpdateJobTest::StartCacheAttemptTest); +} + +TEST_F(AppCacheUpdateJobTest, StartUpgradeAttempt) { + RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpgradeAttemptTest); +} + +TEST_F(AppCacheUpdateJobTest, CacheAttemptFetchManifestFail) { + RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFetchManifestFailTest); +} + +TEST_F(AppCacheUpdateJobTest, UpgradeFetchManifestFail) { + RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFetchManifestFailTest); +} + +TEST_F(AppCacheUpdateJobTest, ManifestRedirect) { + RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestRedirectTest); +} + +TEST_F(AppCacheUpdateJobTest, ManifestWrongMimeType) { + RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestWrongMimeTypeTest); +} + +TEST_F(AppCacheUpdateJobTest, ManifestNotFound) { + RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestNotFoundTest); +} + +TEST_F(AppCacheUpdateJobTest, ManifestGone) { + RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestGoneTest); +} + +TEST_F(AppCacheUpdateJobTest, CacheAttemptNotModified) { + RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptNotModifiedTest); +} + +TEST_F(AppCacheUpdateJobTest, UpgradeNotModified) { + RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNotModifiedTest); +} + +TEST_F(AppCacheUpdateJobTest, UpgradeManifestDataUnchanged) { + RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeManifestDataUnchangedTest); +} + +TEST_F(AppCacheUpdateJobTest, BasicCacheAttemptSuccess) { + RunTestOnIOThread(&AppCacheUpdateJobTest::BasicCacheAttemptSuccessTest); +} + +TEST_F(AppCacheUpdateJobTest, BasicUpgradeSuccess) { + RunTestOnIOThread(&AppCacheUpdateJobTest::BasicUpgradeSuccessTest); +} + +TEST_F(AppCacheUpdateJobTest, UpgradeSuccessMergedTypes) { + RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeSuccessMergedTypesTest); +} + +TEST_F(AppCacheUpdateJobTest, CacheAttemptFailUrlFetch) { + RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFailUrlFetchTest); +} + +TEST_F(AppCacheUpdateJobTest, UpgradeFailUrlFetch) { + RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailUrlFetchTest); +} + +TEST_F(AppCacheUpdateJobTest, UpgradeFailMasterUrlFetch) { + RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMasterUrlFetchTest); +} + +TEST_F(AppCacheUpdateJobTest, EmptyManifest) { + RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyManifestTest); +} + +} // namespace appcache |