diff options
author | pilgrim@chromium.org <pilgrim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-12 05:10:24 +0000 |
---|---|---|
committer | pilgrim@chromium.org <pilgrim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-12 05:10:24 +0000 |
commit | a507b82e40444679eff8d9367a4f5192f12d99d9 (patch) | |
tree | 6fd0bb43d40a45a8dd433a0694d2847045c97a49 /webkit/browser | |
parent | 87d95a61d0ecbe5a52345502f340c48bf25a34a0 (diff) | |
download | chromium_src-a507b82e40444679eff8d9367a4f5192f12d99d9.zip chromium_src-a507b82e40444679eff8d9367a4f5192f12d99d9.tar.gz chromium_src-a507b82e40444679eff8d9367a4f5192f12d99d9.tar.bz2 |
Move all remaining appcache unittests from webkit/ to content/
BUG=338338
TBR=darin@chromium.org
Review URL: https://codereview.chromium.org/235763002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@263477 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/browser')
21 files changed, 132 insertions, 9589 deletions
diff --git a/webkit/browser/appcache/appcache.h b/webkit/browser/appcache/appcache.h index 91de284..54713b7 100644 --- a/webkit/browser/appcache/appcache.h +++ b/webkit/browser/appcache/appcache.h @@ -23,7 +23,11 @@ class IOBuffer; } namespace content { +FORWARD_DECLARE_TEST(AppCacheTest, InitializeWithManifest); +FORWARD_DECLARE_TEST(AppCacheTest, ToFromDatabaseRecords); +class AppCacheTest; class AppCacheStorageImplTest; +class AppCacheUpdateJobTest; } namespace appcache { @@ -146,8 +150,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCache private: friend class AppCacheGroup; friend class AppCacheHost; + friend class content::AppCacheTest; friend class content::AppCacheStorageImplTest; - friend class AppCacheUpdateJobTest; + friend class content::AppCacheUpdateJobTest; friend class base::RefCounted<AppCache>; ~AppCache(); @@ -199,8 +204,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCache // to notify storage when cache is deleted AppCacheStorage* storage_; - FRIEND_TEST_ALL_PREFIXES(AppCacheTest, InitializeWithManifest); - FRIEND_TEST_ALL_PREFIXES(AppCacheTest, ToFromDatabaseRecords); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheTest, InitializeWithManifest); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheTest, ToFromDatabaseRecords); DISALLOW_COPY_AND_ASSIGN(AppCache); }; diff --git a/webkit/browser/appcache/appcache_database.h b/webkit/browser/appcache/appcache_database.h index ea1d479..93bc1bf 100644 --- a/webkit/browser/appcache/appcache_database.h +++ b/webkit/browser/appcache/appcache_database.h @@ -26,6 +26,21 @@ class StatementID; } namespace content { +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, CacheRecords); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, EntryRecords); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, QuickIntegrityCheck); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, NamespaceRecords); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, GroupRecords); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, LazyOpen); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, ExperimentalFlags); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, OnlineWhiteListRecords); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, ReCreate); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, DeletableResponseIds); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, OriginUsage); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, UpgradeSchema3to5); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, UpgradeSchema4to5); +FORWARD_DECLARE_TEST(AppCacheDatabaseTest, WasCorrutionDetected); +class AppCacheDatabaseTest; class AppCacheStorageImplTest; } @@ -212,21 +227,24 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheDatabase { bool is_recreating_; bool was_corruption_detected_; + friend class content::AppCacheDatabaseTest; friend class content::AppCacheStorageImplTest; - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, CacheRecords); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, EntryRecords); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, QuickIntegrityCheck); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, NamespaceRecords); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, GroupRecords); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, LazyOpen); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, ExperimentalFlags); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, OnlineWhiteListRecords); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, ReCreate); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, DeletableResponseIds); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, OriginUsage); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, UpgradeSchema3to5); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, UpgradeSchema4to5); - FRIEND_TEST_ALL_PREFIXES(AppCacheDatabaseTest, WasCorrutionDetected); + + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, CacheRecords); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, EntryRecords); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, QuickIntegrityCheck); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, NamespaceRecords); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, GroupRecords); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, LazyOpen); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, ExperimentalFlags); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, + OnlineWhiteListRecords); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, ReCreate); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, DeletableResponseIds); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, OriginUsage); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, UpgradeSchema3to5); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, UpgradeSchema4to5); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, WasCorrutionDetected); DISALLOW_COPY_AND_ASSIGN(AppCacheDatabase); }; diff --git a/webkit/browser/appcache/appcache_database_unittest.cc b/webkit/browser/appcache/appcache_database_unittest.cc deleted file mode 100644 index 2ebffd0..0000000 --- a/webkit/browser/appcache/appcache_database_unittest.cc +++ /dev/null @@ -1,1210 +0,0 @@ -// 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 "base/bind.h" -#include "base/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/strings/stringprintf.h" -#include "sql/connection.h" -#include "sql/meta_table.h" -#include "sql/statement.h" -#include "sql/test/scoped_error_ignorer.h" -#include "sql/test/test_helpers.h" -#include "sql/transaction.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/sqlite/sqlite3.h" -#include "webkit/browser/appcache/appcache_database.h" -#include "webkit/browser/appcache/appcache_entry.h" - -namespace { - -const base::Time kZeroTime; - -} // namespace - -namespace appcache { - -class AppCacheDatabaseTest {}; - -TEST(AppCacheDatabaseTest, LazyOpen) { - // Use an empty file path to use an in-memory sqlite database. - const base::FilePath kEmptyPath; - AppCacheDatabase db(kEmptyPath); - - EXPECT_FALSE(db.LazyOpen(false)); - EXPECT_TRUE(db.LazyOpen(true)); - - int64 group_id, cache_id, response_id, deleteable_response_rowid; - group_id = cache_id = response_id = deleteable_response_rowid = 0; - EXPECT_TRUE(db.FindLastStorageIds(&group_id, &cache_id, &response_id, - &deleteable_response_rowid)); - EXPECT_EQ(0, group_id); - EXPECT_EQ(0, cache_id); - EXPECT_EQ(0, response_id); - EXPECT_EQ(0, deleteable_response_rowid); - - std::set<GURL> origins; - EXPECT_TRUE(db.FindOriginsWithGroups(&origins)); - EXPECT_TRUE(origins.empty()); -} - -TEST(AppCacheDatabaseTest, ReCreate) { - // Real files on disk for this test. - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - const base::FilePath kDbFile = temp_dir.path().AppendASCII("appcache.db"); - const base::FilePath kNestedDir = temp_dir.path().AppendASCII("nested"); - const base::FilePath kOtherFile = kNestedDir.AppendASCII("other_file"); - EXPECT_TRUE(base::CreateDirectory(kNestedDir)); - EXPECT_EQ(3, base::WriteFile(kOtherFile, "foo", 3)); - - AppCacheDatabase db(kDbFile); - EXPECT_FALSE(db.LazyOpen(false)); - EXPECT_TRUE(db.LazyOpen(true)); - - EXPECT_TRUE(base::PathExists(kDbFile)); - EXPECT_TRUE(base::DirectoryExists(kNestedDir)); - EXPECT_TRUE(base::PathExists(kOtherFile)); - - EXPECT_TRUE(db.DeleteExistingAndCreateNewDatabase()); - - EXPECT_TRUE(base::PathExists(kDbFile)); - EXPECT_FALSE(base::DirectoryExists(kNestedDir)); - EXPECT_FALSE(base::PathExists(kOtherFile)); -} - -#ifdef NDEBUG -// Only run in release builds because sql::Connection and familiy -// crank up DLOG(FATAL)'ness and this test presents it with -// intentionally bad data which causes debug builds to exit instead -// of run to completion. In release builds, errors the are delivered -// to the consumer so we can test the error handling of the consumer. -// TODO: crbug/328576 -TEST(AppCacheDatabaseTest, QuickIntegrityCheck) { - // Real files on disk for this test too, a corrupt database file. - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - base::FilePath mock_dir = temp_dir.path().AppendASCII("mock"); - ASSERT_TRUE(base::CreateDirectory(mock_dir)); - - const base::FilePath kDbFile = mock_dir.AppendASCII("appcache.db"); - const base::FilePath kOtherFile = mock_dir.AppendASCII("other_file"); - EXPECT_EQ(3, base::WriteFile(kOtherFile, "foo", 3)); - - // First create a valid db file. - { - AppCacheDatabase db(kDbFile); - EXPECT_TRUE(db.LazyOpen(true)); - EXPECT_TRUE(base::PathExists(kOtherFile)); - EXPECT_TRUE(base::PathExists(kDbFile)); - } - - // Break it. - ASSERT_TRUE(sql::test::CorruptSizeInHeader(kDbFile)); - - // Reopening will notice the corruption and delete/recreate the directory. - { - sql::ScopedErrorIgnorer ignore_errors; - ignore_errors.IgnoreError(SQLITE_CORRUPT); - AppCacheDatabase db(kDbFile); - EXPECT_TRUE(db.LazyOpen(true)); - EXPECT_FALSE(base::PathExists(kOtherFile)); - EXPECT_TRUE(base::PathExists(kDbFile)); - EXPECT_TRUE(ignore_errors.CheckIgnoredErrors()); - } -} -#endif // NDEBUG - -TEST(AppCacheDatabaseTest, WasCorrutionDetected) { - // Real files on disk for this test too, a corrupt database file. - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - const base::FilePath kDbFile = temp_dir.path().AppendASCII("appcache.db"); - - // First create a valid db file. - AppCacheDatabase db(kDbFile); - EXPECT_TRUE(db.LazyOpen(true)); - EXPECT_TRUE(base::PathExists(kDbFile)); - EXPECT_FALSE(db.was_corruption_detected()); - - // Break it. - ASSERT_TRUE(sql::test::CorruptSizeInHeader(kDbFile)); - - // See the the corruption is detected and reported. - { - sql::ScopedErrorIgnorer ignore_errors; - ignore_errors.IgnoreError(SQLITE_CORRUPT); - std::map<GURL, int64> usage_map; - EXPECT_FALSE(db.GetAllOriginUsage(&usage_map)); - EXPECT_TRUE(db.was_corruption_detected()); - EXPECT_TRUE(base::PathExists(kDbFile)); - EXPECT_TRUE(ignore_errors.CheckIgnoredErrors()); - } -} - -TEST(AppCacheDatabaseTest, ExperimentalFlags) { - const char kExperimentFlagsKey[] = "ExperimentFlags"; - std::string kInjectedFlags("exp1,exp2"); - - // Real files on disk for this test. - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - const base::FilePath kDbFile = temp_dir.path().AppendASCII("appcache.db"); - const base::FilePath kOtherFile = temp_dir.path().AppendASCII("other_file"); - EXPECT_EQ(3, base::WriteFile(kOtherFile, "foo", 3)); - EXPECT_TRUE(base::PathExists(kOtherFile)); - - // Inject a non empty flags value, and verify it got there. - { - AppCacheDatabase db(kDbFile); - EXPECT_TRUE(db.LazyOpen(true)); - EXPECT_TRUE(db.meta_table_->SetValue(kExperimentFlagsKey, kInjectedFlags)); - std::string flags; - EXPECT_TRUE(db.meta_table_->GetValue(kExperimentFlagsKey, &flags)); - EXPECT_EQ(kInjectedFlags, flags); - } - - // If flags don't match the expected value, empty string by default, - // the database should be recreated and other files should be cleared out. - { - AppCacheDatabase db(kDbFile); - EXPECT_TRUE(db.LazyOpen(false)); - std::string flags; - EXPECT_TRUE(db.meta_table_->GetValue(kExperimentFlagsKey, &flags)); - EXPECT_TRUE(flags.empty()); - EXPECT_FALSE(base::PathExists(kOtherFile)); - } -} - -TEST(AppCacheDatabaseTest, EntryRecords) { - const base::FilePath kEmptyPath; - AppCacheDatabase db(kEmptyPath); - EXPECT_TRUE(db.LazyOpen(true)); - - sql::ScopedErrorIgnorer ignore_errors; - // TODO(shess): Suppressing SQLITE_CONSTRAINT because the code - // expects that and handles the resulting error. Consider revising - // the code to use INSERT OR IGNORE (which would not throw - // SQLITE_CONSTRAINT) and then check ChangeCount() to see if any - // changes were made. - ignore_errors.IgnoreError(SQLITE_CONSTRAINT); - - AppCacheDatabase::EntryRecord entry; - - entry.cache_id = 1; - entry.url = GURL("http://blah/1"); - entry.flags = AppCacheEntry::MASTER; - entry.response_id = 1; - entry.response_size = 100; - EXPECT_TRUE(db.InsertEntry(&entry)); - EXPECT_FALSE(db.InsertEntry(&entry)); - - entry.cache_id = 2; - entry.url = GURL("http://blah/2"); - entry.flags = AppCacheEntry::EXPLICIT; - entry.response_id = 2; - entry.response_size = 200; - EXPECT_TRUE(db.InsertEntry(&entry)); - - entry.cache_id = 2; - entry.url = GURL("http://blah/3"); - entry.flags = AppCacheEntry::MANIFEST; - entry.response_id = 3; - entry.response_size = 300; - EXPECT_TRUE(db.InsertEntry(&entry)); - - std::vector<AppCacheDatabase::EntryRecord> found; - - EXPECT_TRUE(db.FindEntriesForCache(1, &found)); - EXPECT_EQ(1U, found.size()); - EXPECT_EQ(1, found[0].cache_id); - EXPECT_EQ(GURL("http://blah/1"), found[0].url); - EXPECT_EQ(AppCacheEntry::MASTER, found[0].flags); - EXPECT_EQ(1, found[0].response_id); - EXPECT_EQ(100, found[0].response_size); - found.clear(); - - EXPECT_TRUE(db.AddEntryFlags(GURL("http://blah/1"), 1, - AppCacheEntry::FOREIGN)); - EXPECT_TRUE(db.FindEntriesForCache(1, &found)); - EXPECT_EQ(1U, found.size()); - EXPECT_EQ(AppCacheEntry::MASTER | AppCacheEntry::FOREIGN, found[0].flags); - found.clear(); - - EXPECT_TRUE(db.FindEntriesForCache(2, &found)); - EXPECT_EQ(2U, found.size()); - EXPECT_EQ(2, found[0].cache_id); - EXPECT_EQ(GURL("http://blah/2"), found[0].url); - EXPECT_EQ(AppCacheEntry::EXPLICIT, found[0].flags); - EXPECT_EQ(2, found[0].response_id); - EXPECT_EQ(200, found[0].response_size); - EXPECT_EQ(2, found[1].cache_id); - EXPECT_EQ(GURL("http://blah/3"), found[1].url); - EXPECT_EQ(AppCacheEntry::MANIFEST, found[1].flags); - EXPECT_EQ(3, found[1].response_id); - EXPECT_EQ(300, found[1].response_size); - found.clear(); - - EXPECT_TRUE(db.DeleteEntriesForCache(2)); - EXPECT_TRUE(db.FindEntriesForCache(2, &found)); - EXPECT_TRUE(found.empty()); - found.clear(); - - EXPECT_TRUE(db.DeleteEntriesForCache(1)); - EXPECT_FALSE(db.AddEntryFlags(GURL("http://blah/1"), 1, - AppCacheEntry::FOREIGN)); - - ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); -} - -TEST(AppCacheDatabaseTest, CacheRecords) { - const base::FilePath kEmptyPath; - AppCacheDatabase db(kEmptyPath); - EXPECT_TRUE(db.LazyOpen(true)); - - sql::ScopedErrorIgnorer ignore_errors; - // TODO(shess): See EntryRecords test. - ignore_errors.IgnoreError(SQLITE_CONSTRAINT); - - const AppCacheDatabase::CacheRecord kZeroRecord; - AppCacheDatabase::CacheRecord record; - EXPECT_FALSE(db.FindCache(1, &record)); - - record.cache_id = 1; - record.group_id = 1; - record.online_wildcard = true; - record.update_time = kZeroTime; - record.cache_size = 100; - EXPECT_TRUE(db.InsertCache(&record)); - EXPECT_FALSE(db.InsertCache(&record)); - - record = kZeroRecord; - EXPECT_TRUE(db.FindCache(1, &record)); - EXPECT_EQ(1, record.cache_id); - EXPECT_EQ(1, record.group_id); - EXPECT_TRUE(record.online_wildcard); - EXPECT_TRUE(kZeroTime == record.update_time); - EXPECT_EQ(100, record.cache_size); - - record = kZeroRecord; - EXPECT_TRUE(db.FindCacheForGroup(1, &record)); - EXPECT_EQ(1, record.cache_id); - EXPECT_EQ(1, record.group_id); - EXPECT_TRUE(record.online_wildcard); - EXPECT_TRUE(kZeroTime == record.update_time); - EXPECT_EQ(100, record.cache_size); - - EXPECT_TRUE(db.DeleteCache(1)); - EXPECT_FALSE(db.FindCache(1, &record)); - EXPECT_FALSE(db.FindCacheForGroup(1, &record)); - - EXPECT_TRUE(db.DeleteCache(1)); - - ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); -} - -TEST(AppCacheDatabaseTest, GroupRecords) { - const base::FilePath kEmptyPath; - AppCacheDatabase db(kEmptyPath); - EXPECT_TRUE(db.LazyOpen(true)); - - sql::ScopedErrorIgnorer ignore_errors; - // TODO(shess): See EntryRecords test. - ignore_errors.IgnoreError(SQLITE_CONSTRAINT); - - const GURL kManifestUrl("http://blah/manifest"); - const GURL kOrigin(kManifestUrl.GetOrigin()); - const base::Time kLastAccessTime = base::Time::Now(); - const base::Time kCreationTime = - kLastAccessTime - base::TimeDelta::FromDays(7); - - const AppCacheDatabase::GroupRecord kZeroRecord; - AppCacheDatabase::GroupRecord record; - std::vector<AppCacheDatabase::GroupRecord> records; - - // Behavior with an empty table - EXPECT_FALSE(db.FindGroup(1, &record)); - EXPECT_FALSE(db.FindGroupForManifestUrl(kManifestUrl, &record)); - EXPECT_TRUE(db.DeleteGroup(1)); - EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records)); - EXPECT_TRUE(records.empty()); - EXPECT_FALSE(db.FindGroupForCache(1, &record)); - - record.group_id = 1; - record.manifest_url = kManifestUrl; - record.origin = kOrigin; - record.last_access_time = kLastAccessTime; - record.creation_time = kCreationTime; - EXPECT_TRUE(db.InsertGroup(&record)); - EXPECT_FALSE(db.InsertGroup(&record)); - - record.group_id = 2; - EXPECT_FALSE(db.InsertGroup(&record)); - - record = kZeroRecord; - EXPECT_TRUE(db.FindGroup(1, &record)); - EXPECT_EQ(1, record.group_id); - EXPECT_EQ(kManifestUrl, record.manifest_url); - EXPECT_EQ(kOrigin, record.origin); - EXPECT_EQ(kCreationTime.ToInternalValue(), - record.creation_time.ToInternalValue()); - EXPECT_EQ(kLastAccessTime.ToInternalValue(), - record.last_access_time.ToInternalValue()); - - record = kZeroRecord; - EXPECT_TRUE(db.FindGroupForManifestUrl(kManifestUrl, &record)); - EXPECT_EQ(1, record.group_id); - EXPECT_EQ(kManifestUrl, record.manifest_url); - EXPECT_EQ(kOrigin, record.origin); - EXPECT_EQ(kCreationTime.ToInternalValue(), - record.creation_time.ToInternalValue()); - EXPECT_EQ(kLastAccessTime.ToInternalValue(), - record.last_access_time.ToInternalValue()); - - record.group_id = 2; - record.manifest_url = kOrigin; - record.origin = kOrigin; - record.last_access_time = kLastAccessTime; - record.creation_time = kCreationTime; - EXPECT_TRUE(db.InsertGroup(&record)); - - record = kZeroRecord; - EXPECT_TRUE(db.FindGroupForManifestUrl(kOrigin, &record)); - EXPECT_EQ(2, record.group_id); - EXPECT_EQ(kOrigin, record.manifest_url); - EXPECT_EQ(kOrigin, record.origin); - EXPECT_EQ(kCreationTime.ToInternalValue(), - record.creation_time.ToInternalValue()); - EXPECT_EQ(kLastAccessTime.ToInternalValue(), - record.last_access_time.ToInternalValue()); - - EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records)); - EXPECT_EQ(2U, records.size()); - EXPECT_EQ(1, records[0].group_id); - EXPECT_EQ(kManifestUrl, records[0].manifest_url); - EXPECT_EQ(kOrigin, records[0].origin); - EXPECT_EQ(2, records[1].group_id); - EXPECT_EQ(kOrigin, records[1].manifest_url); - EXPECT_EQ(kOrigin, records[1].origin); - - EXPECT_TRUE(db.DeleteGroup(1)); - - records.clear(); - EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records)); - EXPECT_EQ(1U, records.size()); - EXPECT_EQ(2, records[0].group_id); - EXPECT_EQ(kOrigin, records[0].manifest_url); - EXPECT_EQ(kOrigin, records[0].origin); - EXPECT_EQ(kCreationTime.ToInternalValue(), - record.creation_time.ToInternalValue()); - EXPECT_EQ(kLastAccessTime.ToInternalValue(), - record.last_access_time.ToInternalValue()); - - std::set<GURL> origins; - EXPECT_TRUE(db.FindOriginsWithGroups(&origins)); - EXPECT_EQ(1U, origins.size()); - EXPECT_EQ(kOrigin, *(origins.begin())); - - const GURL kManifest2("http://blah2/manifest"); - const GURL kOrigin2(kManifest2.GetOrigin()); - record.group_id = 1; - record.manifest_url = kManifest2; - record.origin = kOrigin2; - EXPECT_TRUE(db.InsertGroup(&record)); - - origins.clear(); - EXPECT_TRUE(db.FindOriginsWithGroups(&origins)); - EXPECT_EQ(2U, origins.size()); - EXPECT_TRUE(origins.end() != origins.find(kOrigin)); - EXPECT_TRUE(origins.end() != origins.find(kOrigin2)); - - AppCacheDatabase::CacheRecord cache_record; - cache_record.cache_id = 1; - cache_record.group_id = 1; - cache_record.online_wildcard = true; - cache_record.update_time = kZeroTime; - EXPECT_TRUE(db.InsertCache(&cache_record)); - - record = kZeroRecord; - EXPECT_TRUE(db.FindGroupForCache(1, &record)); - EXPECT_EQ(1, record.group_id); - EXPECT_EQ(kManifest2, record.manifest_url); - EXPECT_EQ(kOrigin2, record.origin); - - ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); -} - -TEST(AppCacheDatabaseTest, NamespaceRecords) { - const base::FilePath kEmptyPath; - AppCacheDatabase db(kEmptyPath); - EXPECT_TRUE(db.LazyOpen(true)); - - sql::ScopedErrorIgnorer ignore_errors; - // TODO(shess): See EntryRecords test. - ignore_errors.IgnoreError(SQLITE_CONSTRAINT); - - const GURL kFooNameSpace1("http://foo/namespace1"); - const GURL kFooNameSpace2("http://foo/namespace2"); - const GURL kFooFallbackEntry("http://foo/entry"); - const GURL kFooOrigin(kFooNameSpace1.GetOrigin()); - const GURL kBarNameSpace1("http://bar/namespace1"); - const GURL kBarNameSpace2("http://bar/namespace2"); - const GURL kBarFallbackEntry("http://bar/entry"); - const GURL kBarOrigin(kBarNameSpace1.GetOrigin()); - - const AppCacheDatabase::NamespaceRecord kZeroRecord; - AppCacheDatabase::NamespaceRecord record; - std::vector<AppCacheDatabase::NamespaceRecord> intercepts; - std::vector<AppCacheDatabase::NamespaceRecord> fallbacks; - - // Behavior with an empty table - EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks)); - EXPECT_TRUE(fallbacks.empty()); - EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks)); - EXPECT_TRUE(fallbacks.empty()); - EXPECT_TRUE(db.DeleteNamespacesForCache(1)); - - // Two records for two differenent caches in the Foo origin. - record.cache_id = 1; - record.origin = kFooOrigin; - record.namespace_.namespace_url = kFooNameSpace1; - record.namespace_.target_url = kFooFallbackEntry; - EXPECT_TRUE(db.InsertNamespace(&record)); - EXPECT_FALSE(db.InsertNamespace(&record)); - - record.cache_id = 2; - record.origin = kFooOrigin; - record.namespace_.namespace_url = kFooNameSpace2; - record.namespace_.target_url = kFooFallbackEntry; - EXPECT_TRUE(db.InsertNamespace(&record)); - - fallbacks.clear(); - EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks)); - EXPECT_EQ(1U, fallbacks.size()); - EXPECT_EQ(1, fallbacks[0].cache_id); - EXPECT_EQ(kFooOrigin, fallbacks[0].origin); - EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url); - EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url); - EXPECT_FALSE(fallbacks[0].namespace_.is_pattern); - - fallbacks.clear(); - EXPECT_TRUE(db.FindNamespacesForCache(2, &intercepts, &fallbacks)); - EXPECT_EQ(1U, fallbacks.size()); - EXPECT_EQ(2, fallbacks[0].cache_id); - EXPECT_EQ(kFooOrigin, fallbacks[0].origin); - EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url); - EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url); - EXPECT_FALSE(fallbacks[0].namespace_.is_pattern); - - fallbacks.clear(); - EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks)); - EXPECT_EQ(2U, fallbacks.size()); - EXPECT_EQ(1, fallbacks[0].cache_id); - EXPECT_EQ(kFooOrigin, fallbacks[0].origin); - EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url); - EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url); - EXPECT_FALSE(fallbacks[0].namespace_.is_pattern); - EXPECT_EQ(2, fallbacks[1].cache_id); - EXPECT_EQ(kFooOrigin, fallbacks[1].origin); - EXPECT_EQ(kFooNameSpace2, fallbacks[1].namespace_.namespace_url); - EXPECT_EQ(kFooFallbackEntry, fallbacks[1].namespace_.target_url); - EXPECT_FALSE(fallbacks[1].namespace_.is_pattern); - - EXPECT_TRUE(db.DeleteNamespacesForCache(1)); - fallbacks.clear(); - EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks)); - EXPECT_EQ(1U, fallbacks.size()); - EXPECT_EQ(2, fallbacks[0].cache_id); - EXPECT_EQ(kFooOrigin, fallbacks[0].origin); - EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url); - EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url); - EXPECT_FALSE(fallbacks[0].namespace_.is_pattern); - - // Two more records for the same cache in the Bar origin. - record.cache_id = 3; - record.origin = kBarOrigin; - record.namespace_.namespace_url = kBarNameSpace1; - record.namespace_.target_url = kBarFallbackEntry; - record.namespace_.is_pattern = true; - EXPECT_TRUE(db.InsertNamespace(&record)); - - record.cache_id = 3; - record.origin = kBarOrigin; - record.namespace_.namespace_url = kBarNameSpace2; - record.namespace_.target_url = kBarFallbackEntry; - record.namespace_.is_pattern = true; - EXPECT_TRUE(db.InsertNamespace(&record)); - - fallbacks.clear(); - EXPECT_TRUE(db.FindNamespacesForCache(3, &intercepts, &fallbacks)); - EXPECT_EQ(2U, fallbacks.size()); - EXPECT_TRUE(fallbacks[0].namespace_.is_pattern); - EXPECT_TRUE(fallbacks[1].namespace_.is_pattern); - - fallbacks.clear(); - EXPECT_TRUE(db.FindNamespacesForOrigin(kBarOrigin, &intercepts, &fallbacks)); - EXPECT_EQ(2U, fallbacks.size()); - EXPECT_TRUE(fallbacks[0].namespace_.is_pattern); - EXPECT_TRUE(fallbacks[1].namespace_.is_pattern); - - ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); -} - -TEST(AppCacheDatabaseTest, OnlineWhiteListRecords) { - const base::FilePath kEmptyPath; - AppCacheDatabase db(kEmptyPath); - EXPECT_TRUE(db.LazyOpen(true)); - - const GURL kFooNameSpace1("http://foo/namespace1"); - const GURL kFooNameSpace2("http://foo/namespace2"); - const GURL kBarNameSpace1("http://bar/namespace1"); - - const AppCacheDatabase::OnlineWhiteListRecord kZeroRecord; - AppCacheDatabase::OnlineWhiteListRecord record; - std::vector<AppCacheDatabase::OnlineWhiteListRecord> records; - - // Behavior with an empty table - EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records)); - EXPECT_TRUE(records.empty()); - EXPECT_TRUE(db.DeleteOnlineWhiteListForCache(1)); - - record.cache_id = 1; - record.namespace_url = kFooNameSpace1; - EXPECT_TRUE(db.InsertOnlineWhiteList(&record)); - record.namespace_url = kFooNameSpace2; - record.is_pattern = true; - EXPECT_TRUE(db.InsertOnlineWhiteList(&record)); - records.clear(); - EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records)); - EXPECT_EQ(2U, records.size()); - EXPECT_EQ(1, records[0].cache_id); - EXPECT_EQ(kFooNameSpace1, records[0].namespace_url); - EXPECT_FALSE(records[0].is_pattern); - EXPECT_EQ(1, records[1].cache_id); - EXPECT_EQ(kFooNameSpace2, records[1].namespace_url); - EXPECT_TRUE(records[1].is_pattern); - - record.cache_id = 2; - record.namespace_url = kBarNameSpace1; - EXPECT_TRUE(db.InsertOnlineWhiteList(&record)); - records.clear(); - EXPECT_TRUE(db.FindOnlineWhiteListForCache(2, &records)); - EXPECT_EQ(1U, records.size()); - - EXPECT_TRUE(db.DeleteOnlineWhiteListForCache(1)); - records.clear(); - EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records)); - EXPECT_TRUE(records.empty()); -} - -TEST(AppCacheDatabaseTest, DeletableResponseIds) { - const base::FilePath kEmptyPath; - AppCacheDatabase db(kEmptyPath); - EXPECT_TRUE(db.LazyOpen(true)); - - sql::ScopedErrorIgnorer ignore_errors; - // TODO(shess): See EntryRecords test. - ignore_errors.IgnoreError(SQLITE_CONSTRAINT); - - std::vector<int64> ids; - - EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100)); - EXPECT_TRUE(ids.empty()); - ids.push_back(0); - EXPECT_TRUE(db.DeleteDeletableResponseIds(ids)); - EXPECT_TRUE(db.InsertDeletableResponseIds(ids)); - - ids.clear(); - EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100)); - EXPECT_EQ(1U, ids.size()); - EXPECT_EQ(0, ids[0]); - - int64 unused, deleteable_response_rowid; - unused = deleteable_response_rowid = 0; - EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused, - &deleteable_response_rowid)); - EXPECT_EQ(1, deleteable_response_rowid); - - - // Expected to fail due to the duplicate id, 0 is already in the table. - ids.clear(); - ids.push_back(0); - ids.push_back(1); - EXPECT_FALSE(db.InsertDeletableResponseIds(ids)); - - ids.clear(); - for (int i = 1; i < 10; ++i) - ids.push_back(i); - EXPECT_TRUE(db.InsertDeletableResponseIds(ids)); - EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused, - &deleteable_response_rowid)); - EXPECT_EQ(10, deleteable_response_rowid); - - ids.clear(); - EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100)); - EXPECT_EQ(10U, ids.size()); - for (int i = 0; i < 10; ++i) - EXPECT_EQ(i, ids[i]); - - // Ensure the limit is respected. - ids.clear(); - EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 5)); - EXPECT_EQ(5U, ids.size()); - for (int i = 0; i < static_cast<int>(ids.size()); ++i) - EXPECT_EQ(i, ids[i]); - - // Ensure the max_rowid is respected (the first rowid is 1). - ids.clear(); - EXPECT_TRUE(db.GetDeletableResponseIds(&ids, 5, 100)); - EXPECT_EQ(5U, ids.size()); - for (int i = 0; i < static_cast<int>(ids.size()); ++i) - EXPECT_EQ(i, ids[i]); - - // Ensure that we can delete from the table. - EXPECT_TRUE(db.DeleteDeletableResponseIds(ids)); - ids.clear(); - EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100)); - EXPECT_EQ(5U, ids.size()); - for (int i = 0; i < static_cast<int>(ids.size()); ++i) - EXPECT_EQ(i + 5, ids[i]); - - ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); -} - -TEST(AppCacheDatabaseTest, OriginUsage) { - const GURL kManifestUrl("http://blah/manifest"); - const GURL kManifestUrl2("http://blah/manifest2"); - const GURL kOrigin(kManifestUrl.GetOrigin()); - const GURL kOtherOriginManifestUrl("http://other/manifest"); - const GURL kOtherOrigin(kOtherOriginManifestUrl.GetOrigin()); - - const base::FilePath kEmptyPath; - AppCacheDatabase db(kEmptyPath); - EXPECT_TRUE(db.LazyOpen(true)); - - std::vector<AppCacheDatabase::CacheRecord> cache_records; - EXPECT_EQ(0, db.GetOriginUsage(kOrigin)); - EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records)); - EXPECT_TRUE(cache_records.empty()); - - AppCacheDatabase::GroupRecord group_record; - group_record.group_id = 1; - group_record.manifest_url = kManifestUrl; - group_record.origin = kOrigin; - EXPECT_TRUE(db.InsertGroup(&group_record)); - AppCacheDatabase::CacheRecord cache_record; - cache_record.cache_id = 1; - cache_record.group_id = 1; - cache_record.online_wildcard = true; - cache_record.update_time = kZeroTime; - cache_record.cache_size = 100; - EXPECT_TRUE(db.InsertCache(&cache_record)); - - EXPECT_EQ(100, db.GetOriginUsage(kOrigin)); - - group_record.group_id = 2; - group_record.manifest_url = kManifestUrl2; - group_record.origin = kOrigin; - EXPECT_TRUE(db.InsertGroup(&group_record)); - cache_record.cache_id = 2; - cache_record.group_id = 2; - cache_record.online_wildcard = true; - cache_record.update_time = kZeroTime; - cache_record.cache_size = 1000; - EXPECT_TRUE(db.InsertCache(&cache_record)); - - EXPECT_EQ(1100, db.GetOriginUsage(kOrigin)); - - group_record.group_id = 3; - group_record.manifest_url = kOtherOriginManifestUrl; - group_record.origin = kOtherOrigin; - EXPECT_TRUE(db.InsertGroup(&group_record)); - cache_record.cache_id = 3; - cache_record.group_id = 3; - cache_record.online_wildcard = true; - cache_record.update_time = kZeroTime; - cache_record.cache_size = 5000; - EXPECT_TRUE(db.InsertCache(&cache_record)); - - EXPECT_EQ(5000, db.GetOriginUsage(kOtherOrigin)); - - EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records)); - EXPECT_EQ(2U, cache_records.size()); - cache_records.clear(); - EXPECT_TRUE(db.FindCachesForOrigin(kOtherOrigin, &cache_records)); - EXPECT_EQ(1U, cache_records.size()); - - std::map<GURL, int64> usage_map; - EXPECT_TRUE(db.GetAllOriginUsage(&usage_map)); - EXPECT_EQ(2U, usage_map.size()); - EXPECT_EQ(1100, usage_map[kOrigin]); - EXPECT_EQ(5000, usage_map[kOtherOrigin]); -} - -#if defined(APPCACHE_USE_SIMPLE_CACHE) -// There is no such upgrade path in this case. -#else -TEST(AppCacheDatabaseTest, UpgradeSchema3to5) { - // Real file on disk for this test. - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - const base::FilePath kDbFile = temp_dir.path().AppendASCII("upgrade3.db"); - - const GURL kMockOrigin("http://mockorigin/"); - const char kNamespaceUrlFormat[] = "namespace%d"; - const char kTargetUrlFormat[] = "target%d"; - const int kNumNamespaces = 10; - - // Create a v3 schema based database containing some fallback records. - { - const int kVersion3 = 3; - const char kGroupsTable[] = "Groups"; - const char kCachesTable[] = "Caches"; - const char kEntriesTable[] = "Entries"; - const char kFallbackNameSpacesTable[] = "FallbackNameSpaces"; - const char kOnlineWhiteListsTable[] = "OnlineWhiteLists"; - const char kDeletableResponseIdsTable[] = "DeletableResponseIds"; - - const struct { - const char* table_name; - const char* columns; - } kTables3[] = { - { kGroupsTable, - "(group_id INTEGER PRIMARY KEY," - " origin TEXT," - " manifest_url TEXT," - " creation_time INTEGER," - " last_access_time INTEGER)" }, - - { kCachesTable, - "(cache_id INTEGER PRIMARY KEY," - " group_id INTEGER," - " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1))," - " update_time INTEGER," - " cache_size INTEGER)" }, // intentionally not normalized - - { kEntriesTable, - "(cache_id INTEGER," - " url TEXT," - " flags INTEGER," - " response_id INTEGER," - " response_size INTEGER)" }, - - { kFallbackNameSpacesTable, - "(cache_id INTEGER," - " origin TEXT," // intentionally not normalized - " namespace_url TEXT," - " fallback_entry_url TEXT)" }, - - { kOnlineWhiteListsTable, - "(cache_id INTEGER," - " namespace_url TEXT)" }, - - { kDeletableResponseIdsTable, - "(response_id INTEGER NOT NULL)" }, - }; - - const struct { - const char* index_name; - const char* table_name; - const char* columns; - bool unique; - } kIndexes3[] = { - { "GroupsOriginIndex", - kGroupsTable, - "(origin)", - false }, - - { "GroupsManifestIndex", - kGroupsTable, - "(manifest_url)", - true }, - - { "CachesGroupIndex", - kCachesTable, - "(group_id)", - false }, - - { "EntriesCacheIndex", - kEntriesTable, - "(cache_id)", - false }, - - { "EntriesCacheAndUrlIndex", - kEntriesTable, - "(cache_id, url)", - true }, - - { "EntriesResponseIdIndex", - kEntriesTable, - "(response_id)", - true }, - - { "FallbackNameSpacesCacheIndex", - kFallbackNameSpacesTable, - "(cache_id)", - false }, - - { "FallbackNameSpacesOriginIndex", - kFallbackNameSpacesTable, - "(origin)", - false }, - - { "FallbackNameSpacesCacheAndUrlIndex", - kFallbackNameSpacesTable, - "(cache_id, namespace_url)", - true }, - - { "OnlineWhiteListCacheIndex", - kOnlineWhiteListsTable, - "(cache_id)", - false }, - - { "DeletableResponsesIdIndex", - kDeletableResponseIdsTable, - "(response_id)", - true }, - }; - - const int kTableCount3 = ARRAYSIZE_UNSAFE(kTables3); - const int kIndexCount3 = ARRAYSIZE_UNSAFE(kIndexes3); - - sql::Connection connection; - EXPECT_TRUE(connection.Open(kDbFile)); - - sql::Transaction transaction(&connection); - EXPECT_TRUE(transaction.Begin()); - - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&connection, kVersion3, kVersion3)); - - for (int i = 0; i < kTableCount3; ++i) { - std::string sql("CREATE TABLE "); - sql += kTables3[i].table_name; - sql += kTables3[i].columns; - EXPECT_TRUE(connection.Execute(sql.c_str())); - } - - for (int i = 0; i < kIndexCount3; ++i) { - std::string sql; - if (kIndexes3[i].unique) - sql += "CREATE UNIQUE INDEX "; - else - sql += "CREATE INDEX "; - sql += kIndexes3[i].index_name; - sql += " ON "; - sql += kIndexes3[i].table_name; - sql += kIndexes3[i].columns; - EXPECT_TRUE(connection.Execute(sql.c_str())); - } - - const char* kSql = - "INSERT INTO FallbackNameSpaces" - " (cache_id, origin, namespace_url, fallback_entry_url)" - " VALUES (?, ?, ?, ?)"; - - sql::Statement statement; - statement.Assign(connection.GetUniqueStatement(kSql)); - EXPECT_TRUE(statement.is_valid()); - for (int i = 0; i < kNumNamespaces; ++i) { - GURL namespace_url( - kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i))); - GURL target_url( - kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i))); - statement.BindInt64(0, i); - statement.BindString(1, kMockOrigin.spec().c_str()); - statement.BindString(2, namespace_url.spec().c_str()); - statement.BindString(3, target_url.spec().c_str()); - ASSERT_TRUE(statement.Run()); - statement.Reset(true); - } - - EXPECT_TRUE(transaction.Commit()); - } - - // Open that database and verify that it got updated. - AppCacheDatabase db(kDbFile); - EXPECT_TRUE(db.LazyOpen(true)); - - EXPECT_FALSE(db.db_->DoesTableExist("FallbackNameSpaces")); - EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNamesSpacesCacheIndex")); - EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNameSpacesOriginIndex")); - EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNameSpacesCacheAndUrlIndex")); - - EXPECT_TRUE(db.db_->DoesTableExist("Namespaces")); - EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesCacheIndex")); - EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesOriginIndex")); - EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesCacheAndUrlIndex")); - EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "is_pattern")); - EXPECT_TRUE(db.db_->DoesColumnExist("OnlineWhiteLists", "is_pattern")); - - EXPECT_EQ(5, db.meta_table_->GetVersionNumber()); - EXPECT_EQ(5, db.meta_table_->GetCompatibleVersionNumber()); - - std::vector<AppCacheDatabase::NamespaceRecord> intercepts; - std::vector<AppCacheDatabase::NamespaceRecord> fallbacks; - EXPECT_TRUE(db.FindNamespacesForOrigin(kMockOrigin, &intercepts, - &fallbacks)); - EXPECT_TRUE(intercepts.empty()); - EXPECT_EQ(kNumNamespaces, static_cast<int>(fallbacks.size())); - - for (int i = 0; i < kNumNamespaces; ++i) { - GURL expected_namespace_url( - kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i))); - GURL expected_target_url( - kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i))); - - EXPECT_EQ(i, fallbacks[i].cache_id); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[i].namespace_.type); - EXPECT_EQ(kMockOrigin, fallbacks[i].origin); - EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_.namespace_url); - EXPECT_EQ(expected_target_url, fallbacks[i].namespace_.target_url); - EXPECT_FALSE(fallbacks[i].namespace_.is_pattern); - } -} -#endif // !APPCACHE_USE_SIMPLE_CACHE - -#if defined(APPCACHE_USE_SIMPLE_CACHE) -// There is no such upgrade path in this case. -#else -TEST(AppCacheDatabaseTest, UpgradeSchema4to5) { - // Real file on disk for this test. - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - const base::FilePath kDbFile = temp_dir.path().AppendASCII("upgrade4.db"); - - const GURL kMockOrigin("http://mockorigin/"); - const char kNamespaceUrlFormat[] = "namespace%d"; - const char kWhitelistUrlFormat[] = "whitelist%d"; - const char kTargetUrlFormat[] = "target%d"; - const int kNumNamespaces = 10; - const int kWhitelistCacheId = 1; - - // Create a v4 schema based database containing some fallback records. - { - const int kVersion4 = 4; - const char kGroupsTable[] = "Groups"; - const char kCachesTable[] = "Caches"; - const char kEntriesTable[] = "Entries"; - const char kNamespacesTable[] = "Namespaces"; - const char kOnlineWhiteListsTable[] = "OnlineWhiteLists"; - const char kDeletableResponseIdsTable[] = "DeletableResponseIds"; - - struct TableInfo { - const char* table_name; - const char* columns; - }; - - struct IndexInfo { - const char* index_name; - const char* table_name; - const char* columns; - bool unique; - }; - - const TableInfo kTables4[] = { - { kGroupsTable, - "(group_id INTEGER PRIMARY KEY," - " origin TEXT," - " manifest_url TEXT," - " creation_time INTEGER," - " last_access_time INTEGER)" }, - - { kCachesTable, - "(cache_id INTEGER PRIMARY KEY," - " group_id INTEGER," - " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1))," - " update_time INTEGER," - " cache_size INTEGER)" }, // intentionally not normalized - - { kEntriesTable, - "(cache_id INTEGER," - " url TEXT," - " flags INTEGER," - " response_id INTEGER," - " response_size INTEGER)" }, - - { kNamespacesTable, - "(cache_id INTEGER," - " origin TEXT," // intentionally not normalized - " type INTEGER," - " namespace_url TEXT," - " target_url TEXT)" }, - - { kOnlineWhiteListsTable, - "(cache_id INTEGER," - " namespace_url TEXT)" }, - - { kDeletableResponseIdsTable, - "(response_id INTEGER NOT NULL)" }, - }; - - const IndexInfo kIndexes4[] = { - { "GroupsOriginIndex", - kGroupsTable, - "(origin)", - false }, - - { "GroupsManifestIndex", - kGroupsTable, - "(manifest_url)", - true }, - - { "CachesGroupIndex", - kCachesTable, - "(group_id)", - false }, - - { "EntriesCacheIndex", - kEntriesTable, - "(cache_id)", - false }, - - { "EntriesCacheAndUrlIndex", - kEntriesTable, - "(cache_id, url)", - true }, - - { "EntriesResponseIdIndex", - kEntriesTable, - "(response_id)", - true }, - - { "NamespacesCacheIndex", - kNamespacesTable, - "(cache_id)", - false }, - - { "NamespacesOriginIndex", - kNamespacesTable, - "(origin)", - false }, - - { "NamespacesCacheAndUrlIndex", - kNamespacesTable, - "(cache_id, namespace_url)", - true }, - - { "OnlineWhiteListCacheIndex", - kOnlineWhiteListsTable, - "(cache_id)", - false }, - - { "DeletableResponsesIdIndex", - kDeletableResponseIdsTable, - "(response_id)", - true }, - }; - - const int kTableCount4 = ARRAYSIZE_UNSAFE(kTables4); - const int kIndexCount4 = ARRAYSIZE_UNSAFE(kIndexes4); - - sql::Connection connection; - EXPECT_TRUE(connection.Open(kDbFile)); - - sql::Transaction transaction(&connection); - EXPECT_TRUE(transaction.Begin()); - - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&connection, kVersion4, kVersion4)); - - for (int i = 0; i < kTableCount4; ++i) { - std::string sql("CREATE TABLE "); - sql += kTables4[i].table_name; - sql += kTables4[i].columns; - EXPECT_TRUE(connection.Execute(sql.c_str())); - } - - for (int i = 0; i < kIndexCount4; ++i) { - std::string sql; - if (kIndexes4[i].unique) - sql += "CREATE UNIQUE INDEX "; - else - sql += "CREATE INDEX "; - sql += kIndexes4[i].index_name; - sql += " ON "; - sql += kIndexes4[i].table_name; - sql += kIndexes4[i].columns; - EXPECT_TRUE(connection.Execute(sql.c_str())); - } - - const char* kNamespacesSql = - "INSERT INTO Namespaces" - " (cache_id, origin, type, namespace_url, target_url)" - " VALUES (?, ?, ?, ?, ?)"; - sql::Statement statement; - statement.Assign(connection.GetUniqueStatement(kNamespacesSql)); - EXPECT_TRUE(statement.is_valid()); - for (int i = 0; i < kNumNamespaces; ++i) { - GURL namespace_url( - kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i))); - GURL target_url( - kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i))); - statement.BindInt64(0, i); - statement.BindString(1, kMockOrigin.spec().c_str()); - statement.BindInt(2, FALLBACK_NAMESPACE); - statement.BindString(3, namespace_url.spec().c_str()); - statement.BindString(4, target_url.spec().c_str()); - ASSERT_TRUE(statement.Run()); - statement.Reset(true); - } - - const char* kWhitelistsSql = - "INSERT INTO OnlineWhiteLists" - " (cache_id, namespace_url)" - " VALUES (?, ?)"; - statement.Assign(connection.GetUniqueStatement(kWhitelistsSql)); - EXPECT_TRUE(statement.is_valid()); - for (int i = 0; i < kNumNamespaces; ++i) { - GURL namespace_url( - kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i))); - statement.BindInt64(0, kWhitelistCacheId); - statement.BindString(1, namespace_url.spec().c_str()); - ASSERT_TRUE(statement.Run()); - statement.Reset(true); - } - - EXPECT_TRUE(transaction.Commit()); - } - - // Open that database and verify that it got upgraded to v5. - AppCacheDatabase db(kDbFile); - EXPECT_TRUE(db.LazyOpen(true)); - EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "is_pattern")); - EXPECT_TRUE(db.db_->DoesColumnExist("OnlineWhiteLists", "is_pattern")); - EXPECT_EQ(5, db.meta_table_->GetVersionNumber()); - EXPECT_EQ(5, db.meta_table_->GetCompatibleVersionNumber()); - - std::vector<AppCacheDatabase::NamespaceRecord> intercepts; - std::vector<AppCacheDatabase::NamespaceRecord> fallbacks; - EXPECT_TRUE(db.FindNamespacesForOrigin(kMockOrigin, &intercepts, - &fallbacks)); - EXPECT_TRUE(intercepts.empty()); - EXPECT_EQ(kNumNamespaces, static_cast<int>(fallbacks.size())); - - std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists; - EXPECT_TRUE(db.FindOnlineWhiteListForCache(kWhitelistCacheId, &whitelists)); - EXPECT_EQ(kNumNamespaces, static_cast<int>(whitelists.size())); - - for (int i = 0; i < kNumNamespaces; ++i) { - GURL expected_namespace_url( - kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i))); - GURL expected_target_url( - kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i))); - GURL expected_whitelist_url( - kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i))); - - EXPECT_EQ(i, fallbacks[i].cache_id); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[i].namespace_.type); - EXPECT_EQ(kMockOrigin, fallbacks[i].origin); - EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_.namespace_url); - EXPECT_EQ(expected_target_url, fallbacks[i].namespace_.target_url); - EXPECT_FALSE(fallbacks[i].namespace_.is_pattern); - EXPECT_EQ(expected_whitelist_url, whitelists[i].namespace_url); - EXPECT_FALSE(whitelists[i].is_pattern); - } -} -#endif // !APPCACHE_USE_SIMPLE_CACHE - -} // namespace appcache diff --git a/webkit/browser/appcache/appcache_disk_cache_unittest.cc b/webkit/browser/appcache/appcache_disk_cache_unittest.cc deleted file mode 100644 index 663292e..0000000 --- a/webkit/browser/appcache/appcache_disk_cache_unittest.cc +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2014 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 "base/bind.h" -#include "base/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/run_loop.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/browser/appcache/appcache_disk_cache.h" - -namespace appcache { - -class AppCacheDiskCacheTest : public testing::Test { - public: - AppCacheDiskCacheTest() {} - - virtual void SetUp() OVERRIDE { - // Use the current thread for the DiskCache's cache_thread. - message_loop_.reset(new base::MessageLoopForIO()); - cache_thread_ = base::MessageLoopProxy::current(); - ASSERT_TRUE(directory_.CreateUniqueTempDir()); - completion_callback_ = base::Bind( - &AppCacheDiskCacheTest::OnComplete, - base::Unretained(this)); - } - - virtual void TearDown() OVERRIDE { - base::RunLoop().RunUntilIdle(); - message_loop_.reset(NULL); - } - - void FlushCacheTasks() { - base::RunLoop().RunUntilIdle(); - } - - void OnComplete(int err) { - completion_results_.push_back(err); - } - - base::ScopedTempDir directory_; - scoped_ptr<base::MessageLoop> message_loop_; - scoped_refptr<base::MessageLoopProxy> cache_thread_; - net::CompletionCallback completion_callback_; - std::vector<int> completion_results_; - - static const int k10MBytes = 10 * 1024 * 1024; -}; - -TEST_F(AppCacheDiskCacheTest, DisablePriorToInitCompletion) { - AppCacheDiskCache::Entry* entry = NULL; - - // Create an instance and start it initializing, queue up - // one of each kind of "entry" function. - scoped_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache); - EXPECT_FALSE(disk_cache->is_disabled()); - disk_cache->InitWithDiskBackend( - directory_.path(), k10MBytes, false, cache_thread_, - completion_callback_); - disk_cache->CreateEntry(1, &entry, completion_callback_); - disk_cache->OpenEntry(2, &entry, completion_callback_); - disk_cache->DoomEntry(3, completion_callback_); - - // Pull the plug on all that. - EXPECT_FALSE(disk_cache->is_disabled()); - disk_cache->Disable(); - EXPECT_TRUE(disk_cache->is_disabled()); - - FlushCacheTasks(); - - EXPECT_EQ(NULL, entry); - EXPECT_EQ(4u, completion_results_.size()); - for (std::vector<int>::const_iterator iter = completion_results_.begin(); - iter < completion_results_.end(); ++iter) { - EXPECT_EQ(net::ERR_ABORTED, *iter); - } - - // Ensure the directory can be deleted at this point. - EXPECT_TRUE(base::DirectoryExists(directory_.path())); - EXPECT_FALSE(base::IsDirectoryEmpty(directory_.path())); - EXPECT_TRUE(base::DeleteFile(directory_.path(), true)); - EXPECT_FALSE(base::DirectoryExists(directory_.path())); -} - -TEST_F(AppCacheDiskCacheTest, DisableAfterInitted) { - // Create an instance and let it fully init. - scoped_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache); - EXPECT_FALSE(disk_cache->is_disabled()); - disk_cache->InitWithDiskBackend( - directory_.path(), k10MBytes, false, cache_thread_, - completion_callback_); - FlushCacheTasks(); - EXPECT_EQ(1u, completion_results_.size()); - EXPECT_EQ(net::OK, completion_results_[0]); - - // Pull the plug - disk_cache->Disable(); - FlushCacheTasks(); - - // Ensure the directory can be deleted at this point. - EXPECT_TRUE(base::DirectoryExists(directory_.path())); - EXPECT_FALSE(base::IsDirectoryEmpty(directory_.path())); - EXPECT_TRUE(base::DeleteFile(directory_.path(), true)); - EXPECT_FALSE(base::DirectoryExists(directory_.path())); - - // Methods should return immediately when disabled and not invoke - // the callback at all. - AppCacheDiskCache::Entry* entry = NULL; - completion_results_.clear(); - EXPECT_EQ(net::ERR_ABORTED, - disk_cache->CreateEntry(1, &entry, completion_callback_)); - EXPECT_EQ(net::ERR_ABORTED, - disk_cache->OpenEntry(2, &entry, completion_callback_)); - EXPECT_EQ(net::ERR_ABORTED, - disk_cache->DoomEntry(3, completion_callback_)); - FlushCacheTasks(); - EXPECT_TRUE(completion_results_.empty()); -} - -// Flaky on Android: http://crbug.com/339534 -TEST_F(AppCacheDiskCacheTest, DISABLED_DisableWithEntriesOpen) { - // Create an instance and let it fully init. - scoped_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache); - EXPECT_FALSE(disk_cache->is_disabled()); - disk_cache->InitWithDiskBackend( - directory_.path(), k10MBytes, false, cache_thread_, - completion_callback_); - FlushCacheTasks(); - EXPECT_EQ(1u, completion_results_.size()); - EXPECT_EQ(net::OK, completion_results_[0]); - - // Note: We don't have detailed expectations of the DiskCache - // operations because on android it's really SimpleCache which - // does behave differently. - // - // What matters for the corruption handling and service reinitiazation - // is that the directory can be deleted after the calling Disable() method, - // and we do have expectations about that. - - // Create/open some entries. - AppCacheDiskCache::Entry* entry1 = NULL; - AppCacheDiskCache::Entry* entry2 = NULL; - disk_cache->CreateEntry(1, &entry1, completion_callback_); - disk_cache->CreateEntry(2, &entry2, completion_callback_); - FlushCacheTasks(); - EXPECT_TRUE(entry1); - EXPECT_TRUE(entry2); - - // Write something to one of the entries and flush it. - const char* kData = "Hello"; - const int kDataLen = strlen(kData) + 1; - scoped_refptr<net::IOBuffer> write_buf(new net::WrappedIOBuffer(kData)); - entry1->Write(0, 0, write_buf, kDataLen, completion_callback_); - FlushCacheTasks(); - - // Queue up a read and a write. - scoped_refptr<net::IOBuffer> read_buf = new net::IOBuffer(kDataLen); - entry1->Read(0, 0, read_buf.get(), kDataLen, completion_callback_); - entry2->Write(0, 0, write_buf.get(), kDataLen, completion_callback_); - - // Pull the plug - disk_cache->Disable(); - FlushCacheTasks(); - - // Ensure the directory can be deleted at this point. - EXPECT_TRUE(base::DirectoryExists(directory_.path())); - EXPECT_FALSE(base::IsDirectoryEmpty(directory_.path())); - EXPECT_TRUE(base::DeleteFile(directory_.path(), true)); - EXPECT_FALSE(base::DirectoryExists(directory_.path())); - - disk_cache.reset(NULL); - - // Also, new IO operations should fail immediately. - EXPECT_EQ( - net::ERR_ABORTED, - entry1->Read(0, 0, read_buf.get(), kDataLen, completion_callback_)); - entry1->Close(); - entry2->Close(); - - FlushCacheTasks(); -} - -} // namespace appcache diff --git a/webkit/browser/appcache/appcache_group.h b/webkit/browser/appcache/appcache_group.h index 82f33ef..fda32127 100644 --- a/webkit/browser/appcache/appcache_group.h +++ b/webkit/browser/appcache/appcache_group.h @@ -17,6 +17,15 @@ #include "url/gurl.h" #include "webkit/browser/webkit_storage_browser_export.h" +namespace content { +FORWARD_DECLARE_TEST(AppCacheGroupTest, StartUpdate); +FORWARD_DECLARE_TEST(AppCacheGroupTest, CancelUpdate); +FORWARD_DECLARE_TEST(AppCacheGroupTest, QueueUpdate); +FORWARD_DECLARE_TEST(AppCacheUpdateJobTest, AlreadyChecking); +FORWARD_DECLARE_TEST(AppCacheUpdateJobTest, AlreadyDownloading); +class AppCacheUpdateJobTest; +} + namespace appcache { class AppCache; @@ -94,9 +103,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheGroup private: class HostObserver; - friend class AppCacheUpdateJob; - friend class AppCacheUpdateJobTest; friend class base::RefCounted<AppCacheGroup>; + friend class content::AppCacheUpdateJobTest; + friend class AppCacheUpdateJob; friend class MockAppCacheStorage; // for old_caches() ~AppCacheGroup(); @@ -153,11 +162,11 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheGroup // True if we're in our destructor. bool is_in_dtor_; - FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, StartUpdate); - FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, CancelUpdate); - FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, QueueUpdate); - FRIEND_TEST_ALL_PREFIXES(AppCacheUpdateJobTest, AlreadyChecking); - FRIEND_TEST_ALL_PREFIXES(AppCacheUpdateJobTest, AlreadyDownloading); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, StartUpdate); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, CancelUpdate); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, QueueUpdate); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheUpdateJobTest, AlreadyChecking); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheUpdateJobTest, AlreadyDownloading); DISALLOW_COPY_AND_ASSIGN(AppCacheGroup); }; diff --git a/webkit/browser/appcache/appcache_group_unittest.cc b/webkit/browser/appcache/appcache_group_unittest.cc deleted file mode 100644 index bb574cb..0000000 --- a/webkit/browser/appcache/appcache_group_unittest.cc +++ /dev/null @@ -1,302 +0,0 @@ -// 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/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 appcache::ErrorDetails& details) - 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 diff --git a/webkit/browser/appcache/appcache_host.h b/webkit/browser/appcache/appcache_host.h index aef8463..2f0f068 100644 --- a/webkit/browser/appcache/appcache_host.h +++ b/webkit/browser/appcache/appcache_host.h @@ -22,6 +22,8 @@ class URLRequest; } // namespace net namespace content { +FORWARD_DECLARE_TEST(AppCacheGroupTest, CleanupUnusedGroup); +FORWARD_DECLARE_TEST(AppCacheGroupTest, QueueUpdate); FORWARD_DECLARE_TEST(AppCacheHostTest, Basic); FORWARD_DECLARE_TEST(AppCacheHostTest, SelectNoCache); FORWARD_DECLARE_TEST(AppCacheHostTest, ForeignEntry); @@ -31,9 +33,13 @@ FORWARD_DECLARE_TEST(AppCacheHostTest, SetSwappableCache); FORWARD_DECLARE_TEST(AppCacheHostTest, ForDedicatedWorker); FORWARD_DECLARE_TEST(AppCacheHostTest, SelectCacheAllowed); FORWARD_DECLARE_TEST(AppCacheHostTest, SelectCacheBlocked); +FORWARD_DECLARE_TEST(AppCacheTest, CleanupUnusedCache); +class AppCacheTest; class AppCacheHostTest; +class AppCacheGroupTest; class AppCacheStorageImplTest; class AppCacheRequestHandlerTest; +class AppCacheUpdateJobTest; } namespace appcache { @@ -175,7 +181,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheHost friend class content::AppCacheHostTest; friend class content::AppCacheStorageImplTest; friend class content::AppCacheRequestHandlerTest; - friend class AppCacheUpdateJobTest; + friend class content::AppCacheUpdateJobTest; Status GetStatus(); void LoadSelectedCache(int64 cache_id); @@ -311,8 +317,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheHost // First party url to be used in policy checks. GURL first_party_url_; - FRIEND_TEST_ALL_PREFIXES(AppCacheTest, CleanupUnusedCache); - FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, CleanupUnusedGroup); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, CleanupUnusedGroup); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, QueueUpdate); FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, Basic); FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, SelectNoCache); FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, ForeignEntry); @@ -322,7 +328,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheHost FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, ForDedicatedWorker); FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, SelectCacheAllowed); FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, SelectCacheBlocked); - FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, QueueUpdate); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheTest, CleanupUnusedCache); DISALLOW_COPY_AND_ASSIGN(AppCacheHost); }; diff --git a/webkit/browser/appcache/appcache_quota_client.h b/webkit/browser/appcache/appcache_quota_client.h index c490183..90ba852 100644 --- a/webkit/browser/appcache/appcache_quota_client.h +++ b/webkit/browser/appcache/appcache_quota_client.h @@ -19,6 +19,10 @@ #include "webkit/browser/webkit_storage_browser_export.h" #include "webkit/common/quota/quota_types.h" +namespace content { +class AppCacheQuotaClientTest; +} + namespace appcache { class AppCacheService; @@ -53,9 +57,9 @@ class AppCacheQuotaClient : public quota::QuotaClient { virtual bool DoesSupport(quota::StorageType type) const OVERRIDE; private: + friend class content::AppCacheQuotaClientTest; friend class AppCacheService; // for NotifyAppCacheIsDestroyed friend class AppCacheStorageImpl; // for NotifyAppCacheIsReady - friend class AppCacheQuotaClientTest; WEBKIT_STORAGE_BROWSER_EXPORT explicit AppCacheQuotaClient(AppCacheService* service); diff --git a/webkit/browser/appcache/appcache_quota_client_unittest.cc b/webkit/browser/appcache/appcache_quota_client_unittest.cc deleted file mode 100644 index 5b7aded..0000000 --- a/webkit/browser/appcache/appcache_quota_client_unittest.cc +++ /dev/null @@ -1,435 +0,0 @@ -// 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 <map> -#include <set> - -#include "base/bind.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/run_loop.h" -#include "net/base/net_errors.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/browser/appcache/appcache_quota_client.h" -#include "webkit/browser/appcache/mock_appcache_service.h" - -namespace appcache { - -// Declared to shorten the line lengths. -static const quota::StorageType kTemp = quota::kStorageTypeTemporary; -static const quota::StorageType kPerm = quota::kStorageTypePersistent; - -// Base class for our test fixtures. -class AppCacheQuotaClientTest : public testing::Test { - public: - const GURL kOriginA; - const GURL kOriginB; - const GURL kOriginOther; - - AppCacheQuotaClientTest() - : kOriginA("http://host"), - kOriginB("http://host:8000"), - kOriginOther("http://other"), - usage_(0), - delete_status_(quota::kQuotaStatusUnknown), - num_get_origin_usage_completions_(0), - num_get_origins_completions_(0), - num_delete_origins_completions_(0), - weak_factory_(this) { - } - - int64 GetOriginUsage( - quota::QuotaClient* client, - const GURL& origin, - quota::StorageType type) { - usage_ = -1; - AsyncGetOriginUsage(client, origin, type); - base::RunLoop().RunUntilIdle(); - return usage_; - } - - const std::set<GURL>& GetOriginsForType( - quota::QuotaClient* client, - quota::StorageType type) { - origins_.clear(); - AsyncGetOriginsForType(client, type); - base::RunLoop().RunUntilIdle(); - return origins_; - } - - const std::set<GURL>& GetOriginsForHost( - quota::QuotaClient* client, - quota::StorageType type, - const std::string& host) { - origins_.clear(); - AsyncGetOriginsForHost(client, type, host); - base::RunLoop().RunUntilIdle(); - return origins_; - } - - quota::QuotaStatusCode DeleteOriginData( - quota::QuotaClient* client, - quota::StorageType type, - const GURL& origin) { - delete_status_ = quota::kQuotaStatusUnknown; - AsyncDeleteOriginData(client, type, origin); - base::RunLoop().RunUntilIdle(); - return delete_status_; - } - - void AsyncGetOriginUsage( - quota::QuotaClient* client, - const GURL& origin, - quota::StorageType type) { - client->GetOriginUsage( - origin, type, - base::Bind(&AppCacheQuotaClientTest::OnGetOriginUsageComplete, - weak_factory_.GetWeakPtr())); - } - - void AsyncGetOriginsForType( - quota::QuotaClient* client, - quota::StorageType type) { - client->GetOriginsForType( - type, - base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete, - weak_factory_.GetWeakPtr())); - } - - void AsyncGetOriginsForHost( - quota::QuotaClient* client, - quota::StorageType type, - const std::string& host) { - client->GetOriginsForHost( - type, host, - base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete, - weak_factory_.GetWeakPtr())); - } - - void AsyncDeleteOriginData( - quota::QuotaClient* client, - quota::StorageType type, - const GURL& origin) { - client->DeleteOriginData( - origin, type, - base::Bind(&AppCacheQuotaClientTest::OnDeleteOriginDataComplete, - weak_factory_.GetWeakPtr())); - } - - void SetUsageMapEntry(const GURL& origin, int64 usage) { - mock_service_.storage()->usage_map_[origin] = usage; - } - - AppCacheQuotaClient* CreateClient() { - return new AppCacheQuotaClient(&mock_service_); - } - - void Call_NotifyAppCacheReady(AppCacheQuotaClient* client) { - client->NotifyAppCacheReady(); - } - - void Call_NotifyAppCacheDestroyed(AppCacheQuotaClient* client) { - client->NotifyAppCacheDestroyed(); - } - - void Call_OnQuotaManagerDestroyed(AppCacheQuotaClient* client) { - client->OnQuotaManagerDestroyed(); - } - - protected: - void OnGetOriginUsageComplete(int64 usage) { - ++num_get_origin_usage_completions_; - usage_ = usage; - } - - void OnGetOriginsComplete(const std::set<GURL>& origins) { - ++num_get_origins_completions_; - origins_ = origins; - } - - void OnDeleteOriginDataComplete(quota::QuotaStatusCode status) { - ++num_delete_origins_completions_; - delete_status_ = status; - } - - base::MessageLoop message_loop_; - int64 usage_; - std::set<GURL> origins_; - quota::QuotaStatusCode delete_status_; - int num_get_origin_usage_completions_; - int num_get_origins_completions_; - int num_delete_origins_completions_; - MockAppCacheService mock_service_; - base::WeakPtrFactory<AppCacheQuotaClientTest> weak_factory_; -}; - - -TEST_F(AppCacheQuotaClientTest, BasicCreateDestroy) { - AppCacheQuotaClient* client = CreateClient(); - Call_NotifyAppCacheReady(client); - Call_OnQuotaManagerDestroyed(client); - Call_NotifyAppCacheDestroyed(client); -} - -TEST_F(AppCacheQuotaClientTest, EmptyService) { - AppCacheQuotaClient* client = CreateClient(); - Call_NotifyAppCacheReady(client); - - EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kTemp)); - EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm)); - EXPECT_TRUE(GetOriginsForType(client, kTemp).empty()); - EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); - EXPECT_TRUE(GetOriginsForHost(client, kTemp, kOriginA.host()).empty()); - EXPECT_TRUE(GetOriginsForHost(client, kPerm, kOriginA.host()).empty()); - EXPECT_EQ(quota::kQuotaStatusOk, DeleteOriginData(client, kTemp, kOriginA)); - EXPECT_EQ(quota::kQuotaStatusOk, DeleteOriginData(client, kPerm, kOriginA)); - - Call_NotifyAppCacheDestroyed(client); - Call_OnQuotaManagerDestroyed(client); -} - -TEST_F(AppCacheQuotaClientTest, NoService) { - AppCacheQuotaClient* client = CreateClient(); - Call_NotifyAppCacheReady(client); - Call_NotifyAppCacheDestroyed(client); - - EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kTemp)); - EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm)); - EXPECT_TRUE(GetOriginsForType(client, kTemp).empty()); - EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); - EXPECT_TRUE(GetOriginsForHost(client, kTemp, kOriginA.host()).empty()); - EXPECT_TRUE(GetOriginsForHost(client, kPerm, kOriginA.host()).empty()); - EXPECT_EQ(quota::kQuotaErrorAbort, - DeleteOriginData(client, kTemp, kOriginA)); - EXPECT_EQ(quota::kQuotaErrorAbort, - DeleteOriginData(client, kPerm, kOriginA)); - - Call_OnQuotaManagerDestroyed(client); -} - -TEST_F(AppCacheQuotaClientTest, GetOriginUsage) { - AppCacheQuotaClient* client = CreateClient(); - Call_NotifyAppCacheReady(client); - - SetUsageMapEntry(kOriginA, 1000); - EXPECT_EQ(1000, GetOriginUsage(client, kOriginA, kTemp)); - EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm)); - - Call_NotifyAppCacheDestroyed(client); - Call_OnQuotaManagerDestroyed(client); -} - -TEST_F(AppCacheQuotaClientTest, GetOriginsForHost) { - AppCacheQuotaClient* client = CreateClient(); - Call_NotifyAppCacheReady(client); - - EXPECT_EQ(kOriginA.host(), kOriginB.host()); - EXPECT_NE(kOriginA.host(), kOriginOther.host()); - - std::set<GURL> origins = GetOriginsForHost(client, kTemp, kOriginA.host()); - EXPECT_TRUE(origins.empty()); - - SetUsageMapEntry(kOriginA, 1000); - SetUsageMapEntry(kOriginB, 10); - SetUsageMapEntry(kOriginOther, 500); - - origins = GetOriginsForHost(client, kTemp, kOriginA.host()); - EXPECT_EQ(2ul, origins.size()); - EXPECT_TRUE(origins.find(kOriginA) != origins.end()); - EXPECT_TRUE(origins.find(kOriginB) != origins.end()); - - origins = GetOriginsForHost(client, kTemp, kOriginOther.host()); - EXPECT_EQ(1ul, origins.size()); - EXPECT_TRUE(origins.find(kOriginOther) != origins.end()); - - origins = GetOriginsForHost(client, kPerm, kOriginA.host()); - EXPECT_TRUE(origins.empty()); - - Call_NotifyAppCacheDestroyed(client); - Call_OnQuotaManagerDestroyed(client); -} - -TEST_F(AppCacheQuotaClientTest, GetOriginsForType) { - AppCacheQuotaClient* client = CreateClient(); - Call_NotifyAppCacheReady(client); - - EXPECT_TRUE(GetOriginsForType(client, kTemp).empty()); - EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); - - SetUsageMapEntry(kOriginA, 1000); - SetUsageMapEntry(kOriginB, 10); - - std::set<GURL> origins = GetOriginsForType(client, kTemp); - EXPECT_EQ(2ul, origins.size()); - EXPECT_TRUE(origins.find(kOriginA) != origins.end()); - EXPECT_TRUE(origins.find(kOriginB) != origins.end()); - - EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); - - Call_NotifyAppCacheDestroyed(client); - Call_OnQuotaManagerDestroyed(client); -} - -TEST_F(AppCacheQuotaClientTest, DeleteOriginData) { - AppCacheQuotaClient* client = CreateClient(); - Call_NotifyAppCacheReady(client); - - // Perm deletions are short circuited in the Client and - // should not reach the AppCacheService. - EXPECT_EQ(quota::kQuotaStatusOk, - DeleteOriginData(client, kPerm, kOriginA)); - EXPECT_EQ(0, mock_service_.delete_called_count()); - - EXPECT_EQ(quota::kQuotaStatusOk, - DeleteOriginData(client, kTemp, kOriginA)); - EXPECT_EQ(1, mock_service_.delete_called_count()); - - mock_service_.set_mock_delete_appcaches_for_origin_result( - net::ERR_ABORTED); - EXPECT_EQ(quota::kQuotaErrorAbort, - DeleteOriginData(client, kTemp, kOriginA)); - EXPECT_EQ(2, mock_service_.delete_called_count()); - - Call_OnQuotaManagerDestroyed(client); - Call_NotifyAppCacheDestroyed(client); -} - -TEST_F(AppCacheQuotaClientTest, PendingRequests) { - AppCacheQuotaClient* client = CreateClient(); - - SetUsageMapEntry(kOriginA, 1000); - SetUsageMapEntry(kOriginB, 10); - SetUsageMapEntry(kOriginOther, 500); - - // Queue up some reqeusts. - AsyncGetOriginUsage(client, kOriginA, kPerm); - AsyncGetOriginUsage(client, kOriginB, kTemp); - AsyncGetOriginsForType(client, kPerm); - AsyncGetOriginsForType(client, kTemp); - AsyncGetOriginsForHost(client, kTemp, kOriginA.host()); - AsyncGetOriginsForHost(client, kTemp, kOriginOther.host()); - AsyncDeleteOriginData(client, kTemp, kOriginA); - AsyncDeleteOriginData(client, kPerm, kOriginA); - AsyncDeleteOriginData(client, kTemp, kOriginB); - - EXPECT_EQ(0, num_get_origin_usage_completions_); - EXPECT_EQ(0, num_get_origins_completions_); - EXPECT_EQ(0, num_delete_origins_completions_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, num_get_origin_usage_completions_); - EXPECT_EQ(0, num_get_origins_completions_); - EXPECT_EQ(0, num_delete_origins_completions_); - - // Pending requests should get serviced when the appcache is ready. - Call_NotifyAppCacheReady(client); - EXPECT_EQ(2, num_get_origin_usage_completions_); - EXPECT_EQ(4, num_get_origins_completions_); - EXPECT_EQ(0, num_delete_origins_completions_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(3, num_delete_origins_completions_); // deletes are really async - - // They should be serviced in order requested. - EXPECT_EQ(10, usage_); - EXPECT_EQ(1ul, origins_.size()); - EXPECT_TRUE(origins_.find(kOriginOther) != origins_.end()); - - Call_NotifyAppCacheDestroyed(client); - Call_OnQuotaManagerDestroyed(client); -} - -TEST_F(AppCacheQuotaClientTest, DestroyServiceWithPending) { - AppCacheQuotaClient* client = CreateClient(); - - SetUsageMapEntry(kOriginA, 1000); - SetUsageMapEntry(kOriginB, 10); - SetUsageMapEntry(kOriginOther, 500); - - // Queue up some reqeusts prior to being ready. - AsyncGetOriginUsage(client, kOriginA, kPerm); - AsyncGetOriginUsage(client, kOriginB, kTemp); - AsyncGetOriginsForType(client, kPerm); - AsyncGetOriginsForType(client, kTemp); - AsyncGetOriginsForHost(client, kTemp, kOriginA.host()); - AsyncGetOriginsForHost(client, kTemp, kOriginOther.host()); - AsyncDeleteOriginData(client, kTemp, kOriginA); - AsyncDeleteOriginData(client, kPerm, kOriginA); - AsyncDeleteOriginData(client, kTemp, kOriginB); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, num_get_origin_usage_completions_); - EXPECT_EQ(0, num_get_origins_completions_); - EXPECT_EQ(0, num_delete_origins_completions_); - - // Kill the service. - Call_NotifyAppCacheDestroyed(client); - - // All should have been aborted and called completion. - EXPECT_EQ(2, num_get_origin_usage_completions_); - EXPECT_EQ(4, num_get_origins_completions_); - EXPECT_EQ(3, num_delete_origins_completions_); - EXPECT_EQ(0, usage_); - EXPECT_TRUE(origins_.empty()); - EXPECT_EQ(quota::kQuotaErrorAbort, delete_status_); - - Call_OnQuotaManagerDestroyed(client); -} - -TEST_F(AppCacheQuotaClientTest, DestroyQuotaManagerWithPending) { - AppCacheQuotaClient* client = CreateClient(); - - SetUsageMapEntry(kOriginA, 1000); - SetUsageMapEntry(kOriginB, 10); - SetUsageMapEntry(kOriginOther, 500); - - // Queue up some reqeusts prior to being ready. - AsyncGetOriginUsage(client, kOriginA, kPerm); - AsyncGetOriginUsage(client, kOriginB, kTemp); - AsyncGetOriginsForType(client, kPerm); - AsyncGetOriginsForType(client, kTemp); - AsyncGetOriginsForHost(client, kTemp, kOriginA.host()); - AsyncGetOriginsForHost(client, kTemp, kOriginOther.host()); - AsyncDeleteOriginData(client, kTemp, kOriginA); - AsyncDeleteOriginData(client, kPerm, kOriginA); - AsyncDeleteOriginData(client, kTemp, kOriginB); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, num_get_origin_usage_completions_); - EXPECT_EQ(0, num_get_origins_completions_); - EXPECT_EQ(0, num_delete_origins_completions_); - - // Kill the quota manager. - Call_OnQuotaManagerDestroyed(client); - Call_NotifyAppCacheReady(client); - - // Callbacks should be deleted and not called. - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, num_get_origin_usage_completions_); - EXPECT_EQ(0, num_get_origins_completions_); - EXPECT_EQ(0, num_delete_origins_completions_); - - Call_NotifyAppCacheDestroyed(client); -} - -TEST_F(AppCacheQuotaClientTest, DestroyWithDeleteInProgress) { - AppCacheQuotaClient* client = CreateClient(); - Call_NotifyAppCacheReady(client); - - // Start an async delete. - AsyncDeleteOriginData(client, kTemp, kOriginB); - EXPECT_EQ(0, num_delete_origins_completions_); - - // Kill the service. - Call_NotifyAppCacheDestroyed(client); - - // Should have been aborted. - EXPECT_EQ(1, num_delete_origins_completions_); - EXPECT_EQ(quota::kQuotaErrorAbort, delete_status_); - - // A real completion callback from the service should - // be dropped if it comes in after NotifyAppCacheDestroyed. - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, num_delete_origins_completions_); - EXPECT_EQ(quota::kQuotaErrorAbort, delete_status_); - - Call_OnQuotaManagerDestroyed(client); -} - -} // namespace appcache diff --git a/webkit/browser/appcache/appcache_response_unittest.cc b/webkit/browser/appcache/appcache_response_unittest.cc deleted file mode 100644 index 1ed7783..0000000 --- a/webkit/browser/appcache/appcache_response_unittest.cc +++ /dev/null @@ -1,717 +0,0 @@ -// 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 <stack> -#include <string> -#include <utility> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/pickle.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/http/http_response_headers.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/browser/appcache/appcache_response.h" -#include "webkit/browser/appcache/mock_appcache_service.h" - -using net::IOBuffer; -using net::WrappedIOBuffer; - -namespace appcache { - -static const int kNumBlocks = 4; -static const int kBlockSize = 1024; -static const int kNoSuchResponseId = 123; - -class AppCacheResponseTest : public testing::Test { - public: - - // Test Harness ------------------------------------------------------------- - - // Helper class used to verify test results - class MockStorageDelegate : public AppCacheStorage::Delegate { - public: - explicit MockStorageDelegate(AppCacheResponseTest* test) - : loaded_info_id_(0), test_(test) { - } - - virtual void OnResponseInfoLoaded(AppCacheResponseInfo* info, - int64 response_id) OVERRIDE { - loaded_info_ = info; - loaded_info_id_ = response_id; - test_->ScheduleNextTask(); - } - - scoped_refptr<AppCacheResponseInfo> loaded_info_; - int64 loaded_info_id_; - AppCacheResponseTest* test_; - }; - - // Helper callback to run a test on our io_thread. The io_thread is spun up - // once and reused for all tests. - template <class Method> - void MethodWrapper(Method method) { - SetUpTest(); - (this->*method)(); - } - - static void SetUpTestCase() { - io_thread_.reset(new base::Thread("AppCacheResponseTest Thread")); - base::Thread::Options options(base::MessageLoop::TYPE_IO, 0); - io_thread_->StartWithOptions(options); - } - - static void TearDownTestCase() { - io_thread_.reset(NULL); - } - - AppCacheResponseTest() {} - - template <class Method> - void RunTestOnIOThread(Method method) { - test_finished_event_ .reset(new base::WaitableEvent(false, false)); - io_thread_->message_loop()->PostTask( - FROM_HERE, base::Bind(&AppCacheResponseTest::MethodWrapper<Method>, - base::Unretained(this), method)); - test_finished_event_->Wait(); - } - - void SetUpTest() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); - DCHECK(task_stack_.empty()); - storage_delegate_.reset(new MockStorageDelegate(this)); - service_.reset(new MockAppCacheService()); - expected_read_result_ = 0; - expected_write_result_ = 0; - written_response_id_ = 0; - should_delete_reader_in_completion_callback_ = false; - should_delete_writer_in_completion_callback_ = false; - reader_deletion_count_down_ = 0; - writer_deletion_count_down_ = 0; - read_callback_was_called_ = false; - write_callback_was_called_ = false; - } - - void TearDownTest() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); - while (!task_stack_.empty()) - task_stack_.pop(); - - reader_.reset(); - read_buffer_ = NULL; - read_info_buffer_ = NULL; - writer_.reset(); - write_buffer_ = NULL; - write_info_buffer_ = NULL; - storage_delegate_.reset(); - service_.reset(); - } - - void TestFinished() { - // We unwind the stack prior to finishing up to let stack - // based objects get deleted. - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); - base::MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(&AppCacheResponseTest::TestFinishedUnwound, - base::Unretained(this))); - } - - void TestFinishedUnwound() { - TearDownTest(); - test_finished_event_->Signal(); - } - - void PushNextTask(const base::Closure& task) { - task_stack_.push(std::pair<base::Closure, bool>(task, false)); - } - - void PushNextTaskAsImmediate(const base::Closure& task) { - task_stack_.push(std::pair<base::Closure, bool>(task, true)); - } - - void ScheduleNextTask() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); - if (task_stack_.empty()) { - TestFinished(); - return; - } - base::Closure task = task_stack_.top().first; - bool immediate = task_stack_.top().second; - task_stack_.pop(); - if (immediate) - task.Run(); - else - base::MessageLoop::current()->PostTask(FROM_HERE, task); - } - - // Wrappers to call AppCacheResponseReader/Writer Read and Write methods - - void WriteBasicResponse() { - static const char kHttpHeaders[] = - "HTTP/1.0 200 OK\0Content-Length: 5\0\0"; - static const char* kHttpBody = "Hello"; - scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody)); - std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders)); - WriteResponse( - MakeHttpResponseInfo(raw_headers), body.get(), strlen(kHttpBody)); - } - - int basic_response_size() { return 5; } // should match kHttpBody above - - void WriteResponse(net::HttpResponseInfo* head, - IOBuffer* body, int body_len) { - DCHECK(body); - scoped_refptr<IOBuffer> body_ref(body); - PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseBody, - base::Unretained(this), body_ref, body_len)); - WriteResponseHead(head); - } - - void WriteResponseHead(net::HttpResponseInfo* head) { - EXPECT_FALSE(writer_->IsWritePending()); - expected_write_result_ = GetHttpResponseInfoSize(head); - write_info_buffer_ = new HttpResponseInfoIOBuffer(head); - writer_->WriteInfo(write_info_buffer_.get(), - base::Bind(&AppCacheResponseTest::OnWriteInfoComplete, - base::Unretained(this))); - } - - void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) { - EXPECT_FALSE(writer_->IsWritePending()); - write_buffer_ = io_buffer; - expected_write_result_ = buf_len; - writer_->WriteData(write_buffer_.get(), - buf_len, - base::Bind(&AppCacheResponseTest::OnWriteComplete, - base::Unretained(this))); - } - - void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) { - EXPECT_FALSE(reader_->IsReadPending()); - read_buffer_ = io_buffer; - expected_read_result_ = buf_len; - reader_->ReadData(read_buffer_.get(), - buf_len, - base::Bind(&AppCacheResponseTest::OnReadComplete, - base::Unretained(this))); - } - - // AppCacheResponseReader / Writer completion callbacks - - void OnWriteInfoComplete(int result) { - EXPECT_FALSE(writer_->IsWritePending()); - EXPECT_EQ(expected_write_result_, result); - ScheduleNextTask(); - } - - void OnWriteComplete(int result) { - EXPECT_FALSE(writer_->IsWritePending()); - write_callback_was_called_ = true; - EXPECT_EQ(expected_write_result_, result); - if (should_delete_writer_in_completion_callback_ && - --writer_deletion_count_down_ == 0) { - writer_.reset(); - } - ScheduleNextTask(); - } - - void OnReadInfoComplete(int result) { - EXPECT_FALSE(reader_->IsReadPending()); - EXPECT_EQ(expected_read_result_, result); - ScheduleNextTask(); - } - - void OnReadComplete(int result) { - EXPECT_FALSE(reader_->IsReadPending()); - read_callback_was_called_ = true; - EXPECT_EQ(expected_read_result_, result); - if (should_delete_reader_in_completion_callback_ && - --reader_deletion_count_down_ == 0) { - reader_.reset(); - } - ScheduleNextTask(); - } - - // Helpers to work with HttpResponseInfo objects - - net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) { - net::HttpResponseInfo* info = new net::HttpResponseInfo; - info->request_time = base::Time::Now(); - info->response_time = base::Time::Now(); - info->was_cached = false; - info->headers = new net::HttpResponseHeaders(raw_headers); - return info; - } - - int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) { - Pickle pickle; - return PickleHttpResonseInfo(&pickle, info); - } - - bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1, - const net::HttpResponseInfo* info2) { - Pickle pickle1; - Pickle pickle2; - PickleHttpResonseInfo(&pickle1, info1); - PickleHttpResonseInfo(&pickle2, info2); - return (pickle1.size() == pickle2.size()) && - (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size())); - } - - int PickleHttpResonseInfo(Pickle* pickle, const net::HttpResponseInfo* info) { - const bool kSkipTransientHeaders = true; - const bool kTruncated = false; - info->Persist(pickle, kSkipTransientHeaders, kTruncated); - return pickle->size(); - } - - // Helpers to fill and verify blocks of memory with a value - - void FillData(char value, char* data, int data_len) { - memset(data, value, data_len); - } - - bool CheckData(char value, const char* data, int data_len) { - for (int i = 0; i < data_len; ++i, ++data) { - if (*data != value) - return false; - } - return true; - } - - // Individual Tests --------------------------------------------------------- - // Most of the individual tests involve multiple async steps. Each test - // is delineated with a section header. - - - // ReadNonExistentResponse ------------------------------------------- - void ReadNonExistentResponse() { - // 1. Attempt to ReadInfo - // 2. Attempt to ReadData - - reader_.reset(service_->storage()->CreateResponseReader( - GURL(), 0, kNoSuchResponseId)); - - // Push tasks in reverse order - PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentData, - base::Unretained(this))); - PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentInfo, - base::Unretained(this))); - ScheduleNextTask(); - } - - void ReadNonExistentInfo() { - EXPECT_FALSE(reader_->IsReadPending()); - read_info_buffer_ = new HttpResponseInfoIOBuffer(); - reader_->ReadInfo(read_info_buffer_.get(), - base::Bind(&AppCacheResponseTest::OnReadInfoComplete, - base::Unretained(this))); - EXPECT_TRUE(reader_->IsReadPending()); - expected_read_result_ = net::ERR_CACHE_MISS; - } - - void ReadNonExistentData() { - EXPECT_FALSE(reader_->IsReadPending()); - read_buffer_ = new IOBuffer(kBlockSize); - reader_->ReadData(read_buffer_.get(), - kBlockSize, - base::Bind(&AppCacheResponseTest::OnReadComplete, - base::Unretained(this))); - EXPECT_TRUE(reader_->IsReadPending()); - expected_read_result_ = net::ERR_CACHE_MISS; - } - - // LoadResponseInfo_Miss ---------------------------------------------------- - void LoadResponseInfo_Miss() { - PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Miss_Verify, - base::Unretained(this))); - service_->storage()->LoadResponseInfo(GURL(), 0, kNoSuchResponseId, - storage_delegate_.get()); - } - - void LoadResponseInfo_Miss_Verify() { - EXPECT_EQ(kNoSuchResponseId, storage_delegate_->loaded_info_id_); - EXPECT_TRUE(!storage_delegate_->loaded_info_.get()); - TestFinished(); - } - - // LoadResponseInfo_Hit ---------------------------------------------------- - void LoadResponseInfo_Hit() { - // This tests involves multiple async steps. - // 1. Write a response headers and body to storage - // a. headers - // b. body - // 2. Use LoadResponseInfo to read the response headers back out - PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Step2, - base::Unretained(this))); - writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0)); - written_response_id_ = writer_->response_id(); - WriteBasicResponse(); - } - - void LoadResponseInfo_Hit_Step2() { - writer_.reset(); - PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Verify, - base::Unretained(this))); - service_->storage()->LoadResponseInfo(GURL(), 0, written_response_id_, - storage_delegate_.get()); - } - - void LoadResponseInfo_Hit_Verify() { - EXPECT_EQ(written_response_id_, storage_delegate_->loaded_info_id_); - EXPECT_TRUE(storage_delegate_->loaded_info_.get()); - EXPECT_TRUE(CompareHttpResponseInfos( - write_info_buffer_->http_info.get(), - storage_delegate_->loaded_info_->http_response_info())); - EXPECT_EQ(basic_response_size(), - storage_delegate_->loaded_info_->response_data_size()); - TestFinished(); - } - - // AmountWritten ---------------------------------------------------- - - void AmountWritten() { - static const char kHttpHeaders[] = - "HTTP/1.0 200 OK\0\0"; - std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders)); - net::HttpResponseInfo* head = MakeHttpResponseInfo(raw_headers); - int expected_amount_written = - GetHttpResponseInfoSize(head) + kNumBlocks * kBlockSize; - - // Push tasks in reverse order. - PushNextTask(base::Bind(&AppCacheResponseTest::Verify_AmountWritten, - base::Unretained(this), expected_amount_written)); - for (int i = 0; i < kNumBlocks; ++i) { - PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock, - base::Unretained(this), kNumBlocks - i)); - } - PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseHead, - base::Unretained(this), head)); - - writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0)); - written_response_id_ = writer_->response_id(); - ScheduleNextTask(); - } - - void Verify_AmountWritten(int expected_amount_written) { - EXPECT_EQ(expected_amount_written, writer_->amount_written()); - TestFinished(); - } - - - // WriteThenVariouslyReadResponse ------------------------------------------- - - void WriteThenVariouslyReadResponse() { - // This tests involves multiple async steps. - // 1. First, write a large body using multiple writes, we don't bother - // with a response head for this test. - // 2. Read the entire body, using multiple reads - // 3. Read the entire body, using one read. - // 4. Attempt to read beyond the EOF. - // 5. Read just a range. - // 6. Attempt to read beyond EOF of a range. - - // Push tasks in reverse order - PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangeFullyBeyondEOF, - base::Unretained(this))); - PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangePartiallyBeyondEOF, - base::Unretained(this))); - PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF, - base::Unretained(this))); - PushNextTask(base::Bind(&AppCacheResponseTest::ReadRange, - base::Unretained(this))); - PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF, - base::Unretained(this))); - PushNextTask(base::Bind(&AppCacheResponseTest::ReadAllAtOnce, - base::Unretained(this))); - PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks, - base::Unretained(this))); - PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks, - base::Unretained(this))); - - // Get them going. - ScheduleNextTask(); - } - - void WriteOutBlocks() { - writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0)); - written_response_id_ = writer_->response_id(); - for (int i = 0; i < kNumBlocks; ++i) { - PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock, - base::Unretained(this), kNumBlocks - i)); - } - ScheduleNextTask(); - } - - void WriteOneBlock(int block_number) { - scoped_refptr<IOBuffer> io_buffer( - new IOBuffer(kBlockSize)); - FillData(block_number, io_buffer->data(), kBlockSize); - WriteResponseBody(io_buffer, kBlockSize); - } - - void ReadInBlocks() { - writer_.reset(); - reader_.reset(service_->storage()->CreateResponseReader( - GURL(), 0, written_response_id_)); - for (int i = 0; i < kNumBlocks; ++i) { - PushNextTask(base::Bind(&AppCacheResponseTest::ReadOneBlock, - base::Unretained(this), kNumBlocks - i)); - } - ScheduleNextTask(); - } - - void ReadOneBlock(int block_number) { - PushNextTask(base::Bind(&AppCacheResponseTest::VerifyOneBlock, - base::Unretained(this), block_number)); - ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize); - } - - void VerifyOneBlock(int block_number) { - EXPECT_TRUE(CheckData(block_number, read_buffer_->data(), kBlockSize)); - ScheduleNextTask(); - } - - void ReadAllAtOnce() { - PushNextTask(base::Bind(&AppCacheResponseTest::VerifyAllAtOnce, - base::Unretained(this))); - reader_.reset(service_->storage()->CreateResponseReader( - GURL(), 0, written_response_id_)); - int big_size = kNumBlocks * kBlockSize; - ReadResponseBody(new IOBuffer(big_size), big_size); - } - - void VerifyAllAtOnce() { - char* p = read_buffer_->data(); - for (int i = 0; i < kNumBlocks; ++i, p += kBlockSize) - EXPECT_TRUE(CheckData(i + 1, p, kBlockSize)); - ScheduleNextTask(); - } - - void ReadPastEOF() { - EXPECT_FALSE(reader_->IsReadPending()); - read_buffer_ = new IOBuffer(kBlockSize); - expected_read_result_ = 0; - reader_->ReadData(read_buffer_.get(), - kBlockSize, - base::Bind(&AppCacheResponseTest::OnReadComplete, - base::Unretained(this))); - } - - void ReadRange() { - PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRange, - base::Unretained(this))); - reader_.reset(service_->storage()->CreateResponseReader( - GURL(), 0, written_response_id_)); - reader_->SetReadRange(kBlockSize, kBlockSize); - ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize); - } - - void VerifyRange() { - EXPECT_TRUE(CheckData(2, read_buffer_->data(), kBlockSize)); - ScheduleNextTask(); // ReadPastEOF is scheduled next - } - - void ReadRangePartiallyBeyondEOF() { - PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRangeBeyondEOF, - base::Unretained(this))); - reader_.reset(service_->storage()->CreateResponseReader( - GURL(), 0, written_response_id_)); - reader_->SetReadRange(kBlockSize, kNumBlocks * kBlockSize); - ReadResponseBody(new IOBuffer(kNumBlocks * kBlockSize), - kNumBlocks * kBlockSize); - expected_read_result_ = (kNumBlocks - 1) * kBlockSize; - } - - void VerifyRangeBeyondEOF() { - // Just verify the first 1k - VerifyRange(); - } - - void ReadRangeFullyBeyondEOF() { - reader_.reset(service_->storage()->CreateResponseReader( - GURL(), 0, written_response_id_)); - reader_->SetReadRange((kNumBlocks * kBlockSize) + 1, kBlockSize); - ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize); - expected_read_result_ = 0; - } - - // IOChaining ------------------------------------------- - void IOChaining() { - // 1. Write several blocks out initiating the subsequent write - // from within the completion callback of the previous write. - // 2. Read and verify several blocks in similarly chaining reads. - - // Push tasks in reverse order - PushNextTaskAsImmediate( - base::Bind(&AppCacheResponseTest::ReadInBlocksImmediately, - base::Unretained(this))); - PushNextTaskAsImmediate( - base::Bind(&AppCacheResponseTest::WriteOutBlocksImmediately, - base::Unretained(this))); - - // Get them going. - ScheduleNextTask(); - } - - void WriteOutBlocksImmediately() { - writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0)); - written_response_id_ = writer_->response_id(); - for (int i = 0; i < kNumBlocks; ++i) { - PushNextTaskAsImmediate( - base::Bind(&AppCacheResponseTest::WriteOneBlock, - base::Unretained(this), kNumBlocks - i)); - } - ScheduleNextTask(); - } - - void ReadInBlocksImmediately() { - writer_.reset(); - reader_.reset(service_->storage()->CreateResponseReader( - GURL(), 0, written_response_id_)); - for (int i = 0; i < kNumBlocks; ++i) { - PushNextTaskAsImmediate( - base::Bind(&AppCacheResponseTest::ReadOneBlockImmediately, - base::Unretained(this), - kNumBlocks - i)); - } - ScheduleNextTask(); - } - - void ReadOneBlockImmediately(int block_number) { - PushNextTaskAsImmediate(base::Bind(&AppCacheResponseTest::VerifyOneBlock, - base::Unretained(this), block_number)); - ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize); - } - - // DeleteWithinCallbacks ------------------------------------------- - void DeleteWithinCallbacks() { - // 1. Write out a few blocks normally, and upon - // completion of the last write, delete the writer. - // 2. Read in a few blocks normally, and upon completion - // of the last read, delete the reader. - - should_delete_reader_in_completion_callback_ = true; - reader_deletion_count_down_ = kNumBlocks; - should_delete_writer_in_completion_callback_ = true; - writer_deletion_count_down_ = kNumBlocks; - - PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks, - base::Unretained(this))); - PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks, - base::Unretained(this))); - ScheduleNextTask(); - } - - // DeleteWithIOPending ------------------------------------------- - void DeleteWithIOPending() { - // 1. Write a few blocks normally. - // 2. Start a write, delete with it pending. - // 3. Start a read, delete with it pending. - PushNextTask(base::Bind(&AppCacheResponseTest::ReadThenDelete, - base::Unretained(this))); - PushNextTask(base::Bind(&AppCacheResponseTest::WriteThenDelete, - base::Unretained(this))); - PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks, - base::Unretained(this))); - ScheduleNextTask(); - } - - void WriteThenDelete() { - write_callback_was_called_ = false; - WriteOneBlock(5); - EXPECT_TRUE(writer_->IsWritePending()); - writer_.reset(); - ScheduleNextTask(); - } - - void ReadThenDelete() { - read_callback_was_called_ = false; - reader_.reset(service_->storage()->CreateResponseReader( - GURL(), 0, written_response_id_)); - ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize); - EXPECT_TRUE(reader_->IsReadPending()); - reader_.reset(); - - // Wait a moment to verify no callbacks. - base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, base::Bind(&AppCacheResponseTest::VerifyNoCallbacks, - base::Unretained(this)), - base::TimeDelta::FromMilliseconds(10)); - } - - void VerifyNoCallbacks() { - EXPECT_TRUE(!write_callback_was_called_); - EXPECT_TRUE(!read_callback_was_called_); - TestFinished(); - } - - // Data members - - scoped_ptr<base::WaitableEvent> test_finished_event_; - scoped_ptr<MockStorageDelegate> storage_delegate_; - scoped_ptr<MockAppCacheService> service_; - std::stack<std::pair<base::Closure, bool> > task_stack_; - - scoped_ptr<AppCacheResponseReader> reader_; - scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_; - scoped_refptr<IOBuffer> read_buffer_; - int expected_read_result_; - bool should_delete_reader_in_completion_callback_; - int reader_deletion_count_down_; - bool read_callback_was_called_; - - int64 written_response_id_; - scoped_ptr<AppCacheResponseWriter> writer_; - scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_; - scoped_refptr<IOBuffer> write_buffer_; - int expected_write_result_; - bool should_delete_writer_in_completion_callback_; - int writer_deletion_count_down_; - bool write_callback_was_called_; - - static scoped_ptr<base::Thread> io_thread_; -}; - -// static -scoped_ptr<base::Thread> AppCacheResponseTest::io_thread_; - -TEST_F(AppCacheResponseTest, ReadNonExistentResponse) { - RunTestOnIOThread(&AppCacheResponseTest::ReadNonExistentResponse); -} - -TEST_F(AppCacheResponseTest, LoadResponseInfo_Miss) { - RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Miss); -} - -TEST_F(AppCacheResponseTest, LoadResponseInfo_Hit) { - RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Hit); -} - -TEST_F(AppCacheResponseTest, AmountWritten) { - RunTestOnIOThread(&AppCacheResponseTest::AmountWritten); -} - -TEST_F(AppCacheResponseTest, WriteThenVariouslyReadResponse) { - RunTestOnIOThread(&AppCacheResponseTest::WriteThenVariouslyReadResponse); -} - -TEST_F(AppCacheResponseTest, IOChaining) { - RunTestOnIOThread(&AppCacheResponseTest::IOChaining); -} - -TEST_F(AppCacheResponseTest, DeleteWithinCallbacks) { - RunTestOnIOThread(&AppCacheResponseTest::DeleteWithinCallbacks); -} - -TEST_F(AppCacheResponseTest, DeleteWithIOPending) { - RunTestOnIOThread(&AppCacheResponseTest::DeleteWithIOPending); -} - -} // namespace appcache diff --git a/webkit/browser/appcache/appcache_service.h b/webkit/browser/appcache/appcache_service.h index f81a409..4f9ae4b 100644 --- a/webkit/browser/appcache/appcache_service.h +++ b/webkit/browser/appcache/appcache_service.h @@ -30,6 +30,8 @@ class MessageLoopProxy; } namespace content { +FORWARD_DECLARE_TEST(AppCacheServiceTest, ScheduleReinitialize); +class AppCacheServiceTest; class AppCacheStorageImplTest; } @@ -199,9 +201,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheService { bool force_keep_session_state() const { return force_keep_session_state_; } protected: + friend class content::AppCacheServiceTest; friend class content::AppCacheStorageImplTest; - friend class AppCacheServiceTest; - FRIEND_TEST_ALL_PREFIXES(AppCacheServiceTest, ScheduleReinitialize); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheServiceTest, ScheduleReinitialize); class AsyncHelper; class CanHandleOfflineHelper; diff --git a/webkit/browser/appcache/appcache_service_unittest.cc b/webkit/browser/appcache/appcache_service_unittest.cc deleted file mode 100644 index 4ae6b83..0000000 --- a/webkit/browser/appcache/appcache_service_unittest.cc +++ /dev/null @@ -1,377 +0,0 @@ -// 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/bind.h" -#include "base/bind_helpers.h" -#include "base/pickle.h" -#include "base/run_loop.h" -#include "net/base/completion_callback.h" -#include "net/base/io_buffer.h" -#include "net/http/http_response_headers.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/browser/appcache/appcache_response.h" -#include "webkit/browser/appcache/appcache_service.h" -#include "webkit/browser/appcache/mock_appcache_storage.h" - - -namespace appcache { -namespace { - -const int64 kMockGroupId = 1; -const int64 kMockCacheId = 1; -const int64 kMockResponseId = 1; -const int64 kMissingCacheId = 5; -const int64 kMissingResponseId = 5; -const char kMockHeaders[] = - "HTTP/1.0 200 OK\0Content-Length: 5\0\0"; -const char kMockBody[] = "Hello"; -const int kMockBodySize = 5; - -class MockResponseReader : public AppCacheResponseReader { - public: - MockResponseReader(int64 response_id, - net::HttpResponseInfo* info, int info_size, - const char* data, int data_size) - : AppCacheResponseReader(response_id, 0, NULL), - info_(info), info_size_(info_size), - data_(data), data_size_(data_size) { - } - virtual void ReadInfo(HttpResponseInfoIOBuffer* info_buf, - const net::CompletionCallback& callback) OVERRIDE { - info_buffer_ = info_buf; - callback_ = callback; // Cleared on completion. - - int rv = info_.get() ? info_size_ : net::ERR_FAILED; - info_buffer_->http_info.reset(info_.release()); - info_buffer_->response_data_size = data_size_; - ScheduleUserCallback(rv); - } - virtual void ReadData(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) OVERRIDE { - buffer_ = buf; - buffer_len_ = buf_len; - callback_ = callback; // Cleared on completion. - - if (!data_) { - ScheduleUserCallback(net::ERR_CACHE_READ_FAILURE); - return; - } - DCHECK(buf_len >= data_size_); - memcpy(buf->data(), data_, data_size_); - ScheduleUserCallback(data_size_); - data_size_ = 0; - } - - private: - void ScheduleUserCallback(int result) { - base::MessageLoop::current()->PostTask(FROM_HERE, - base::Bind(&MockResponseReader::InvokeUserCompletionCallback, - weak_factory_.GetWeakPtr(), result)); - } - - scoped_ptr<net::HttpResponseInfo> info_; - int info_size_; - const char* data_; - int data_size_; -}; - -} // namespace - - -class AppCacheServiceTest : public testing::Test { - public: - AppCacheServiceTest() - : kOrigin("http://hello/"), - kManifestUrl(kOrigin.Resolve("manifest")), - service_(new AppCacheService(NULL)), - delete_result_(net::OK), delete_completion_count_(0), - deletion_callback_( - base::Bind(&AppCacheServiceTest::OnDeleteAppCachesComplete, - base::Unretained(this))) { - // Setup to use mock storage. - service_->storage_.reset(new MockAppCacheStorage(service_.get())); - } - - void OnDeleteAppCachesComplete(int result) { - delete_result_ = result; - ++delete_completion_count_; - } - - MockAppCacheStorage* mock_storage() { - return static_cast<MockAppCacheStorage*>(service_->storage()); - } - - void ResetStorage() { - service_->storage_.reset(new MockAppCacheStorage(service_.get())); - } - - bool IsGroupStored(const GURL& manifest_url) { - return mock_storage()->IsGroupForManifestStored(manifest_url); - } - - int CountPendingHelpers() { - return service_->pending_helpers_.size(); - } - - void SetupMockGroup() { - scoped_ptr<net::HttpResponseInfo> info(MakeMockResponseInfo()); - const int kMockInfoSize = GetResponseInfoSize(info.get()); - - // Create a mock group, cache, and entry and stuff them into mock storage. - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service_->storage(), kManifestUrl, kMockGroupId)); - scoped_refptr<AppCache> cache( - new AppCache(service_->storage(), kMockCacheId)); - cache->AddEntry( - kManifestUrl, - AppCacheEntry(AppCacheEntry::MANIFEST, kMockResponseId, - kMockInfoSize + kMockBodySize)); - cache->set_complete(true); - group->AddCache(cache.get()); - mock_storage()->AddStoredGroup(group.get()); - mock_storage()->AddStoredCache(cache.get()); - } - - void SetupMockReader( - bool valid_info, bool valid_data, bool valid_size) { - net::HttpResponseInfo* info = valid_info ? MakeMockResponseInfo() : NULL; - int info_size = info ? GetResponseInfoSize(info) : 0; - const char* data = valid_data ? kMockBody : NULL; - int data_size = valid_size ? kMockBodySize : 3; - mock_storage()->SimulateResponseReader( - new MockResponseReader(kMockResponseId, info, info_size, - data, data_size)); - } - - net::HttpResponseInfo* MakeMockResponseInfo() { - net::HttpResponseInfo* info = new net::HttpResponseInfo; - info->request_time = base::Time::Now(); - info->response_time = base::Time::Now(); - info->was_cached = false; - info->headers = new net::HttpResponseHeaders( - std::string(kMockHeaders, arraysize(kMockHeaders))); - return info; - } - - int GetResponseInfoSize(const net::HttpResponseInfo* info) { - Pickle pickle; - return PickleResponseInfo(&pickle, info); - } - - int PickleResponseInfo(Pickle* pickle, const net::HttpResponseInfo* info) { - const bool kSkipTransientHeaders = true; - const bool kTruncated = false; - info->Persist(pickle, kSkipTransientHeaders, kTruncated); - return pickle->size(); - } - - const GURL kOrigin; - const GURL kManifestUrl; - - scoped_ptr<AppCacheService> service_; - int delete_result_; - int delete_completion_count_; - net::CompletionCallback deletion_callback_; - - private: - base::MessageLoop message_loop_; -}; - -TEST_F(AppCacheServiceTest, DeleteAppCachesForOrigin) { - // Without giving mock storage simiulated info, should fail. - service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_); - EXPECT_EQ(0, delete_completion_count_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, delete_completion_count_); - EXPECT_EQ(net::ERR_FAILED, delete_result_); - delete_completion_count_ = 0; - - // Should succeed given an empty info collection. - mock_storage()->SimulateGetAllInfo(new AppCacheInfoCollection); - service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_); - EXPECT_EQ(0, delete_completion_count_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, delete_completion_count_); - EXPECT_EQ(net::OK, delete_result_); - delete_completion_count_ = 0; - - scoped_refptr<AppCacheInfoCollection> info(new AppCacheInfoCollection); - - // Should succeed given a non-empty info collection. - AppCacheInfo mock_manifest_1; - AppCacheInfo mock_manifest_2; - AppCacheInfo mock_manifest_3; - mock_manifest_1.manifest_url = kOrigin.Resolve("manifest1"); - mock_manifest_2.manifest_url = kOrigin.Resolve("manifest2"); - mock_manifest_3.manifest_url = kOrigin.Resolve("manifest3"); - AppCacheInfoVector info_vector; - info_vector.push_back(mock_manifest_1); - info_vector.push_back(mock_manifest_2); - info_vector.push_back(mock_manifest_3); - info->infos_by_origin[kOrigin] = info_vector; - mock_storage()->SimulateGetAllInfo(info.get()); - service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_); - EXPECT_EQ(0, delete_completion_count_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, delete_completion_count_); - EXPECT_EQ(net::OK, delete_result_); - delete_completion_count_ = 0; - - // Should fail if storage fails to delete. - info->infos_by_origin[kOrigin] = info_vector; - mock_storage()->SimulateGetAllInfo(info.get()); - mock_storage()->SimulateMakeGroupObsoleteFailure(); - service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_); - EXPECT_EQ(0, delete_completion_count_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, delete_completion_count_); - EXPECT_EQ(net::ERR_FAILED, delete_result_); - delete_completion_count_ = 0; - - // Should complete with abort error if the service is deleted - // prior to a delete completion. - service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_); - EXPECT_EQ(0, delete_completion_count_); - service_.reset(); // kill it - EXPECT_EQ(1, delete_completion_count_); - EXPECT_EQ(net::ERR_ABORTED, delete_result_); - delete_completion_count_ = 0; - - // Let any tasks lingering from the sudden deletion run and verify - // no other completion calls occur. - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, delete_completion_count_); -} - -TEST_F(AppCacheServiceTest, CheckAppCacheResponse) { - // Check a non-existing manifest. - EXPECT_FALSE(IsGroupStored(kManifestUrl)); - service_->CheckAppCacheResponse(kManifestUrl, 1, 1); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, CountPendingHelpers()); - EXPECT_FALSE(IsGroupStored(kManifestUrl)); - ResetStorage(); - - // Check a response that looks good. - // Nothing should be deleted. - SetupMockGroup(); - EXPECT_TRUE(IsGroupStored(kManifestUrl)); - SetupMockReader(true, true, true); - service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, CountPendingHelpers()); - EXPECT_TRUE(IsGroupStored(kManifestUrl)); - ResetStorage(); - - // Check a response for which there is no cache entry. - // The group should get deleted. - SetupMockGroup(); - service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, - kMissingResponseId); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, CountPendingHelpers()); - EXPECT_FALSE(IsGroupStored(kManifestUrl)); - ResetStorage(); - - // Check a response for which there is no manifest entry in a newer version - // of the cache. Nothing should get deleted in this case. - SetupMockGroup(); - service_->CheckAppCacheResponse(kManifestUrl, kMissingCacheId, - kMissingResponseId); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, CountPendingHelpers()); - EXPECT_TRUE(IsGroupStored(kManifestUrl)); - ResetStorage(); - - // Check a response with bad headers. - SetupMockGroup(); - service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId); - SetupMockReader(false, true, true); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, CountPendingHelpers()); - EXPECT_FALSE(IsGroupStored(kManifestUrl)); - ResetStorage(); - - // Check a response with bad data. - SetupMockGroup(); - service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId); - SetupMockReader(true, false, true); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, CountPendingHelpers()); - EXPECT_FALSE(IsGroupStored(kManifestUrl)); - ResetStorage(); - - // Check a response with truncated data. - SetupMockGroup(); - service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId); - SetupMockReader(true, true, false); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, CountPendingHelpers()); - EXPECT_FALSE(IsGroupStored(kManifestUrl)); - ResetStorage(); - - service_.reset(); // Clean up. - base::RunLoop().RunUntilIdle(); -} - -// Just tests the backoff scheduling function, not the actual reinit function. -TEST_F(AppCacheServiceTest, ScheduleReinitialize) { - const base::TimeDelta kNoDelay; - const base::TimeDelta kOneSecond(base::TimeDelta::FromSeconds(1)); - const base::TimeDelta k30Seconds(base::TimeDelta::FromSeconds(30)); - const base::TimeDelta kOneHour(base::TimeDelta::FromHours(1)); - - // Do things get initialized as expected? - scoped_ptr<AppCacheService> service(new AppCacheService(NULL)); - EXPECT_TRUE(service->last_reinit_time_.is_null()); - EXPECT_FALSE(service->reinit_timer_.IsRunning()); - EXPECT_EQ(kNoDelay, service->next_reinit_delay_); - - // Do we see artifacts of the timer pending and such? - service->ScheduleReinitialize(); - EXPECT_TRUE(service->reinit_timer_.IsRunning()); - EXPECT_EQ(kNoDelay, service->reinit_timer_.GetCurrentDelay()); - EXPECT_EQ(k30Seconds, service->next_reinit_delay_); - - // Nothing should change if already scheduled - service->ScheduleReinitialize(); - EXPECT_TRUE(service->reinit_timer_.IsRunning()); - EXPECT_EQ(kNoDelay, service->reinit_timer_.GetCurrentDelay()); - EXPECT_EQ(k30Seconds, service->next_reinit_delay_); - - // Does the delay increase as expected? - service->reinit_timer_.Stop(); - service->last_reinit_time_ = base::Time::Now() - kOneSecond; - service->ScheduleReinitialize(); - EXPECT_TRUE(service->reinit_timer_.IsRunning()); - EXPECT_EQ(k30Seconds, service->reinit_timer_.GetCurrentDelay()); - EXPECT_EQ(k30Seconds + k30Seconds, service->next_reinit_delay_); - - // Does the delay reset as expected? - service->reinit_timer_.Stop(); - service->last_reinit_time_ = base::Time::Now() - - base::TimeDelta::FromHours(2); - service->ScheduleReinitialize(); - EXPECT_TRUE(service->reinit_timer_.IsRunning()); - EXPECT_EQ(kNoDelay, service->reinit_timer_.GetCurrentDelay()); - EXPECT_EQ(k30Seconds, service->next_reinit_delay_); - - // Does the delay max out as expected? - service->reinit_timer_.Stop(); - service->last_reinit_time_ = base::Time::Now() - kOneSecond; - service->next_reinit_delay_ = kOneHour; - service->ScheduleReinitialize(); - EXPECT_TRUE(service->reinit_timer_.IsRunning()); - EXPECT_EQ(kOneHour, service->reinit_timer_.GetCurrentDelay()); - EXPECT_EQ(kOneHour, service->next_reinit_delay_); - - // Fine to delete while pending. - service.reset(NULL); -} - - - -} // namespace appcache diff --git a/webkit/browser/appcache/appcache_storage.h b/webkit/browser/appcache/appcache_storage.h index 8114461..caf68e2 100644 --- a/webkit/browser/appcache/appcache_storage.h +++ b/webkit/browser/appcache/appcache_storage.h @@ -22,6 +22,8 @@ class GURL; namespace content { FORWARD_DECLARE_TEST(AppCacheStorageTest, DelegateReferences); FORWARD_DECLARE_TEST(AppCacheStorageTest, UsageMap); +class AppCacheQuotaClientTest; +class AppCacheResponseTest; class AppCacheStorageTest; } @@ -200,8 +202,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheStorage { AppCacheService* service() { return service_; } protected: - friend class AppCacheQuotaClientTest; - friend class AppCacheResponseTest; + friend class content::AppCacheQuotaClientTest; + friend class content::AppCacheResponseTest; friend class content::AppCacheStorageTest; // Helper to call a collection of delegates. diff --git a/webkit/browser/appcache/appcache_unittest.cc b/webkit/browser/appcache/appcache_unittest.cc deleted file mode 100644 index a7b79a6..0000000 --- a/webkit/browser/appcache/appcache_unittest.cc +++ /dev/null @@ -1,695 +0,0 @@ -// 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 "testing/gtest/include/gtest/gtest.h" -#include "webkit/browser/appcache/appcache.h" -#include "webkit/browser/appcache/appcache_host.h" -#include "webkit/browser/appcache/mock_appcache_service.h" - -namespace appcache { - -namespace { - -class MockAppCacheFrontend : public AppCacheFrontend { - public: - virtual void OnCacheSelected(int host_id, const AppCacheInfo& info) OVERRIDE { - } - virtual void OnStatusChanged(const std::vector<int>& host_ids, - Status status) OVERRIDE {} - virtual void OnEventRaised(const std::vector<int>& host_ids, - EventID event_id) OVERRIDE {} - virtual void OnProgressEventRaised( - const std::vector<int>& host_ids, - const GURL& url, - int num_total, int num_complete) OVERRIDE {} - virtual void OnErrorEventRaised(const std::vector<int>& host_ids, - const ErrorDetails& details) OVERRIDE {} - virtual void OnLogMessage(int host_id, LogLevel log_level, - const std::string& message) OVERRIDE {} - virtual void OnContentBlocked( - int host_id, const GURL& manifest_url) OVERRIDE {} -}; - -} // namespace - -class AppCacheTest : public testing::Test { -}; - -TEST(AppCacheTest, CleanupUnusedCache) { - MockAppCacheService service; - MockAppCacheFrontend frontend; - scoped_refptr<AppCache> cache(new AppCache(service.storage(), 111)); - cache->set_complete(true); - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), GURL("http://blah/manifest"), 111)); - group->AddCache(cache.get()); - - AppCacheHost host1(1, &frontend, &service); - AppCacheHost host2(2, &frontend, &service); - - host1.AssociateCompleteCache(cache.get()); - host2.AssociateCompleteCache(cache.get()); - - host1.AssociateNoCache(GURL()); - host2.AssociateNoCache(GURL()); -} - -TEST(AppCacheTest, AddModifyRemoveEntry) { - MockAppCacheService service; - scoped_refptr<AppCache> cache(new AppCache(service.storage(), 111)); - - EXPECT_TRUE(cache->entries().empty()); - EXPECT_EQ(0L, cache->cache_size()); - - const GURL kFooUrl("http://foo.com"); - const int64 kFooResponseId = 1; - const int64 kFooSize = 100; - AppCacheEntry entry1(AppCacheEntry::MASTER, kFooResponseId, kFooSize); - cache->AddEntry(kFooUrl, entry1); - EXPECT_EQ(entry1.types(), cache->GetEntry(kFooUrl)->types()); - EXPECT_EQ(1UL, cache->entries().size()); - EXPECT_EQ(kFooSize, cache->cache_size()); - - const GURL kBarUrl("http://bar.com"); - const int64 kBarResponseId = 2; - const int64 kBarSize = 200; - AppCacheEntry entry2(AppCacheEntry::FALLBACK, kBarResponseId, kBarSize); - EXPECT_TRUE(cache->AddOrModifyEntry(kBarUrl, entry2)); - EXPECT_EQ(entry2.types(), cache->GetEntry(kBarUrl)->types()); - EXPECT_EQ(2UL, cache->entries().size()); - EXPECT_EQ(kFooSize + kBarSize, cache->cache_size()); - - // Expected to return false when an existing entry is modified. - AppCacheEntry entry3(AppCacheEntry::EXPLICIT); - EXPECT_FALSE(cache->AddOrModifyEntry(kFooUrl, entry3)); - EXPECT_EQ((AppCacheEntry::MASTER | AppCacheEntry::EXPLICIT), - cache->GetEntry(kFooUrl)->types()); - // Only the type should be modified. - EXPECT_EQ(kFooResponseId, cache->GetEntry(kFooUrl)->response_id()); - EXPECT_EQ(kFooSize, cache->GetEntry(kFooUrl)->response_size()); - EXPECT_EQ(kFooSize + kBarSize, cache->cache_size()); - - EXPECT_EQ(entry2.types(), cache->GetEntry(kBarUrl)->types()); // unchanged - - cache->RemoveEntry(kBarUrl); - EXPECT_EQ(kFooSize, cache->cache_size()); - cache->RemoveEntry(kFooUrl); - EXPECT_EQ(0L, cache->cache_size()); - EXPECT_TRUE(cache->entries().empty()); -} - -TEST(AppCacheTest, InitializeWithManifest) { - MockAppCacheService service; - - scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234)); - EXPECT_TRUE(cache->fallback_namespaces_.empty()); - EXPECT_TRUE(cache->online_whitelist_namespaces_.empty()); - EXPECT_FALSE(cache->online_whitelist_all_); - - Manifest manifest; - manifest.explicit_urls.insert("http://one.com"); - manifest.explicit_urls.insert("http://two.com"); - manifest.fallback_namespaces.push_back( - Namespace(FALLBACK_NAMESPACE, GURL("http://fb1.com"), - GURL("http://fbone.com"), true)); - manifest.online_whitelist_namespaces.push_back( - Namespace(NETWORK_NAMESPACE, GURL("http://w1.com"), GURL(), false)); - manifest.online_whitelist_namespaces.push_back( - Namespace(NETWORK_NAMESPACE, GURL("http://w2.com"), GURL(), false)); - manifest.online_whitelist_all = true; - - cache->InitializeWithManifest(&manifest); - const std::vector<Namespace>& fallbacks = - cache->fallback_namespaces_; - size_t expected = 1; - EXPECT_EQ(expected, fallbacks.size()); - EXPECT_EQ(GURL("http://fb1.com"), fallbacks[0].namespace_url); - EXPECT_EQ(GURL("http://fbone.com"), fallbacks[0].target_url); - EXPECT_TRUE(fallbacks[0].is_pattern); - const NamespaceVector& whitelist = cache->online_whitelist_namespaces_; - expected = 2; - EXPECT_EQ(expected, whitelist.size()); - EXPECT_EQ(GURL("http://w1.com"), whitelist[0].namespace_url); - EXPECT_EQ(GURL("http://w2.com"), whitelist[1].namespace_url); - EXPECT_TRUE(cache->online_whitelist_all_); - - // Ensure collections in manifest were taken over by the cache rather than - // copied. - EXPECT_TRUE(manifest.fallback_namespaces.empty()); - EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); -} - -TEST(AppCacheTest, FindResponseForRequest) { - MockAppCacheService service; - - const GURL kOnlineNamespaceUrl("http://blah/online_namespace"); - const GURL kFallbackEntryUrl1("http://blah/fallback_entry1"); - const GURL kFallbackNamespaceUrl1("http://blah/fallback_namespace/"); - const GURL kFallbackEntryUrl2("http://blah/fallback_entry2"); - const GURL kFallbackNamespaceUrl2("http://blah/fallback_namespace/longer"); - const GURL kManifestUrl("http://blah/manifest"); - const GURL kForeignExplicitEntryUrl("http://blah/foreign"); - const GURL kInOnlineNamespaceUrl( - "http://blah/online_namespace/network"); - const GURL kExplicitInOnlineNamespaceUrl( - "http://blah/online_namespace/explicit"); - const GURL kFallbackTestUrl1("http://blah/fallback_namespace/1"); - const GURL kFallbackTestUrl2("http://blah/fallback_namespace/longer2"); - const GURL kInterceptNamespace("http://blah/intercept_namespace/"); - const GURL kInterceptNamespaceWithinFallback( - "http://blah/fallback_namespace/intercept_namespace/"); - const GURL kInterceptNamespaceEntry("http://blah/intercept_entry"); - const GURL kOnlineNamespaceWithinOtherNamespaces( - "http://blah/fallback_namespace/intercept_namespace/1/online"); - - const int64 kFallbackResponseId1 = 1; - const int64 kFallbackResponseId2 = 2; - const int64 kManifestResponseId = 3; - const int64 kForeignExplicitResponseId = 4; - const int64 kExplicitInOnlineNamespaceResponseId = 5; - const int64 kInterceptResponseId = 6; - - Manifest manifest; - manifest.online_whitelist_namespaces.push_back( - Namespace(NETWORK_NAMESPACE, kOnlineNamespaceUrl, - GURL(), false)); - manifest.online_whitelist_namespaces.push_back( - Namespace(NETWORK_NAMESPACE, kOnlineNamespaceWithinOtherNamespaces, - GURL(), false)); - manifest.fallback_namespaces.push_back( - Namespace(FALLBACK_NAMESPACE, kFallbackNamespaceUrl1, - kFallbackEntryUrl1, false)); - manifest.fallback_namespaces.push_back( - Namespace(FALLBACK_NAMESPACE, kFallbackNamespaceUrl2, - kFallbackEntryUrl2, false)); - manifest.intercept_namespaces.push_back( - Namespace(INTERCEPT_NAMESPACE, kInterceptNamespace, - kInterceptNamespaceEntry, false)); - manifest.intercept_namespaces.push_back( - Namespace(INTERCEPT_NAMESPACE, kInterceptNamespaceWithinFallback, - kInterceptNamespaceEntry, false)); - - // Create a cache with some namespaces and entries. - scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234)); - cache->InitializeWithManifest(&manifest); - cache->AddEntry( - kFallbackEntryUrl1, - AppCacheEntry(AppCacheEntry::FALLBACK, kFallbackResponseId1)); - cache->AddEntry( - kFallbackEntryUrl2, - AppCacheEntry(AppCacheEntry::FALLBACK, kFallbackResponseId2)); - cache->AddEntry( - kManifestUrl, - AppCacheEntry(AppCacheEntry::MANIFEST, kManifestResponseId)); - cache->AddEntry( - kForeignExplicitEntryUrl, - AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN, - kForeignExplicitResponseId)); - cache->AddEntry( - kExplicitInOnlineNamespaceUrl, - AppCacheEntry(AppCacheEntry::EXPLICIT, - kExplicitInOnlineNamespaceResponseId)); - cache->AddEntry( - kInterceptNamespaceEntry, - AppCacheEntry(AppCacheEntry::INTERCEPT, kInterceptResponseId)); - cache->set_complete(true); - - // See that we get expected results from FindResponseForRequest - - bool found = false; - AppCacheEntry entry; - AppCacheEntry fallback_entry; - GURL intercept_namespace; - GURL fallback_namespace; - bool network_namespace = false; - - found = cache->FindResponseForRequest(GURL("http://blah/miss"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_FALSE(found); - - found = cache->FindResponseForRequest(kForeignExplicitEntryUrl, - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_EQ(kForeignExplicitResponseId, entry.response_id()); - EXPECT_FALSE(fallback_entry.has_response_id()); - EXPECT_FALSE(network_namespace); - - entry = AppCacheEntry(); // reset - - found = cache->FindResponseForRequest(kManifestUrl, - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_EQ(kManifestResponseId, entry.response_id()); - EXPECT_FALSE(fallback_entry.has_response_id()); - EXPECT_FALSE(network_namespace); - - entry = AppCacheEntry(); // reset - - found = cache->FindResponseForRequest(kInOnlineNamespaceUrl, - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_FALSE(entry.has_response_id()); - EXPECT_FALSE(fallback_entry.has_response_id()); - EXPECT_TRUE(network_namespace); - - network_namespace = false; // reset - - found = cache->FindResponseForRequest(kExplicitInOnlineNamespaceUrl, - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_EQ(kExplicitInOnlineNamespaceResponseId, entry.response_id()); - EXPECT_FALSE(fallback_entry.has_response_id()); - EXPECT_FALSE(network_namespace); - - entry = AppCacheEntry(); // reset - - found = cache->FindResponseForRequest(kFallbackTestUrl1, - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_FALSE(entry.has_response_id()); - EXPECT_EQ(kFallbackResponseId1, fallback_entry.response_id()); - EXPECT_EQ(kFallbackEntryUrl1, - cache->GetFallbackEntryUrl(fallback_namespace)); - EXPECT_FALSE(network_namespace); - - fallback_entry = AppCacheEntry(); // reset - - found = cache->FindResponseForRequest(kFallbackTestUrl2, - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_FALSE(entry.has_response_id()); - EXPECT_EQ(kFallbackResponseId2, fallback_entry.response_id()); - EXPECT_EQ(kFallbackEntryUrl2, - cache->GetFallbackEntryUrl(fallback_namespace)); - EXPECT_FALSE(network_namespace); - - fallback_entry = AppCacheEntry(); // reset - - found = cache->FindResponseForRequest(kOnlineNamespaceWithinOtherNamespaces, - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_FALSE(entry.has_response_id()); - EXPECT_FALSE(fallback_entry.has_response_id()); - EXPECT_TRUE(network_namespace); - - fallback_entry = AppCacheEntry(); // reset - - found = cache->FindResponseForRequest( - kOnlineNamespaceWithinOtherNamespaces.Resolve("online_resource"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_FALSE(entry.has_response_id()); - EXPECT_FALSE(fallback_entry.has_response_id()); - EXPECT_TRUE(network_namespace); - - fallback_namespace = GURL(); - - found = cache->FindResponseForRequest( - kInterceptNamespace.Resolve("intercept_me"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_EQ(kInterceptResponseId, entry.response_id()); - EXPECT_EQ(kInterceptNamespaceEntry, - cache->GetInterceptEntryUrl(intercept_namespace)); - EXPECT_FALSE(fallback_entry.has_response_id()); - EXPECT_TRUE(fallback_namespace.is_empty()); - EXPECT_FALSE(network_namespace); - - entry = AppCacheEntry(); // reset - - found = cache->FindResponseForRequest( - kInterceptNamespaceWithinFallback.Resolve("intercept_me"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_EQ(kInterceptResponseId, entry.response_id()); - EXPECT_EQ(kInterceptNamespaceEntry, - cache->GetInterceptEntryUrl(intercept_namespace)); - EXPECT_FALSE(fallback_entry.has_response_id()); - EXPECT_TRUE(fallback_namespace.is_empty()); - EXPECT_FALSE(network_namespace); -} - -TEST(AppCacheTest, FindInterceptPatternResponseForRequest) { - MockAppCacheService service; - - // Setup an appcache with an intercept namespace that uses pattern matching. - const GURL kInterceptNamespaceBase("http://blah/intercept_namespace/"); - const GURL kInterceptPatternNamespace( - kInterceptNamespaceBase.Resolve("*.hit*")); - const GURL kInterceptNamespaceEntry("http://blah/intercept_resource"); - const int64 kInterceptResponseId = 1; - Manifest manifest; - manifest.intercept_namespaces.push_back( - Namespace(INTERCEPT_NAMESPACE, kInterceptPatternNamespace, - kInterceptNamespaceEntry, true)); - scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234)); - cache->InitializeWithManifest(&manifest); - cache->AddEntry( - kInterceptNamespaceEntry, - AppCacheEntry(AppCacheEntry::INTERCEPT, kInterceptResponseId)); - cache->set_complete(true); - - // See that the pattern match works. - bool found = false; - AppCacheEntry entry; - AppCacheEntry fallback_entry; - GURL intercept_namespace; - GURL fallback_namespace; - bool network_namespace = false; - - found = cache->FindResponseForRequest( - GURL("http://blah/miss"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_FALSE(found); - - found = cache->FindResponseForRequest( - GURL("http://blah/intercept_namespace/another_miss"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_FALSE(found); - - found = cache->FindResponseForRequest( - GURL("http://blah/intercept_namespace/path.hit"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_EQ(kInterceptResponseId, entry.response_id()); - EXPECT_EQ(kInterceptNamespaceEntry, - cache->GetInterceptEntryUrl(intercept_namespace)); - EXPECT_FALSE(fallback_entry.has_response_id()); - EXPECT_TRUE(fallback_namespace.is_empty()); - EXPECT_FALSE(network_namespace); - - entry = AppCacheEntry(); // reset - - found = cache->FindResponseForRequest( - GURL("http://blah/intercept_namespace/longer/path.hit?arg=ok"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_EQ(kInterceptResponseId, entry.response_id()); - EXPECT_EQ(kInterceptNamespaceEntry, - cache->GetInterceptEntryUrl(intercept_namespace)); - EXPECT_FALSE(fallback_entry.has_response_id()); - EXPECT_TRUE(fallback_namespace.is_empty()); - EXPECT_FALSE(network_namespace); -} - -TEST(AppCacheTest, FindFallbackPatternResponseForRequest) { - MockAppCacheService service; - - // Setup an appcache with a fallback namespace that uses pattern matching. - const GURL kFallbackNamespaceBase("http://blah/fallback_namespace/"); - const GURL kFallbackPatternNamespace( - kFallbackNamespaceBase.Resolve("*.hit*")); - const GURL kFallbackNamespaceEntry("http://blah/fallback_resource"); - const int64 kFallbackResponseId = 1; - Manifest manifest; - manifest.fallback_namespaces.push_back( - Namespace(FALLBACK_NAMESPACE, kFallbackPatternNamespace, - kFallbackNamespaceEntry, true)); - scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234)); - cache->InitializeWithManifest(&manifest); - cache->AddEntry( - kFallbackNamespaceEntry, - AppCacheEntry(AppCacheEntry::FALLBACK, kFallbackResponseId)); - cache->set_complete(true); - - // See that the pattern match works. - bool found = false; - AppCacheEntry entry; - AppCacheEntry fallback_entry; - GURL intercept_namespace; - GURL fallback_namespace; - bool network_namespace = false; - - found = cache->FindResponseForRequest( - GURL("http://blah/miss"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_FALSE(found); - - found = cache->FindResponseForRequest( - GURL("http://blah/fallback_namespace/another_miss"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_FALSE(found); - - found = cache->FindResponseForRequest( - GURL("http://blah/fallback_namespace/path.hit"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_FALSE(entry.has_response_id()); - EXPECT_EQ(kFallbackResponseId, fallback_entry.response_id()); - EXPECT_EQ(kFallbackNamespaceEntry, - cache->GetFallbackEntryUrl(fallback_namespace)); - EXPECT_FALSE(network_namespace); - - fallback_entry = AppCacheEntry(); - fallback_namespace = GURL(); - - found = cache->FindResponseForRequest( - GURL("http://blah/fallback_namespace/longer/path.hit?arg=ok"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_FALSE(entry.has_response_id()); - EXPECT_EQ(kFallbackResponseId, fallback_entry.response_id()); - EXPECT_EQ(kFallbackNamespaceEntry, - cache->GetFallbackEntryUrl(fallback_namespace)); - EXPECT_TRUE(intercept_namespace.is_empty()); - EXPECT_FALSE(network_namespace); -} - - -TEST(AppCacheTest, FindNetworkNamespacePatternResponseForRequest) { - MockAppCacheService service; - - // Setup an appcache with a network namespace that uses pattern matching. - const GURL kNetworkNamespaceBase("http://blah/network_namespace/"); - const GURL kNetworkPatternNamespace( - kNetworkNamespaceBase.Resolve("*.hit*")); - Manifest manifest; - manifest.online_whitelist_namespaces.push_back( - Namespace(NETWORK_NAMESPACE, kNetworkPatternNamespace, - GURL(), true)); - manifest.online_whitelist_all = false; - scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234)); - cache->InitializeWithManifest(&manifest); - cache->set_complete(true); - - // See that the pattern match works. - bool found = false; - AppCacheEntry entry; - AppCacheEntry fallback_entry; - GURL intercept_namespace; - GURL fallback_namespace; - bool network_namespace = false; - - found = cache->FindResponseForRequest( - GURL("http://blah/miss"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_FALSE(found); - - found = cache->FindResponseForRequest( - GURL("http://blah/network_namespace/path.hit"), - &entry, &intercept_namespace, - &fallback_entry, &fallback_namespace, - &network_namespace); - EXPECT_TRUE(found); - EXPECT_TRUE(network_namespace); - EXPECT_FALSE(entry.has_response_id()); - EXPECT_FALSE(fallback_entry.has_response_id()); -} - -TEST(AppCacheTest, ToFromDatabaseRecords) { - // Setup a cache with some entries. - const int64 kCacheId = 1234; - const int64 kGroupId = 4321; - const GURL kManifestUrl("http://foo.com/manifest"); - const GURL kInterceptUrl("http://foo.com/intercept.html"); - const GURL kFallbackUrl("http://foo.com/fallback.html"); - const GURL kWhitelistUrl("http://foo.com/whitelist*"); - const std::string kData( - "CACHE MANIFEST\r" - "CHROMIUM-INTERCEPT:\r" - "/intercept return /intercept.html\r" - "FALLBACK:\r" - "/ /fallback.html\r" - "NETWORK:\r" - "/whitelist* isPattern\r" - "*\r"); - MockAppCacheService service; - scoped_refptr<AppCacheGroup> group = - new AppCacheGroup(service.storage(), kManifestUrl, kGroupId); - scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId)); - Manifest manifest; - EXPECT_TRUE( - ParseManifest(kManifestUrl, kData.c_str(), kData.length(), manifest)); - cache->InitializeWithManifest(&manifest); - EXPECT_EQ(NETWORK_NAMESPACE, cache->online_whitelist_namespaces_[0].type); - EXPECT_TRUE(cache->online_whitelist_namespaces_[0].is_pattern); - EXPECT_EQ(kWhitelistUrl, - cache->online_whitelist_namespaces_[0].namespace_url); - cache->AddEntry( - kManifestUrl, - AppCacheEntry(AppCacheEntry::MANIFEST, 1, 1)); - cache->AddEntry( - kInterceptUrl, - AppCacheEntry(AppCacheEntry::INTERCEPT, 3, 3)); - cache->AddEntry( - kFallbackUrl, - AppCacheEntry(AppCacheEntry::FALLBACK, 2, 2)); - - // Get it to produce database records and verify them. - AppCacheDatabase::CacheRecord cache_record; - std::vector<AppCacheDatabase::EntryRecord> entries; - std::vector<AppCacheDatabase::NamespaceRecord> intercepts; - std::vector<AppCacheDatabase::NamespaceRecord> fallbacks; - std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists; - cache->ToDatabaseRecords(group.get(), - &cache_record, - &entries, - &intercepts, - &fallbacks, - &whitelists); - EXPECT_EQ(kCacheId, cache_record.cache_id); - EXPECT_EQ(kGroupId, cache_record.group_id); - EXPECT_TRUE(cache_record.online_wildcard); - EXPECT_EQ(1 + 2 + 3, cache_record.cache_size); - EXPECT_EQ(3u, entries.size()); - EXPECT_EQ(1u, intercepts.size()); - EXPECT_EQ(1u, fallbacks.size()); - EXPECT_EQ(1u, whitelists.size()); - cache = NULL; - - // Create a new AppCache and populate it with those records and verify. - cache = new AppCache(service.storage(), kCacheId); - cache->InitializeWithDatabaseRecords( - cache_record, entries, intercepts, - fallbacks, whitelists); - EXPECT_TRUE(cache->online_whitelist_all_); - EXPECT_EQ(3u, cache->entries().size()); - EXPECT_TRUE(cache->GetEntry(kManifestUrl)); - EXPECT_TRUE(cache->GetEntry(kInterceptUrl)); - EXPECT_TRUE(cache->GetEntry(kFallbackUrl)); - EXPECT_EQ(kInterceptUrl, - cache->GetInterceptEntryUrl(GURL("http://foo.com/intercept"))); - EXPECT_EQ(kFallbackUrl, - cache->GetFallbackEntryUrl(GURL("http://foo.com/"))); - EXPECT_EQ(1 + 2 + 3, cache->cache_size()); - EXPECT_EQ(NETWORK_NAMESPACE, cache->online_whitelist_namespaces_[0].type); - EXPECT_TRUE(cache->online_whitelist_namespaces_[0].is_pattern); - EXPECT_EQ(kWhitelistUrl, - cache->online_whitelist_namespaces_[0].namespace_url); -} - -TEST(AppCacheTest, IsNamespaceMatch) { - Namespace prefix; - prefix.namespace_url = GURL("http://foo.com/prefix"); - prefix.is_pattern = false; - EXPECT_TRUE(prefix.IsMatch( - GURL("http://foo.com/prefix_and_anothing_goes"))); - EXPECT_FALSE(prefix.IsMatch( - GURL("http://foo.com/nope"))); - - Namespace bar_no_star; - bar_no_star.namespace_url = GURL("http://foo.com/bar"); - bar_no_star.is_pattern = true; - EXPECT_TRUE(bar_no_star.IsMatch( - GURL("http://foo.com/bar"))); - EXPECT_FALSE(bar_no_star.IsMatch( - GURL("http://foo.com/bar/nope"))); - - Namespace bar_star; - bar_star.namespace_url = GURL("http://foo.com/bar/*"); - bar_star.is_pattern = true; - EXPECT_TRUE(bar_star.IsMatch( - GURL("http://foo.com/bar/"))); - EXPECT_TRUE(bar_star.IsMatch( - GURL("http://foo.com/bar/should_match"))); - EXPECT_FALSE(bar_star.IsMatch( - GURL("http://foo.com/not_bar/should_not_match"))); - - Namespace star_bar_star; - star_bar_star.namespace_url = GURL("http://foo.com/*/bar/*"); - star_bar_star.is_pattern = true; - EXPECT_TRUE(star_bar_star.IsMatch( - GURL("http://foo.com/any/bar/should_match"))); - EXPECT_TRUE(star_bar_star.IsMatch( - GURL("http://foo.com/any/bar/"))); - EXPECT_FALSE(star_bar_star.IsMatch( - GURL("http://foo.com/any/not_bar/no_match"))); - - Namespace query_star_edit; - query_star_edit.namespace_url = GURL("http://foo.com/query?id=*&verb=edit*"); - query_star_edit.is_pattern = true; - EXPECT_TRUE(query_star_edit.IsMatch( - GURL("http://foo.com/query?id=1234&verb=edit&option=blue"))); - EXPECT_TRUE(query_star_edit.IsMatch( - GURL("http://foo.com/query?id=12345&option=blue&verb=edit"))); - EXPECT_FALSE(query_star_edit.IsMatch( - GURL("http://foo.com/query?id=12345&option=blue&verb=print"))); - EXPECT_TRUE(query_star_edit.IsMatch( - GURL("http://foo.com/query?id=123&verb=print&verb=edit"))); - - Namespace star_greediness; - star_greediness.namespace_url = GURL("http://foo.com/*/b"); - star_greediness.is_pattern = true; - EXPECT_TRUE(star_greediness.IsMatch( - GURL("http://foo.com/a/b"))); - EXPECT_TRUE(star_greediness.IsMatch( - GURL("http://foo.com/a/wxy/z/b"))); - EXPECT_TRUE(star_greediness.IsMatch( - GURL("http://foo.com/a/b/b"))); - EXPECT_TRUE(star_greediness.IsMatch( - GURL("http://foo.com/b/b"))); - EXPECT_TRUE(star_greediness.IsMatch( - GURL("http://foo.com/a/b/b/b/b/b"))); - EXPECT_TRUE(star_greediness.IsMatch( - GURL("http://foo.com/a/b/b/b/a/b"))); - EXPECT_TRUE(star_greediness.IsMatch( - GURL("http://foo.com/a/b/01234567890abcdef/b"))); - EXPECT_TRUE(star_greediness.IsMatch( - GURL("http://foo.com/a/b/01234567890abcdef/b01234567890abcdef/b"))); - EXPECT_TRUE(star_greediness.IsMatch( - GURL("http://foo.com/a/b/01234567890abcdef_eat_some_more_characters_" - "/and_even_more_for_the_heck_of_it/01234567890abcdef/b"))); -} - -} // namespace appacache diff --git a/webkit/browser/appcache/appcache_update_job.h b/webkit/browser/appcache/appcache_update_job.h index 09e8669..86740b7f 100644 --- a/webkit/browser/appcache/appcache_update_job.h +++ b/webkit/browser/appcache/appcache_update_job.h @@ -26,6 +26,12 @@ #include "webkit/browser/webkit_storage_browser_export.h" #include "webkit/common/appcache/appcache_interfaces.h" +namespace content { +FORWARD_DECLARE_TEST(AppCacheGroupTest, QueueUpdate); +class AppCacheGroupTest; +class AppCacheUpdateJobTest; +} + namespace appcache { class HostNotifier; @@ -51,7 +57,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheUpdateJob void StartUpdate(AppCacheHost* host, const GURL& new_master_resource); private: - friend class AppCacheUpdateJobTest; + friend class content::AppCacheGroupTest; + friend class content::AppCacheUpdateJobTest; class URLFetcher; // Master entries have multiple hosts, for example, the same page is opened @@ -333,7 +340,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheUpdateJob AppCacheStorage* storage_; - FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, QueueUpdate); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, QueueUpdate); DISALLOW_COPY_AND_ASSIGN(AppCacheUpdateJob); }; diff --git a/webkit/browser/appcache/appcache_update_job_unittest.cc b/webkit/browser/appcache/appcache_update_job_unittest.cc deleted file mode 100644 index c7c9e41..0000000 --- a/webkit/browser/appcache/appcache_update_job_unittest.cc +++ /dev/null @@ -1,3693 +0,0 @@ -// 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 "base/bind.h" -#include "base/bind_helpers.h" -#include "base/stl_util.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "net/base/net_errors.h" -#include "net/http/http_response_headers.h" -#include "net/url_request/url_request_error_job.h" -#include "net/url_request/url_request_job_factory_impl.h" -#include "net/url_request/url_request_test_job.h" -#include "net/url_request/url_request_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/browser/appcache/appcache_group.h" -#include "webkit/browser/appcache/appcache_host.h" -#include "webkit/browser/appcache/appcache_response.h" -#include "webkit/browser/appcache/appcache_update_job.h" -#include "webkit/browser/appcache/mock_appcache_service.h" - -namespace appcache { -class AppCacheUpdateJobTest; - -namespace { - -const char kManifest1Contents[] = - "CACHE MANIFEST\n" - "explicit1\n" - "FALLBACK:\n" - "fallback1 fallback1a\n" - "NETWORK:\n" - "*\n"; - -// There are a handful of http accessible resources that we need to conduct -// these tests. Instead of running a seperate server to host these resources, -// we mock them up. -class MockHttpServer { - public: - static GURL GetMockUrl(const std::string& path) { - return GURL("http://mockhost/" + path); - } - - static GURL GetMockHttpsUrl(const std::string& path) { - return GURL("https://mockhost/" + path); - } - - static GURL GetMockCrossOriginHttpsUrl(const std::string& path) { - return GURL("https://cross_origin_host/" + path); - } - - static net::URLRequestJob* JobFactory( - net::URLRequest* request, net::NetworkDelegate* network_delegate) { - if (request->url().host() != "mockhost" && - request->url().host() != "cross_origin_host") - return new net::URLRequestErrorJob(request, network_delegate, -100); - - std::string headers, body; - GetMockResponse(request->url().path(), &headers, &body); - return new net::URLRequestTestJob( - request, network_delegate, headers, body, true); - } - - private: - static void GetMockResponse(const std::string& path, - std::string* headers, - std::string* body) { - const char ok_headers[] = - "HTTP/1.1 200 OK\0" - "\0"; - const char error_headers[] = - "HTTP/1.1 500 BOO HOO\0" - "\0"; - const char manifest_headers[] = - "HTTP/1.1 200 OK\0" - "Content-type: text/cache-manifest\0" - "\0"; - const char not_modified_headers[] = - "HTTP/1.1 304 NOT MODIFIED\0" - "\0"; - const char gone_headers[] = - "HTTP/1.1 410 GONE\0" - "\0"; - const char not_found_headers[] = - "HTTP/1.1 404 NOT FOUND\0" - "\0"; - const char no_store_headers[] = - "HTTP/1.1 200 OK\0" - "Cache-Control: no-store\0" - "\0"; - - if (path == "/files/missing-mime-manifest") { - (*headers) = std::string(ok_headers, arraysize(ok_headers)); - (*body) = "CACHE MANIFEST\n"; - } else if (path == "/files/bad-manifest") { - (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); - (*body) = "BAD CACHE MANIFEST"; - } else if (path == "/files/empty1") { - (*headers) = std::string(ok_headers, arraysize(ok_headers)); - (*body) = ""; - } else if (path == "/files/empty-file-manifest") { - (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); - (*body) = "CACHE MANIFEST\n" - "empty1\n"; - } else if (path == "/files/empty-manifest") { - (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); - (*body) = "CACHE MANIFEST\n"; - } else if (path == "/files/explicit1") { - (*headers) = std::string(ok_headers, arraysize(ok_headers)); - (*body) = "explicit1"; - } else if (path == "/files/explicit2") { - (*headers) = std::string(ok_headers, arraysize(ok_headers)); - (*body) = "explicit2"; - } else if (path == "/files/fallback1a") { - (*headers) = std::string(ok_headers, arraysize(ok_headers)); - (*body) = "fallback1a"; - } else if (path == "/files/intercept1a") { - (*headers) = std::string(ok_headers, arraysize(ok_headers)); - (*body) = "intercept1a"; - } else if (path == "/files/gone") { - (*headers) = std::string(gone_headers, arraysize(gone_headers)); - (*body) = ""; - } else if (path == "/files/manifest1") { - (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); - (*body) = kManifest1Contents; - } else if (path == "/files/manifest1-with-notmodified") { - (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); - (*body) = kManifest1Contents; - (*body).append("CACHE:\n" - "notmodified\n"); - } else if (path == "/files/manifest-fb-404") { - (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); - (*body) = "CACHE MANIFEST\n" - "explicit1\n" - "FALLBACK:\n" - "fallback1 fallback1a\n" - "fallback404 fallback-404\n" - "NETWORK:\n" - "online1\n"; - } else if (path == "/files/manifest-merged-types") { - (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); - (*body) = "CACHE MANIFEST\n" - "explicit1\n" - "# manifest is also an explicit entry\n" - "manifest-merged-types\n" - "FALLBACK:\n" - "# fallback is also explicit entry\n" - "fallback1 explicit1\n" - "NETWORK:\n" - "online1\n"; - } else if (path == "/files/manifest-with-404") { - (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); - (*body) = "CACHE MANIFEST\n" - "explicit-404\n" - "explicit1\n" - "explicit2\n" - "explicit3\n" - "FALLBACK:\n" - "fallback1 fallback1a\n" - "NETWORK:\n" - "online1\n"; - } else if (path == "/files/manifest-with-intercept") { - (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); - (*body) = "CACHE MANIFEST\n" - "CHROMIUM-INTERCEPT:\n" - "intercept1 return intercept1a\n"; - } else if (path == "/files/notmodified") { - (*headers) = std::string(not_modified_headers, - arraysize(not_modified_headers)); - (*body) = ""; - } else if (path == "/files/servererror") { - (*headers) = std::string(error_headers, - arraysize(error_headers)); - (*body) = "error"; - } else if (path == "/files/valid_cross_origin_https_manifest") { - (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); - (*body) = "CACHE MANIFEST\n" - "https://cross_origin_host/files/explicit1\n"; - } else if (path == "/files/invalid_cross_origin_https_manifest") { - (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); - (*body) = "CACHE MANIFEST\n" - "https://cross_origin_host/files/no-store-headers\n"; - } else if (path == "/files/no-store-headers") { - (*headers) = std::string(no_store_headers, arraysize(no_store_headers)); - (*body) = "no-store"; - } else { - (*headers) = std::string(not_found_headers, - arraysize(not_found_headers)); - (*body) = ""; - } - } -}; - -class MockHttpServerJobFactory - : public net::URLRequestJobFactory::ProtocolHandler { - public: - virtual net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const OVERRIDE { - return MockHttpServer::JobFactory(request, network_delegate); - } -}; - -inline bool operator==(const Namespace& lhs, const Namespace& rhs) { - return lhs.type == rhs.type && - lhs.namespace_url == rhs.namespace_url && - lhs.target_url == rhs.target_url; -} - -} // namespace - -class MockFrontend : public AppCacheFrontend { - public: - MockFrontend() - : ignore_progress_events_(false), verify_progress_events_(false), - last_progress_total_(-1), last_progress_complete_(-1), - start_update_trigger_(CHECKING_EVENT), update_(NULL) { - } - - virtual void OnCacheSelected( - int host_id, const appcache::AppCacheInfo& info) OVERRIDE { - } - - virtual void OnStatusChanged(const std::vector<int>& host_ids, - Status status) OVERRIDE { - } - - virtual void OnEventRaised(const std::vector<int>& host_ids, - EventID event_id) OVERRIDE { - raised_events_.push_back(RaisedEvent(host_ids, event_id)); - - // Trigger additional updates if requested. - if (event_id == start_update_trigger_ && update_) { - for (std::vector<AppCacheHost*>::iterator it = update_hosts_.begin(); - it != update_hosts_.end(); ++it) { - AppCacheHost* host = *it; - update_->StartUpdate(host, - (host ? host->pending_master_entry_url() : GURL())); - } - update_hosts_.clear(); // only trigger once - } - } - - virtual void OnErrorEventRaised(const std::vector<int>& host_ids, - const appcache::ErrorDetails& details) - OVERRIDE { - error_message_ = details.message; - OnEventRaised(host_ids, ERROR_EVENT); - } - - virtual void OnProgressEventRaised(const std::vector<int>& host_ids, - const GURL& url, - int num_total, - int num_complete) OVERRIDE { - if (!ignore_progress_events_) - OnEventRaised(host_ids, PROGRESS_EVENT); - - if (verify_progress_events_) { - EXPECT_GE(num_total, num_complete); - EXPECT_GE(num_complete, 0); - - if (last_progress_total_ == -1) { - // Should start at zero. - EXPECT_EQ(0, num_complete); - } else { - // Total should be stable and complete should bump up by one at a time. - EXPECT_EQ(last_progress_total_, num_total); - EXPECT_EQ(last_progress_complete_ + 1, num_complete); - } - - // Url should be valid for all except the 'final' event. - if (num_total == num_complete) - EXPECT_TRUE(url.is_empty()); - else - EXPECT_TRUE(url.is_valid()); - - last_progress_total_ = num_total; - last_progress_complete_ = num_complete; - } - } - - 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 { - } - - void AddExpectedEvent(const std::vector<int>& host_ids, EventID event_id) { - DCHECK(!ignore_progress_events_ || event_id != PROGRESS_EVENT); - expected_events_.push_back(RaisedEvent(host_ids, event_id)); - } - - void SetIgnoreProgressEvents(bool ignore) { - // Some tests involve joining new hosts to an already running update job - // or intentionally failing. The timing and sequencing of the progress - // events generated by an update job are dependent on the behavior of - // an external HTTP server. For jobs that do not run fully till completion, - // due to either joining late or early exit, we skip monitoring the - // progress events to avoid flakiness. - ignore_progress_events_ = ignore; - } - - void SetVerifyProgressEvents(bool verify) { - verify_progress_events_ = verify; - } - - void TriggerAdditionalUpdates(EventID trigger_event, - AppCacheUpdateJob* update) { - start_update_trigger_ = trigger_event; - update_ = update; - } - - void AdditionalUpdateHost(AppCacheHost* host) { - update_hosts_.push_back(host); - } - - typedef std::vector<int> HostIds; - typedef std::pair<HostIds, EventID> RaisedEvent; - typedef std::vector<RaisedEvent> RaisedEvents; - RaisedEvents raised_events_; - std::string error_message_; - - // Set the expected events if verification needs to happen asynchronously. - RaisedEvents expected_events_; - std::string expected_error_message_; - - bool ignore_progress_events_; - - bool verify_progress_events_; - int last_progress_total_; - int last_progress_complete_; - - // Add ability for frontend to add master entries to an inprogress update. - EventID start_update_trigger_; - AppCacheUpdateJob* update_; - std::vector<AppCacheHost*> update_hosts_; -}; - -// Helper factories to simulate redirected URL responses for tests. -class RedirectFactory : public net::URLRequestJobFactory::ProtocolHandler { - public: - virtual net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const OVERRIDE { - return new net::URLRequestTestJob( - request, - network_delegate, - net::URLRequestTestJob::test_redirect_headers(), - net::URLRequestTestJob::test_data_1(), - true); - } -}; - -// Helper class to simulate a URL that returns retry or success. -class RetryRequestTestJob : public net::URLRequestTestJob { - public: - enum RetryHeader { - NO_RETRY_AFTER, - NONZERO_RETRY_AFTER, - RETRY_AFTER_0, - }; - - static const GURL kRetryUrl; - - // Call this at the start of each retry test. - static void Initialize(int num_retry_responses, RetryHeader header, - int expected_requests) { - num_requests_ = 0; - num_retries_ = num_retry_responses; - retry_after_ = header; - expected_requests_ = expected_requests; - } - - // Verifies results at end of test and resets counters. - static void Verify() { - EXPECT_EQ(expected_requests_, num_requests_); - num_requests_ = 0; - expected_requests_ = 0; - } - - static net::URLRequestJob* RetryFactory( - net::URLRequest* request, net::NetworkDelegate* network_delegate) { - ++num_requests_; - if (num_retries_ > 0 && request->original_url() == kRetryUrl) { - --num_retries_; - return new RetryRequestTestJob( - request, network_delegate, RetryRequestTestJob::retry_headers(), 503); - } else { - return new RetryRequestTestJob( - request, - network_delegate, - RetryRequestTestJob::manifest_headers(), 200); - } - } - - virtual int GetResponseCode() const OVERRIDE { return response_code_; } - - private: - virtual ~RetryRequestTestJob() {} - - static std::string retry_headers() { - const char no_retry_after[] = - "HTTP/1.1 503 BOO HOO\0" - "\0"; - const char nonzero[] = - "HTTP/1.1 503 BOO HOO\0" - "Retry-After: 60\0" - "\0"; - const char retry_after_0[] = - "HTTP/1.1 503 BOO HOO\0" - "Retry-After: 0\0" - "\0"; - - switch (retry_after_) { - case NO_RETRY_AFTER: - return std::string(no_retry_after, arraysize(no_retry_after)); - case NONZERO_RETRY_AFTER: - return std::string(nonzero, arraysize(nonzero)); - case RETRY_AFTER_0: - default: - return std::string(retry_after_0, arraysize(retry_after_0)); - } - } - - static std::string manifest_headers() { - const char headers[] = - "HTTP/1.1 200 OK\0" - "Content-type: text/cache-manifest\0" - "\0"; - return std::string(headers, arraysize(headers)); - } - - static std::string data() { - return std::string("CACHE MANIFEST\r" - "http://retry\r"); // must be same as kRetryUrl - } - - RetryRequestTestJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& headers, - int response_code) - : net::URLRequestTestJob( - request, network_delegate, headers, data(), true), - response_code_(response_code) { - } - - int response_code_; - - static int num_requests_; - static int num_retries_; - static RetryHeader retry_after_; - static int expected_requests_; -}; - -class RetryRequestTestJobFactory - : public net::URLRequestJobFactory::ProtocolHandler { - public: - virtual net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const OVERRIDE { - return RetryRequestTestJob::RetryFactory(request, network_delegate); - } -}; - -// static -const GURL RetryRequestTestJob::kRetryUrl("http://retry"); -int RetryRequestTestJob::num_requests_ = 0; -int RetryRequestTestJob::num_retries_; -RetryRequestTestJob::RetryHeader RetryRequestTestJob::retry_after_; -int RetryRequestTestJob::expected_requests_ = 0; - -// Helper class to check for certain HTTP headers. -class HttpHeadersRequestTestJob : public net::URLRequestTestJob { - public: - // Call this at the start of each HTTP header-related test. - static void Initialize(const std::string& expect_if_modified_since, - const std::string& expect_if_none_match) { - expect_if_modified_since_ = expect_if_modified_since; - expect_if_none_match_ = expect_if_none_match; - } - - // Verifies results at end of test and resets class. - static void Verify() { - if (!expect_if_modified_since_.empty()) - EXPECT_TRUE(saw_if_modified_since_); - if (!expect_if_none_match_.empty()) - EXPECT_TRUE(saw_if_none_match_); - - // Reset. - expect_if_modified_since_.clear(); - saw_if_modified_since_ = false; - expect_if_none_match_.clear(); - saw_if_none_match_ = false; - already_checked_ = false; - } - - static net::URLRequestJob* IfModifiedSinceFactory( - net::URLRequest* request, net::NetworkDelegate* network_delegate) { - if (!already_checked_) { - already_checked_ = true; // only check once for a test - const net::HttpRequestHeaders& extra_headers = - request->extra_request_headers(); - std::string header_value; - saw_if_modified_since_ = - extra_headers.GetHeader( - net::HttpRequestHeaders::kIfModifiedSince, &header_value) && - header_value == expect_if_modified_since_; - - saw_if_none_match_ = - extra_headers.GetHeader( - net::HttpRequestHeaders::kIfNoneMatch, &header_value) && - header_value == expect_if_none_match_; - } - return MockHttpServer::JobFactory(request, network_delegate); - } - - protected: - virtual ~HttpHeadersRequestTestJob() {} - - private: - static std::string expect_if_modified_since_; - static bool saw_if_modified_since_; - static std::string expect_if_none_match_; - static bool saw_if_none_match_; - static bool already_checked_; -}; - -// static -std::string HttpHeadersRequestTestJob::expect_if_modified_since_; -bool HttpHeadersRequestTestJob::saw_if_modified_since_ = false; -std::string HttpHeadersRequestTestJob::expect_if_none_match_; -bool HttpHeadersRequestTestJob::saw_if_none_match_ = false; -bool HttpHeadersRequestTestJob::already_checked_ = false; - -class IfModifiedSinceJobFactory - : public net::URLRequestJobFactory::ProtocolHandler { - public: - virtual net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const OVERRIDE { - return HttpHeadersRequestTestJob::IfModifiedSinceFactory( - request, network_delegate); - } -}; - -class IOThread : public base::Thread { - public: - explicit IOThread(const char* name) - : base::Thread(name) { - } - - virtual ~IOThread() { - Stop(); - } - - net::URLRequestContext* request_context() { - return request_context_.get(); - } - - void SetNewJobFactory(net::URLRequestJobFactory* job_factory) { - DCHECK(job_factory); - job_factory_.reset(job_factory); - request_context_->set_job_factory(job_factory_.get()); - } - - virtual void Init() OVERRIDE { - scoped_ptr<net::URLRequestJobFactoryImpl> factory( - new net::URLRequestJobFactoryImpl()); - factory->SetProtocolHandler("http", new MockHttpServerJobFactory); - factory->SetProtocolHandler("https", new MockHttpServerJobFactory); - job_factory_ = factory.Pass(); - request_context_.reset(new net::TestURLRequestContext()); - request_context_->set_job_factory(job_factory_.get()); - } - - virtual void CleanUp() OVERRIDE { - request_context_.reset(); - job_factory_.reset(); - } - - private: - scoped_ptr<net::URLRequestJobFactory> job_factory_; - scoped_ptr<net::URLRequestContext> request_context_; -}; - -class AppCacheUpdateJobTest : public testing::Test, - public AppCacheGroup::UpdateObserver { - public: - AppCacheUpdateJobTest() - : do_checks_after_update_finished_(false), - expect_group_obsolete_(false), - expect_group_has_cache_(false), - expect_group_is_being_deleted_(false), - expect_old_cache_(NULL), - expect_newest_cache_(NULL), - expect_non_null_update_time_(false), - tested_manifest_(NONE), - tested_manifest_path_override_(NULL) { - io_thread_.reset(new IOThread("AppCacheUpdateJob IO test thread")); - base::Thread::Options options(base::MessageLoop::TYPE_IO, 0); - io_thread_->StartWithOptions(options); - } - - // 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, base::Bind(method, base::Unretained(this))); - - // Wait until task is done before exiting the test. - event_->Wait(); - } - - void StartCacheAttemptTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"), - service_->storage()->NewGroupId()); - - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend mock_frontend; - AppCacheHost host(1, &mock_frontend, service_.get()); - - update->StartUpdate(&host, GURL()); - - // 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_TRUE(base::MessageLoopForIO::IsCurrent()); - - { - MakeService(); - group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"), - service_->storage()->NewGroupId()); - - // Give the group some existing caches. - AppCache* cache1 = MakeCacheForGroup(1, 111); - AppCache* cache2 = MakeCacheForGroup(2, 222); - - // 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.AssociateCompleteCache(cache1); - - AppCacheHost host2(2, &mock_frontend2, service_.get()); - host2.AssociateCompleteCache(cache2); - - AppCacheHost host3(3, &mock_frontend1, service_.get()); - host3.AssociateCompleteCache(cache1); - - AppCacheHost host4(4, &mock_frontend3, service_.get()); - - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - update->StartUpdate(&host4, GURL()); - - // 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_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - update->manifest_fetcher_->request()->CancelWithError(-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_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(1, 111); - MockFrontend* frontend1 = MakeMockFrontend(); - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - AppCacheHost* host2 = MakeHost(2, frontend2); - host1->AssociateCompleteCache(cache); - host2->AssociateCompleteCache(cache); - - update->StartUpdate(NULL, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - update->manifest_fetcher_->request()->CancelWithError(-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_TRUE(base::MessageLoopForIO::IsCurrent()); - - net::URLRequestJobFactoryImpl* new_factory( - new net::URLRequestJobFactoryImpl); - new_factory->SetProtocolHandler("http", new RedirectFactory); - io_thread_->SetNewJobFactory(new_factory); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), GURL("http://testme"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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 ManifestMissingMimeTypeTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), - MockHttpServer::GetMockUrl("files/missing-mime-manifest"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 33); - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->AssociateCompleteCache(cache); - - frontend->SetVerifyProgressEvents(true); - - update->StartUpdate(NULL, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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; - tested_manifest_path_override_ = "files/missing-mime-manifest"; - MockFrontend::HostIds ids(1, host->host_id()); - frontend->AddExpectedEvent(ids, CHECKING_EVENT); - frontend->AddExpectedEvent(ids, DOWNLOADING_EVENT); - frontend->AddExpectedEvent(ids, PROGRESS_EVENT); // final - frontend->AddExpectedEvent(ids, UPDATE_READY_EVENT); - - WaitForUpdateToFinish(); - } - - void ManifestNotFoundTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/nosuchfile"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(1, 111); - MockFrontend* frontend1 = MakeMockFrontend(); - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - AppCacheHost* host2 = MakeHost(2, frontend2); - host1->AssociateCompleteCache(cache); - host2->AssociateCompleteCache(cache); - - update->StartUpdate(NULL, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/gone"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - // 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 CacheAttemptNotModifiedTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(1, 111); - MockFrontend* frontend1 = MakeMockFrontend(); - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - AppCacheHost* host2 = MakeHost(2, frontend2); - host1->AssociateCompleteCache(cache); - host2->AssociateCompleteCache(cache); - - update->StartUpdate(NULL, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - // Create response writer to get a response id. - response_writer_.reset( - service_->storage()->CreateResponseWriter(group_->manifest_url(), - group_->group_id())); - - AppCache* cache = MakeCacheForGroup(1, response_writer_->response_id()); - MockFrontend* frontend1 = MakeMockFrontend(); - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - AppCacheHost* host2 = MakeHost(2, frontend2); - host1->AssociateCompleteCache(cache); - host2->AssociateCompleteCache(cache); - - // 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); - - // Seed storage with expected manifest data. - const std::string seed_data(kManifest1Contents); - scoped_refptr<net::StringIOBuffer> io_buffer( - new net::StringIOBuffer(seed_data)); - response_writer_->WriteData( - io_buffer.get(), - seed_data.length(), - base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData, - base::Unretained(this))); - - // Start update after data write completes asynchronously. - } - - // See http://code.google.com/p/chromium/issues/detail?id=95101 - void Bug95101Test() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/empty-manifest"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - // Create a malformed cache with a missing manifest entry. - GURL wrong_manifest_url = - MockHttpServer::GetMockUrl("files/missing-mime-manifest"); - AppCache* cache = MakeCacheForGroup(1, wrong_manifest_url, 111); - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->AssociateCompleteCache(cache); - - update->StartUpdate(NULL, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - // Set up checks for when update job finishes. - do_checks_after_update_finished_ = true; - expect_group_is_being_deleted_ = true; - expect_group_has_cache_ = true; - expect_newest_cache_ = cache; // newest cache unaffected by update - MockFrontend::HostIds id(1, host->host_id()); - frontend->AddExpectedEvent(id, CHECKING_EVENT); - frontend->AddExpectedEvent(id, ERROR_EVENT); - frontend->expected_error_message_ = - "Manifest entry not found in existing cache"; - WaitForUpdateToFinish(); - } - - void StartUpdateAfterSeedingStorageData(int result) { - ASSERT_GT(result, 0); - response_writer_.reset(); - - AppCacheUpdateJob* update = group_->update_job_; - update->StartUpdate(NULL, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - WaitForUpdateToFinish(); - } - - void BasicCacheAttemptSuccessTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - GURL manifest_url = MockHttpServer::GetMockUrl("files/manifest1"); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), manifest_url, - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - - // 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 DownloadInterceptEntriesTest() { - // Ensures we download intercept entries too. - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - GURL manifest_url = - MockHttpServer::GetMockUrl("files/manifest-with-intercept"); - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), manifest_url, - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - - // 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_ = MANIFEST_WITH_INTERCEPT; - frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()), - CHECKING_EVENT); - - WaitForUpdateToFinish(); - } - - void BasicUpgradeSuccessTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - // Create a response writer to get a response id. - response_writer_.reset( - service_->storage()->CreateResponseWriter(group_->manifest_url(), - group_->group_id())); - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), - response_writer_->response_id()); - MockFrontend* frontend1 = MakeMockFrontend(); - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - AppCacheHost* host2 = MakeHost(2, frontend2); - host1->AssociateCompleteCache(cache); - host2->AssociateCompleteCache(cache); - frontend1->SetVerifyProgressEvents(true); - frontend2->SetVerifyProgressEvents(true); - - // 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, PROGRESS_EVENT); // final - 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); // final - frontend2->AddExpectedEvent(ids2, UPDATE_READY_EVENT); - - // Seed storage with expected manifest data different from manifest1. - const std::string seed_data("different"); - scoped_refptr<net::StringIOBuffer> io_buffer( - new net::StringIOBuffer(seed_data)); - response_writer_->WriteData( - io_buffer.get(), - seed_data.length(), - base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData, - base::Unretained(this))); - - // Start update after data write completes asynchronously. - } - - void UpgradeLoadFromNewestCacheTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42); - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->AssociateCompleteCache(cache); - - // Give the newest cache an entry that is in storage. - response_writer_.reset( - service_->storage()->CreateResponseWriter(group_->manifest_url(), - group_->group_id())); - cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"), - AppCacheEntry(AppCacheEntry::EXPLICIT, - response_writer_->response_id())); - - // 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; - expect_response_ids_.insert( - std::map<GURL, int64>::value_type( - MockHttpServer::GetMockUrl("files/explicit1"), - response_writer_->response_id())); - tested_manifest_ = MANIFEST1; - MockFrontend::HostIds ids(1, host->host_id()); - frontend->AddExpectedEvent(ids, CHECKING_EVENT); - frontend->AddExpectedEvent(ids, DOWNLOADING_EVENT); - frontend->AddExpectedEvent(ids, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids, PROGRESS_EVENT); // final - frontend->AddExpectedEvent(ids, UPDATE_READY_EVENT); - - // Seed storage with expected http response info for entry. Allow reuse. - const char data[] = - "HTTP/1.1 200 OK\0" - "Cache-Control: max-age=8675309\0" - "\0"; - net::HttpResponseHeaders* headers = - new net::HttpResponseHeaders(std::string(data, arraysize(data))); - net::HttpResponseInfo* response_info = new net::HttpResponseInfo(); - response_info->request_time = base::Time::Now(); - response_info->response_time = base::Time::Now(); - response_info->headers = headers; // adds ref to headers - scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( - new HttpResponseInfoIOBuffer(response_info)); // adds ref to info - response_writer_->WriteInfo( - io_buffer.get(), - base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData, - base::Unretained(this))); - - // Start update after data write completes asynchronously. - } - - void UpgradeNoLoadFromNewestCacheTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42); - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->AssociateCompleteCache(cache); - - // Give the newest cache an entry that is in storage. - response_writer_.reset( - service_->storage()->CreateResponseWriter(group_->manifest_url(), - group_->group_id())); - cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"), - AppCacheEntry(AppCacheEntry::EXPLICIT, - response_writer_->response_id())); - - // 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 ids(1, host->host_id()); - frontend->AddExpectedEvent(ids, CHECKING_EVENT); - frontend->AddExpectedEvent(ids, DOWNLOADING_EVENT); - frontend->AddExpectedEvent(ids, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids, PROGRESS_EVENT); // final - frontend->AddExpectedEvent(ids, UPDATE_READY_EVENT); - - // Seed storage with expected http response info for entry. Do NOT - // allow reuse by setting an expires header in the past. - const char data[] = - "HTTP/1.1 200 OK\0" - "Expires: Thu, 01 Dec 1994 16:00:00 GMT\0" - "\0"; - net::HttpResponseHeaders* headers = - new net::HttpResponseHeaders(std::string(data, arraysize(data))); - net::HttpResponseInfo* response_info = new net::HttpResponseInfo(); - response_info->request_time = base::Time::Now(); - response_info->response_time = base::Time::Now(); - response_info->headers = headers; // adds ref to headers - scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( - new HttpResponseInfoIOBuffer(response_info)); // adds ref to info - response_writer_->WriteInfo( - io_buffer.get(), - base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData, - base::Unretained(this))); - - // Start update after data write completes asynchronously. - } - - void UpgradeLoadFromNewestCacheVaryHeaderTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42); - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->AssociateCompleteCache(cache); - - // Give the newest cache an entry that is in storage. - response_writer_.reset( - service_->storage()->CreateResponseWriter(group_->manifest_url(), - group_->group_id())); - cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"), - AppCacheEntry(AppCacheEntry::EXPLICIT, - response_writer_->response_id())); - - // 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 ids(1, host->host_id()); - frontend->AddExpectedEvent(ids, CHECKING_EVENT); - frontend->AddExpectedEvent(ids, DOWNLOADING_EVENT); - frontend->AddExpectedEvent(ids, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids, PROGRESS_EVENT); // final - frontend->AddExpectedEvent(ids, UPDATE_READY_EVENT); - - // Seed storage with expected http response info for entry: a vary header. - const char data[] = - "HTTP/1.1 200 OK\0" - "Cache-Control: max-age=8675309\0" - "Vary: blah\0" - "\0"; - net::HttpResponseHeaders* headers = - new net::HttpResponseHeaders(std::string(data, arraysize(data))); - net::HttpResponseInfo* response_info = new net::HttpResponseInfo(); - response_info->request_time = base::Time::Now(); - response_info->response_time = base::Time::Now(); - response_info->headers = headers; // adds ref to headers - scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( - new HttpResponseInfoIOBuffer(response_info)); // adds ref to info - response_writer_->WriteInfo( - io_buffer.get(), - base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData, - base::Unretained(this))); - - // Start update after data write completes asynchronously. - } - - void UpgradeSuccessMergedTypesTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), - MockHttpServer::GetMockUrl("files/manifest-merged-types"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42); - MockFrontend* frontend1 = MakeMockFrontend(); - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - AppCacheHost* host2 = MakeHost(2, frontend2); - host1->AssociateCompleteCache(cache); - host2->AssociateCompleteCache(cache); - - // Give the newest cache a master entry that is also one of the explicit - // entries in the manifest. - cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"), - AppCacheEntry(AppCacheEntry::MASTER, 111)); - - update->StartUpdate(NULL, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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 - frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // manifest - frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // final - 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); // final - frontend2->AddExpectedEvent(ids2, UPDATE_READY_EVENT); - - WaitForUpdateToFinish(); - } - - void CacheAttemptFailUrlFetchTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), - MockHttpServer::GetMockUrl("files/manifest-with-404"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), - MockHttpServer::GetMockUrl("files/manifest-fb-404"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 99); - MockFrontend* frontend1 = MakeMockFrontend(); - MockFrontend* frontend2 = MakeMockFrontend(); - frontend1->SetIgnoreProgressEvents(true); - frontend2->SetIgnoreProgressEvents(true); - AppCacheHost* host1 = MakeHost(1, frontend1); - AppCacheHost* host2 = MakeHost(2, frontend2); - host1->AssociateCompleteCache(cache); - host2->AssociateCompleteCache(cache); - - update->StartUpdate(NULL, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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, ERROR_EVENT); - MockFrontend::HostIds ids2(1, host2->host_id()); - frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); - frontend2->AddExpectedEvent(ids2, DOWNLOADING_EVENT); - frontend2->AddExpectedEvent(ids2, ERROR_EVENT); - - WaitForUpdateToFinish(); - } - - void UpgradeFailMasterUrlFetchTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - tested_manifest_path_override_ = "files/manifest1-with-notmodified"; - - MakeService(); - const GURL kManifestUrl = - MockHttpServer::GetMockUrl(tested_manifest_path_override_); - group_ = new AppCacheGroup( - service_->storage(), kManifestUrl, - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 25); - MockFrontend* frontend1 = MakeMockFrontend(); - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - AppCacheHost* host2 = MakeHost(2, frontend2); - host1->AssociateCompleteCache(cache); - host2->AssociateCompleteCache(cache); - - // Give the newest cache some existing entries; one will fail with a 404. - cache->AddEntry( - MockHttpServer::GetMockUrl("files/notfound"), - AppCacheEntry(AppCacheEntry::MASTER, 222)); - cache->AddEntry( - MockHttpServer::GetMockUrl("files/explicit2"), - AppCacheEntry(AppCacheEntry::MASTER | AppCacheEntry::FOREIGN, 333)); - cache->AddEntry( - MockHttpServer::GetMockUrl("files/servererror"), - AppCacheEntry(AppCacheEntry::MASTER, 444)); - cache->AddEntry( - MockHttpServer::GetMockUrl("files/notmodified"), - AppCacheEntry(AppCacheEntry::EXPLICIT, 555)); - - // Seed the response_info working set with canned data for - // files/servererror and for files/notmodified to test that the - // existing entries for those resource are reused by the update job. - const char kData[] = - "HTTP/1.1 200 OK\0" - "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0" - "\0"; - const std::string kRawHeaders(kData, arraysize(kData)); - MakeAppCacheResponseInfo(kManifestUrl, 444, kRawHeaders); - MakeAppCacheResponseInfo(kManifestUrl, 555, kRawHeaders); - - update->StartUpdate(NULL, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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( - MockHttpServer::GetMockUrl("files/explicit2"), - AppCacheEntry(AppCacheEntry::MASTER))); // foreign flag is dropped - expect_extra_entries_.insert(AppCache::EntryMap::value_type( - MockHttpServer::GetMockUrl("files/servererror"), - AppCacheEntry(AppCacheEntry::MASTER))); - expect_extra_entries_.insert(AppCache::EntryMap::value_type( - MockHttpServer::GetMockUrl("files/notmodified"), - AppCacheEntry(AppCacheEntry::EXPLICIT))); - expect_response_ids_.insert(std::map<GURL, int64>::value_type( - MockHttpServer::GetMockUrl("files/servererror"), 444)); // copied - expect_response_ids_.insert(std::map<GURL, int64>::value_type( - MockHttpServer::GetMockUrl("files/notmodified"), 555)); // copied - 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 - frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // explicit2 - frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // servererror - frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // notmodified - frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // final - 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); // explicit1 - frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); // fallback1a - frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); // notfound - frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); // explicit2 - frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); // servererror - frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); // notmodified - frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); // final - frontend2->AddExpectedEvent(ids2, UPDATE_READY_EVENT); - - WaitForUpdateToFinish(); - } - - void EmptyManifestTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/empty-manifest"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 33); - MockFrontend* frontend1 = MakeMockFrontend(); - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - AppCacheHost* host2 = MakeHost(2, frontend2); - host1->AssociateCompleteCache(cache); - host2->AssociateCompleteCache(cache); - - frontend1->SetVerifyProgressEvents(true); - - update->StartUpdate(NULL, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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, PROGRESS_EVENT); // final - 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); // final - frontend2->AddExpectedEvent(ids2, UPDATE_READY_EVENT); - - WaitForUpdateToFinish(); - } - - void EmptyFileTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), - MockHttpServer::GetMockUrl("files/empty-file-manifest"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 22); - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->AssociateCompleteCache(cache); - frontend->SetVerifyProgressEvents(true); - - update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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_ = EMPTY_FILE_MANIFEST; - MockFrontend::HostIds ids1(1, host->host_id()); - frontend->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend->AddExpectedEvent(ids1, DOWNLOADING_EVENT); - frontend->AddExpectedEvent(ids1, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids1, PROGRESS_EVENT); // final - frontend->AddExpectedEvent(ids1, UPDATE_READY_EVENT); - - WaitForUpdateToFinish(); - } - - void RetryRequestTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - // Set some large number of times to return retry. - // Expect 1 manifest fetch and 3 retries. - RetryRequestTestJob::Initialize(5, RetryRequestTestJob::RETRY_AFTER_0, 4); - net::URLRequestJobFactoryImpl* new_factory( - new net::URLRequestJobFactoryImpl); - new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory); - io_thread_->SetNewJobFactory(new_factory); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), - RetryRequestTestJob::kRetryUrl, - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - // 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 RetryNoRetryAfterTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - // Set some large number of times to return retry. - // Expect 1 manifest fetch and 0 retries. - RetryRequestTestJob::Initialize(5, RetryRequestTestJob::NO_RETRY_AFTER, 1); - net::URLRequestJobFactoryImpl* new_factory( - new net::URLRequestJobFactoryImpl); - new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory); - io_thread_->SetNewJobFactory(new_factory); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), - RetryRequestTestJob::kRetryUrl, - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - // 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 RetryNonzeroRetryAfterTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - // Set some large number of times to return retry. - // Expect 1 request and 0 retry attempts. - RetryRequestTestJob::Initialize( - 5, RetryRequestTestJob::NONZERO_RETRY_AFTER, 1); - net::URLRequestJobFactoryImpl* new_factory( - new net::URLRequestJobFactoryImpl); - new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory); - io_thread_->SetNewJobFactory(new_factory); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), - RetryRequestTestJob::kRetryUrl, - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - // 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 RetrySuccessTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - // Set 2 as the retry limit (does not exceed the max). - // Expect 1 manifest fetch, 2 retries, 1 url fetch, 1 manifest refetch. - RetryRequestTestJob::Initialize(2, RetryRequestTestJob::RETRY_AFTER_0, 5); - net::URLRequestJobFactoryImpl* new_factory( - new net::URLRequestJobFactoryImpl); - new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory); - io_thread_->SetNewJobFactory(new_factory); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), - RetryRequestTestJob::kRetryUrl, - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - // Set up checks for when update job finishes. - do_checks_after_update_finished_ = true; - expect_group_obsolete_ = false; - expect_group_has_cache_ = true; - frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()), - CHECKING_EVENT); - - WaitForUpdateToFinish(); - } - - void RetryUrlTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - // Set 1 as the retry limit (does not exceed the max). - // Expect 1 manifest fetch, 1 url fetch, 1 url retry, 1 manifest refetch. - RetryRequestTestJob::Initialize(1, RetryRequestTestJob::RETRY_AFTER_0, 4); - net::URLRequestJobFactoryImpl* new_factory( - new net::URLRequestJobFactoryImpl); - new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory); - io_thread_->SetNewJobFactory(new_factory); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), GURL("http://retryurl"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - // Set up checks for when update job finishes. - do_checks_after_update_finished_ = true; - expect_group_obsolete_ = false; - expect_group_has_cache_ = true; - frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()), - CHECKING_EVENT); - - WaitForUpdateToFinish(); - } - - void FailStoreNewestCacheTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service_->storage()); - storage->SimulateStoreGroupAndNewestCacheFailure(); - - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - - // Set up checks for when update job finishes. - do_checks_after_update_finished_ = true; - expect_group_obsolete_ = false; - expect_group_has_cache_ = false; // storage failed - frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()), - CHECKING_EVENT); - - WaitForUpdateToFinish(); - } - - void UpgradeFailStoreNewestCacheTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service_->storage()); - storage->SimulateStoreGroupAndNewestCacheFailure(); - - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 11); - MockFrontend* frontend1 = MakeMockFrontend(); - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - AppCacheHost* host2 = MakeHost(2, frontend2); - host1->AssociateCompleteCache(cache); - host2->AssociateCompleteCache(cache); - - update->StartUpdate(NULL, GURL()); - - // 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; // unchanged - 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, 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, ERROR_EVENT); - - WaitForUpdateToFinish(); - } - - void MasterEntryFailStoreNewestCacheTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service_->storage()); - storage->SimulateStoreGroupAndNewestCacheFailure(); - - const GURL kManifestUrl = MockHttpServer::GetMockUrl("files/notmodified"); - const int64 kManifestResponseId = 11; - - // Seed the response_info working set with canned data for - // files/servererror and for files/notmodified to test that the - // existing entries for those resource are reused by the update job. - const char kData[] = - "HTTP/1.1 200 OK\0" - "Content-type: text/cache-manifest\0" - "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0" - "\0"; - const std::string kRawHeaders(kData, arraysize(kData)); - MakeAppCacheResponseInfo(kManifestUrl, kManifestResponseId, kRawHeaders); - - group_ = new AppCacheGroup( - service_->storage(), kManifestUrl, - service_->storage()->NewGroupId()); - scoped_refptr<AppCache> cache( - MakeCacheForGroup(service_->storage()->NewCacheId(), - kManifestResponseId)); - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->first_party_url_ = kManifestUrl; - host->SelectCache(MockHttpServer::GetMockUrl("files/empty1"), - kNoCacheId, kManifestUrl); - - // Set up checks for when update job finishes. - do_checks_after_update_finished_ = true; - tested_manifest_ = EMPTY_MANIFEST; - tested_manifest_path_override_ = "files/notmodified"; - expect_group_obsolete_ = false; - expect_group_has_cache_ = true; - expect_newest_cache_ = cache.get(); // unchanged - MockFrontend::HostIds ids1(1, host->host_id()); - frontend->AddExpectedEvent(ids1, ERROR_EVENT); - frontend->expected_error_message_ = - "Failed to commit new cache to storage"; - - WaitForUpdateToFinish(); - } - - void UpgradeFailMakeGroupObsoleteTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service_->storage()); - storage->SimulateMakeGroupObsoleteFailure(); - - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/nosuchfile"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(1, 111); - MockFrontend* frontend1 = MakeMockFrontend(); - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - AppCacheHost* host2 = MakeHost(2, frontend2); - host1->AssociateCompleteCache(cache); - host2->AssociateCompleteCache(cache); - - update->StartUpdate(NULL, GURL()); - EXPECT_TRUE(update->manifest_fetcher_ != 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, ERROR_EVENT); - MockFrontend::HostIds ids2(1, host2->host_id()); - frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); - frontend2->AddExpectedEvent(ids2, ERROR_EVENT); - - WaitForUpdateToFinish(); - } - - void MasterEntryFetchManifestFailTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"), 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->new_master_entry_url_ = GURL("http://failme/blah"); - update->StartUpdate(host, host->new_master_entry_url_); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - update->manifest_fetcher_->request()->CancelWithError(-100); - - // Set up checks for when update job finishes. - do_checks_after_update_finished_ = true; - expect_group_obsolete_ = false; - expect_group_has_cache_ = false; - MockFrontend::HostIds ids1(1, host->host_id()); - frontend->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend->AddExpectedEvent(ids1, ERROR_EVENT); - - WaitForUpdateToFinish(); - } - - void MasterEntryBadManifestTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), - MockHttpServer::GetMockUrl("files/bad-manifest"), 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/blah"); - update->StartUpdate(host, host->new_master_entry_url_); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - // Set up checks for when update job finishes. - do_checks_after_update_finished_ = true; - expect_group_obsolete_ = false; - expect_group_has_cache_ = false; - MockFrontend::HostIds ids1(1, host->host_id()); - frontend->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend->AddExpectedEvent(ids1, ERROR_EVENT); - - WaitForUpdateToFinish(); - } - - void MasterEntryManifestNotFoundTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), - MockHttpServer::GetMockUrl("files/nosuchfile"), - 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/blah"); - - update->StartUpdate(host, host->new_master_entry_url_); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - // Set up checks for when update job finishes. - do_checks_after_update_finished_ = true; - expect_group_obsolete_ = false; - expect_group_has_cache_ = false; - MockFrontend::HostIds ids1(1, host->host_id()); - frontend->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend->AddExpectedEvent(ids1, ERROR_EVENT); - - WaitForUpdateToFinish(); - } - - void MasterEntryFailUrlFetchTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), - MockHttpServer::GetMockUrl("files/manifest-fb-404"), 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - frontend->SetIgnoreProgressEvents(true); - AppCacheHost* host = MakeHost(1, frontend); - host->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit1"); - - update->StartUpdate(host, host->new_master_entry_url_); - EXPECT_TRUE(update->manifest_fetcher_ != 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 fallback url is cache failure - MockFrontend::HostIds ids1(1, host->host_id()); - frontend->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend->AddExpectedEvent(ids1, DOWNLOADING_EVENT); - frontend->AddExpectedEvent(ids1, ERROR_EVENT); - - WaitForUpdateToFinish(); - } - - void MasterEntryAllFailTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), - MockHttpServer::GetMockUrl("files/manifest1"), - 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend1 = MakeMockFrontend(); - frontend1->SetIgnoreProgressEvents(true); - AppCacheHost* host1 = MakeHost(1, frontend1); - host1->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/nosuchfile"); - update->StartUpdate(host1, host1->new_master_entry_url_); - - MockFrontend* frontend2 = MakeMockFrontend(); - frontend2->SetIgnoreProgressEvents(true); - AppCacheHost* host2 = MakeHost(2, frontend2); - host2->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/servererror"); - update->StartUpdate(host2, host2->new_master_entry_url_); - - // Set up checks for when update job finishes. - do_checks_after_update_finished_ = true; - expect_group_obsolete_ = false; - expect_group_has_cache_ = false; // all pending masters failed - MockFrontend::HostIds ids1(1, host1->host_id()); - frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend1->AddExpectedEvent(ids1, DOWNLOADING_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, ERROR_EVENT); - - WaitForUpdateToFinish(); - } - - void UpgradeMasterEntryAllFailTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), - MockHttpServer::GetMockUrl("files/manifest1"), - 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42); - MockFrontend* frontend1 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - host1->AssociateCompleteCache(cache); - - MockFrontend* frontend2 = MakeMockFrontend(); - frontend2->SetIgnoreProgressEvents(true); - AppCacheHost* host2 = MakeHost(2, frontend2); - host2->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/nosuchfile"); - update->StartUpdate(host2, host2->new_master_entry_url_); - - MockFrontend* frontend3 = MakeMockFrontend(); - frontend3->SetIgnoreProgressEvents(true); - AppCacheHost* host3 = MakeHost(3, frontend3); - host3->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/servererror"); - update->StartUpdate(host3, host3->new_master_entry_url_); - - // 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, PROGRESS_EVENT); // final - frontend1->AddExpectedEvent(ids1, UPDATE_READY_EVENT); - MockFrontend::HostIds ids2(1, host2->host_id()); - frontend2->AddExpectedEvent(ids2, DOWNLOADING_EVENT); - frontend2->AddExpectedEvent(ids2, ERROR_EVENT); - MockFrontend::HostIds ids3(1, host3->host_id()); - frontend3->AddExpectedEvent(ids3, CHECKING_EVENT); - frontend3->AddExpectedEvent(ids3, DOWNLOADING_EVENT); - frontend3->AddExpectedEvent(ids3, ERROR_EVENT); - - WaitForUpdateToFinish(); - } - - void MasterEntrySomeFailTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), - MockHttpServer::GetMockUrl("files/manifest1"), - 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend1 = MakeMockFrontend(); - frontend1->SetIgnoreProgressEvents(true); - AppCacheHost* host1 = MakeHost(1, frontend1); - host1->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/nosuchfile"); - update->StartUpdate(host1, host1->new_master_entry_url_); - - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host2 = MakeHost(2, frontend2); - host2->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit2"); - update->StartUpdate(host2, host2->new_master_entry_url_); - - // Set up checks for when update job finishes. - do_checks_after_update_finished_ = true; - expect_group_obsolete_ = false; - expect_group_has_cache_ = true; // as long as one pending master succeeds - tested_manifest_ = MANIFEST1; - expect_extra_entries_.insert(AppCache::EntryMap::value_type( - MockHttpServer::GetMockUrl("files/explicit2"), - AppCacheEntry(AppCacheEntry::MASTER))); - MockFrontend::HostIds ids1(1, host1->host_id()); - frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend1->AddExpectedEvent(ids1, DOWNLOADING_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); // final - frontend2->AddExpectedEvent(ids2, CACHED_EVENT); - - WaitForUpdateToFinish(); - } - - void UpgradeMasterEntrySomeFailTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), - MockHttpServer::GetMockUrl("files/manifest1"), - 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42); - MockFrontend* frontend1 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - host1->AssociateCompleteCache(cache); - - MockFrontend* frontend2 = MakeMockFrontend(); - frontend2->SetIgnoreProgressEvents(true); - AppCacheHost* host2 = MakeHost(2, frontend2); - host2->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/nosuchfile"); - update->StartUpdate(host2, host2->new_master_entry_url_); - - MockFrontend* frontend3 = MakeMockFrontend(); - AppCacheHost* host3 = MakeHost(3, frontend3); - host3->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit2"); - update->StartUpdate(host3, host3->new_master_entry_url_); - - // 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( - MockHttpServer::GetMockUrl("files/explicit2"), - AppCacheEntry(AppCacheEntry::MASTER))); - 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); // final - frontend1->AddExpectedEvent(ids1, UPDATE_READY_EVENT); - MockFrontend::HostIds ids2(1, host2->host_id()); - frontend2->AddExpectedEvent(ids2, DOWNLOADING_EVENT); - frontend2->AddExpectedEvent(ids2, ERROR_EVENT); - MockFrontend::HostIds ids3(1, host3->host_id()); - frontend3->AddExpectedEvent(ids3, CHECKING_EVENT); - frontend3->AddExpectedEvent(ids3, DOWNLOADING_EVENT); - frontend3->AddExpectedEvent(ids3, PROGRESS_EVENT); - frontend3->AddExpectedEvent(ids3, PROGRESS_EVENT); - frontend3->AddExpectedEvent(ids3, PROGRESS_EVENT); // final - frontend3->AddExpectedEvent(ids3, UPDATE_READY_EVENT); - - WaitForUpdateToFinish(); - } - - void MasterEntryNoUpdateTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup(service_->storage(), - MockHttpServer::GetMockUrl("files/notmodified"), 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(1, 111); - MockFrontend* frontend1 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - host1->AssociateCompleteCache(cache); - - // Give cache an existing entry that can also be fetched. - cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit2"), - AppCacheEntry(AppCacheEntry::EXPLICIT, 222)); - - // Reset the update time to null so we can verify it gets - // modified in this test case by the UpdateJob. - cache->set_update_time(base::Time()); - - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host2 = MakeHost(2, frontend2); - host2->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit1"); - update->StartUpdate(host2, host2->new_master_entry_url_); - - AppCacheHost* host3 = MakeHost(3, frontend2); // same frontend as host2 - host3->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit2"); - update->StartUpdate(host3, host3->new_master_entry_url_); - - // 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 still the same cache - expect_non_null_update_time_ = true; - tested_manifest_ = PENDING_MASTER_NO_UPDATE; - MockFrontend::HostIds ids1(1, host1->host_id()); - frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend1->AddExpectedEvent(ids1, NO_UPDATE_EVENT); - MockFrontend::HostIds ids3(1, host3->host_id()); - frontend2->AddExpectedEvent(ids3, CHECKING_EVENT); - MockFrontend::HostIds ids2and3; - ids2and3.push_back(host2->host_id()); - ids2and3.push_back(host3->host_id()); - frontend2->AddExpectedEvent(ids2and3, NO_UPDATE_EVENT); - - WaitForUpdateToFinish(); - } - - void StartUpdateMidCacheAttemptTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend1 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - host1->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit2"); - update->StartUpdate(host1, host1->new_master_entry_url_); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - // Set up additional updates to be started while update is in progress. - MockFrontend* frontend2 = MakeMockFrontend(); - frontend2->SetIgnoreProgressEvents(true); - AppCacheHost* host2 = MakeHost(2, frontend2); - host2->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/nosuchfile"); - - MockFrontend* frontend3 = MakeMockFrontend(); - AppCacheHost* host3 = MakeHost(3, frontend3); - host3->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit1"); - - MockFrontend* frontend4 = MakeMockFrontend(); - AppCacheHost* host4 = MakeHost(4, frontend4); - host4->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit2"); - - MockFrontend* frontend5 = MakeMockFrontend(); - AppCacheHost* host5 = MakeHost(5, frontend5); // no master entry url - - frontend1->TriggerAdditionalUpdates(DOWNLOADING_EVENT, update); - frontend1->AdditionalUpdateHost(host2); // fetch will fail - frontend1->AdditionalUpdateHost(host3); // same as an explicit entry - frontend1->AdditionalUpdateHost(host4); // same as another master entry - frontend1->AdditionalUpdateHost(NULL); // no host - frontend1->AdditionalUpdateHost(host5); // no master entry url - - // 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; - expect_extra_entries_.insert(AppCache::EntryMap::value_type( - MockHttpServer::GetMockUrl("files/explicit2"), - AppCacheEntry(AppCacheEntry::MASTER))); - 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); // final - frontend1->AddExpectedEvent(ids1, CACHED_EVENT); - MockFrontend::HostIds ids2(1, host2->host_id()); - frontend2->AddExpectedEvent(ids2, CHECKING_EVENT); - frontend2->AddExpectedEvent(ids2, DOWNLOADING_EVENT); - frontend2->AddExpectedEvent(ids2, ERROR_EVENT); - MockFrontend::HostIds ids3(1, host3->host_id()); - frontend3->AddExpectedEvent(ids3, CHECKING_EVENT); - frontend3->AddExpectedEvent(ids3, DOWNLOADING_EVENT); - frontend3->AddExpectedEvent(ids3, PROGRESS_EVENT); - frontend3->AddExpectedEvent(ids3, PROGRESS_EVENT); - frontend3->AddExpectedEvent(ids3, PROGRESS_EVENT); // final - frontend3->AddExpectedEvent(ids3, CACHED_EVENT); - MockFrontend::HostIds ids4(1, host4->host_id()); - frontend4->AddExpectedEvent(ids4, CHECKING_EVENT); - frontend4->AddExpectedEvent(ids4, DOWNLOADING_EVENT); - frontend4->AddExpectedEvent(ids4, PROGRESS_EVENT); - frontend4->AddExpectedEvent(ids4, PROGRESS_EVENT); - frontend4->AddExpectedEvent(ids4, PROGRESS_EVENT); // final - frontend4->AddExpectedEvent(ids4, CACHED_EVENT); - - // Host 5 is not associated with cache so no progress/cached events. - MockFrontend::HostIds ids5(1, host5->host_id()); - frontend5->AddExpectedEvent(ids5, CHECKING_EVENT); - frontend5->AddExpectedEvent(ids5, DOWNLOADING_EVENT); - - WaitForUpdateToFinish(); - } - - void StartUpdateMidNoUpdateTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"), - service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(1, 111); - MockFrontend* frontend1 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - host1->AssociateCompleteCache(cache); - - // Give cache an existing entry. - cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit2"), - AppCacheEntry(AppCacheEntry::EXPLICIT, 222)); - - // Start update with a pending master entry that will fail to give us an - // event to trigger other updates. - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host2 = MakeHost(2, frontend2); - host2->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/nosuchfile"); - update->StartUpdate(host2, host2->new_master_entry_url_); - EXPECT_TRUE(update->manifest_fetcher_ != NULL); - - // Set up additional updates to be started while update is in progress. - MockFrontend* frontend3 = MakeMockFrontend(); - AppCacheHost* host3 = MakeHost(3, frontend3); - host3->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit1"); - - MockFrontend* frontend4 = MakeMockFrontend(); - AppCacheHost* host4 = MakeHost(4, frontend4); // no master entry url - - MockFrontend* frontend5 = MakeMockFrontend(); - AppCacheHost* host5 = MakeHost(5, frontend5); - host5->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit2"); // existing entry - - MockFrontend* frontend6 = MakeMockFrontend(); - AppCacheHost* host6 = MakeHost(6, frontend6); - host6->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit1"); - - frontend2->TriggerAdditionalUpdates(ERROR_EVENT, update); - frontend2->AdditionalUpdateHost(host3); - frontend2->AdditionalUpdateHost(NULL); // no host - frontend2->AdditionalUpdateHost(host4); // no master entry url - frontend2->AdditionalUpdateHost(host5); // same as existing cache entry - frontend2->AdditionalUpdateHost(host6); // same as another master entry - - // 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 - tested_manifest_ = PENDING_MASTER_NO_UPDATE; - MockFrontend::HostIds ids1(1, host1->host_id()); // prior associated host - frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend1->AddExpectedEvent(ids1, NO_UPDATE_EVENT); - MockFrontend::HostIds ids2(1, host2->host_id()); - frontend2->AddExpectedEvent(ids2, ERROR_EVENT); - MockFrontend::HostIds ids3(1, host3->host_id()); - frontend3->AddExpectedEvent(ids3, CHECKING_EVENT); - frontend3->AddExpectedEvent(ids3, NO_UPDATE_EVENT); - MockFrontend::HostIds ids4(1, host4->host_id()); // unassociated w/cache - frontend4->AddExpectedEvent(ids4, CHECKING_EVENT); - MockFrontend::HostIds ids5(1, host5->host_id()); - frontend5->AddExpectedEvent(ids5, CHECKING_EVENT); - frontend5->AddExpectedEvent(ids5, NO_UPDATE_EVENT); - MockFrontend::HostIds ids6(1, host6->host_id()); - frontend6->AddExpectedEvent(ids6, CHECKING_EVENT); - frontend6->AddExpectedEvent(ids6, NO_UPDATE_EVENT); - - WaitForUpdateToFinish(); - } - - void StartUpdateMidDownloadTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), - MockHttpServer::GetMockUrl("files/manifest1"), - 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42); - MockFrontend* frontend1 = MakeMockFrontend(); - AppCacheHost* host1 = MakeHost(1, frontend1); - host1->AssociateCompleteCache(cache); - - update->StartUpdate(NULL, GURL()); - - // Set up additional updates to be started while update is in progress. - MockFrontend* frontend2 = MakeMockFrontend(); - AppCacheHost* host2 = MakeHost(2, frontend2); - host2->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit1"); - - MockFrontend* frontend3 = MakeMockFrontend(); - AppCacheHost* host3 = MakeHost(3, frontend3); - host3->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit2"); - - MockFrontend* frontend4 = MakeMockFrontend(); - AppCacheHost* host4 = MakeHost(4, frontend4); // no master entry url - - MockFrontend* frontend5 = MakeMockFrontend(); - AppCacheHost* host5 = MakeHost(5, frontend5); - host5->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit2"); - - frontend1->TriggerAdditionalUpdates(PROGRESS_EVENT, update); - frontend1->AdditionalUpdateHost(host2); // same as entry in manifest - frontend1->AdditionalUpdateHost(NULL); // no host - frontend1->AdditionalUpdateHost(host3); // new master entry - frontend1->AdditionalUpdateHost(host4); // no master entry url - frontend1->AdditionalUpdateHost(host5); // same as another master entry - - // 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; - expect_extra_entries_.insert(AppCache::EntryMap::value_type( - MockHttpServer::GetMockUrl("files/explicit2"), - AppCacheEntry(AppCacheEntry::MASTER))); - MockFrontend::HostIds ids1(1, host1->host_id()); // prior associated host - 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); // final - 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); // final - frontend2->AddExpectedEvent(ids2, UPDATE_READY_EVENT); - MockFrontend::HostIds ids3(1, host3->host_id()); - frontend3->AddExpectedEvent(ids3, CHECKING_EVENT); - frontend3->AddExpectedEvent(ids3, DOWNLOADING_EVENT); - frontend3->AddExpectedEvent(ids3, PROGRESS_EVENT); - frontend3->AddExpectedEvent(ids3, PROGRESS_EVENT); // final - frontend3->AddExpectedEvent(ids3, UPDATE_READY_EVENT); - MockFrontend::HostIds ids4(1, host4->host_id()); // unassociated w/cache - frontend4->AddExpectedEvent(ids4, CHECKING_EVENT); - frontend4->AddExpectedEvent(ids4, DOWNLOADING_EVENT); - MockFrontend::HostIds ids5(1, host5->host_id()); - frontend5->AddExpectedEvent(ids5, CHECKING_EVENT); - frontend5->AddExpectedEvent(ids5, DOWNLOADING_EVENT); - frontend5->AddExpectedEvent(ids5, PROGRESS_EVENT); - frontend5->AddExpectedEvent(ids5, PROGRESS_EVENT); // final - frontend5->AddExpectedEvent(ids5, UPDATE_READY_EVENT); - - WaitForUpdateToFinish(); - } - - void QueueMasterEntryTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), - MockHttpServer::GetMockUrl("files/manifest1"), - 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - // Pretend update job has been running and is about to terminate. - group_->update_status_ = AppCacheGroup::DOWNLOADING; - update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST; - EXPECT_TRUE(update->IsTerminating()); - - // Start an update. Should be queued. - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->new_master_entry_url_ = - MockHttpServer::GetMockUrl("files/explicit2"); - update->StartUpdate(host, host->new_master_entry_url_); - EXPECT_TRUE(update->pending_master_entries_.empty()); - EXPECT_FALSE(group_->queued_updates_.empty()); - - // Delete update, causing it to finish, which should trigger a new update - // for the queued host and master entry after a delay. - delete update; - EXPECT_FALSE(group_->restart_update_task_.IsCancelled()); - - // Set up checks for when queued update job finishes. - do_checks_after_update_finished_ = true; - expect_group_obsolete_ = false; - expect_group_has_cache_ = true; - tested_manifest_ = MANIFEST1; - expect_extra_entries_.insert(AppCache::EntryMap::value_type( - host->new_master_entry_url_, AppCacheEntry(AppCacheEntry::MASTER))); - MockFrontend::HostIds ids1(1, host->host_id()); - frontend->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend->AddExpectedEvent(ids1, DOWNLOADING_EVENT); - frontend->AddExpectedEvent(ids1, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids1, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids1, PROGRESS_EVENT); // final - frontend->AddExpectedEvent(ids1, CACHED_EVENT); - - // Group status will be IDLE so cannot call WaitForUpdateToFinish. - group_->AddUpdateObserver(this); - } - - void IfModifiedSinceTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - net::URLRequestJobFactoryImpl* new_factory( - new net::URLRequestJobFactoryImpl); - new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory); - io_thread_->SetNewJobFactory(new_factory); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), GURL("http://headertest"), 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - // First test against a cache attempt. Will start manifest fetch - // synchronously. - HttpHeadersRequestTestJob::Initialize(std::string(), std::string()); - MockFrontend mock_frontend; - AppCacheHost host(1, &mock_frontend, service_.get()); - update->StartUpdate(&host, GURL()); - HttpHeadersRequestTestJob::Verify(); - delete update; - - // Now simulate a refetch manifest request. Will start fetch request - // synchronously. - const char data[] = - "HTTP/1.1 200 OK\0" - "\0"; - net::HttpResponseHeaders* headers = - new net::HttpResponseHeaders(std::string(data, arraysize(data))); - net::HttpResponseInfo* response_info = new net::HttpResponseInfo(); - response_info->headers = headers; // adds ref to headers - - HttpHeadersRequestTestJob::Initialize(std::string(), std::string()); - update = new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - group_->update_status_ = AppCacheGroup::DOWNLOADING; - update->manifest_response_info_.reset(response_info); - update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST; - update->FetchManifest(false); // not first request - HttpHeadersRequestTestJob::Verify(); - delete update; - - // Change the headers to include a Last-Modified header. Manifest refetch - // should include If-Modified-Since header. - const char data2[] = - "HTTP/1.1 200 OK\0" - "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0" - "\0"; - net::HttpResponseHeaders* headers2 = - new net::HttpResponseHeaders(std::string(data2, arraysize(data2))); - response_info = new net::HttpResponseInfo(); - response_info->headers = headers2; - - HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT", - std::string()); - update = new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - group_->update_status_ = AppCacheGroup::DOWNLOADING; - update->manifest_response_info_.reset(response_info); - update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST; - update->FetchManifest(false); // not first request - HttpHeadersRequestTestJob::Verify(); - delete update; - - UpdateFinished(); - } - - void IfModifiedSinceUpgradeTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT", - std::string()); - net::URLRequestJobFactoryImpl* new_factory( - new net::URLRequestJobFactoryImpl); - new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory); - io_thread_->SetNewJobFactory(new_factory); - - MakeService(); - group_ =new AppCacheGroup( - service_->storage(), - MockHttpServer::GetMockUrl("files/manifest1"), - 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - // Give the newest cache a manifest enry that is in storage. - response_writer_.reset( - service_->storage()->CreateResponseWriter(group_->manifest_url(), - group_->group_id())); - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), - response_writer_->response_id()); - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->AssociateCompleteCache(cache); - - // 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, host->host_id()); - frontend->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend->AddExpectedEvent(ids1, DOWNLOADING_EVENT); - frontend->AddExpectedEvent(ids1, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids1, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids1, PROGRESS_EVENT); // final - frontend->AddExpectedEvent(ids1, UPDATE_READY_EVENT); - - // Seed storage with expected manifest response info that will cause - // an If-Modified-Since header to be put in the manifest fetch request. - const char data[] = - "HTTP/1.1 200 OK\0" - "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0" - "\0"; - net::HttpResponseHeaders* headers = - new net::HttpResponseHeaders(std::string(data, arraysize(data))); - net::HttpResponseInfo* response_info = new net::HttpResponseInfo(); - response_info->headers = headers; // adds ref to headers - scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( - new HttpResponseInfoIOBuffer(response_info)); // adds ref to info - response_writer_->WriteInfo( - io_buffer.get(), - base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData, - base::Unretained(this))); - - // Start update after data write completes asynchronously. - } - - void IfNoneMatchUpgradeTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\""); - net::URLRequestJobFactoryImpl* new_factory( - new net::URLRequestJobFactoryImpl); - new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory); - io_thread_->SetNewJobFactory(new_factory); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), - MockHttpServer::GetMockUrl("files/manifest1"), - 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - // Give the newest cache a manifest enry that is in storage. - response_writer_.reset( - service_->storage()->CreateResponseWriter(group_->manifest_url(), - group_->group_id())); - - AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), - response_writer_->response_id()); - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - host->AssociateCompleteCache(cache); - - // 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, host->host_id()); - frontend->AddExpectedEvent(ids1, CHECKING_EVENT); - frontend->AddExpectedEvent(ids1, DOWNLOADING_EVENT); - frontend->AddExpectedEvent(ids1, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids1, PROGRESS_EVENT); - frontend->AddExpectedEvent(ids1, PROGRESS_EVENT); // final - frontend->AddExpectedEvent(ids1, UPDATE_READY_EVENT); - - // Seed storage with expected manifest response info that will cause - // an If-None-Match header to be put in the manifest fetch request. - const char data[] = - "HTTP/1.1 200 OK\0" - "ETag: \"LadeDade\"\0" - "\0"; - net::HttpResponseHeaders* headers = - new net::HttpResponseHeaders(std::string(data, arraysize(data))); - net::HttpResponseInfo* response_info = new net::HttpResponseInfo(); - response_info->headers = headers; // adds ref to headers - scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( - new HttpResponseInfoIOBuffer(response_info)); // adds ref to info - response_writer_->WriteInfo( - io_buffer.get(), - base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData, - base::Unretained(this))); - - // Start update after data write completes asynchronously. - } - - void IfNoneMatchRefetchTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\""); - net::URLRequestJobFactoryImpl* new_factory( - new net::URLRequestJobFactoryImpl); - new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory); - io_thread_->SetNewJobFactory(new_factory); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), GURL("http://headertest"), 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - // Simulate a refetch manifest request that uses an ETag header. - const char data[] = - "HTTP/1.1 200 OK\0" - "ETag: \"LadeDade\"\0" - "\0"; - net::HttpResponseHeaders* headers = - new net::HttpResponseHeaders(std::string(data, arraysize(data))); - net::HttpResponseInfo* response_info = new net::HttpResponseInfo(); - response_info->headers = headers; // adds ref to headers - - group_->update_status_ = AppCacheGroup::DOWNLOADING; - update->manifest_response_info_.reset(response_info); - update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST; - update->FetchManifest(false); // not first request - HttpHeadersRequestTestJob::Verify(); - delete update; - - UpdateFinished(); - } - - void MultipleHeadersRefetchTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - // Verify that code is correct when building multiple extra headers. - HttpHeadersRequestTestJob::Initialize( - "Sat, 29 Oct 1994 19:43:31 GMT", "\"LadeDade\""); - net::URLRequestJobFactoryImpl* new_factory( - new net::URLRequestJobFactoryImpl); - new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory); - io_thread_->SetNewJobFactory(new_factory); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), GURL("http://headertest"), 111); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - // Simulate a refetch manifest request that uses an ETag header. - const char data[] = - "HTTP/1.1 200 OK\0" - "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0" - "ETag: \"LadeDade\"\0" - "\0"; - net::HttpResponseHeaders* headers = - new net::HttpResponseHeaders(std::string(data, arraysize(data))); - net::HttpResponseInfo* response_info = new net::HttpResponseInfo(); - response_info->headers = headers; // adds ref to headers - - group_->update_status_ = AppCacheGroup::DOWNLOADING; - update->manifest_response_info_.reset(response_info); - update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST; - update->FetchManifest(false); // not first request - HttpHeadersRequestTestJob::Verify(); - delete update; - - UpdateFinished(); - } - - void CrossOriginHttpsSuccessTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - GURL manifest_url = MockHttpServer::GetMockHttpsUrl( - "files/valid_cross_origin_https_manifest"); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), manifest_url, service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - - // 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_ = NONE; - MockFrontend::HostIds host_ids(1, host->host_id()); - frontend->AddExpectedEvent(host_ids, CHECKING_EVENT); - - WaitForUpdateToFinish(); - } - - void CrossOriginHttpsDeniedTest() { - ASSERT_TRUE(base::MessageLoopForIO::IsCurrent()); - - GURL manifest_url = MockHttpServer::GetMockHttpsUrl( - "files/invalid_cross_origin_https_manifest"); - - MakeService(); - group_ = new AppCacheGroup( - service_->storage(), manifest_url, service_->storage()->NewGroupId()); - AppCacheUpdateJob* update = - new AppCacheUpdateJob(service_.get(), group_.get()); - group_->update_job_ = update; - - MockFrontend* frontend = MakeMockFrontend(); - AppCacheHost* host = MakeHost(1, frontend); - update->StartUpdate(host, GURL()); - - // Set up checks for when update job finishes. - do_checks_after_update_finished_ = true; - expect_group_obsolete_ = false; - expect_group_has_cache_ = false; - tested_manifest_ = NONE; - MockFrontend::HostIds host_ids(1, host->host_id()); - frontend->AddExpectedEvent(host_ids, CHECKING_EVENT); - - WaitForUpdateToFinish(); - } - - void WaitForUpdateToFinish() { - if (group_->update_status() == AppCacheGroup::IDLE) - UpdateFinished(); - else - group_->AddUpdateObserver(this); - } - - virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE { - ASSERT_EQ(group_, group); - protect_newest_cache_ = group->newest_complete_cache(); - UpdateFinished(); - } - - void UpdateFinished() { - // We unwind the stack prior to finishing up to let stack-based objects - // get deleted. - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&AppCacheUpdateJobTest::UpdateFinishedUnwound, - base::Unretained(this))); - } - - void UpdateFinishedUnwound() { - 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. - protect_newest_cache_ = NULL; - group_ = NULL; - STLDeleteContainerPointers(hosts_.begin(), hosts_.end()); - STLDeleteContainerPointers(frontends_.begin(), frontends_.end()); - response_infos_.clear(); - service_.reset(NULL); - - event_->Signal(); - } - - void MakeService() { - service_.reset(new MockAppCacheService()); - service_->set_request_context(io_thread_->request_context()); - } - - AppCache* MakeCacheForGroup(int64 cache_id, int64 manifest_response_id) { - return MakeCacheForGroup(cache_id, group_->manifest_url(), - manifest_response_id); - } - - AppCache* MakeCacheForGroup(int64 cache_id, const GURL& manifest_entry_url, - int64 manifest_response_id) { - AppCache* cache = new AppCache(service_->storage(), cache_id); - cache->set_complete(true); - cache->set_update_time(base::Time::Now()); - group_->AddCache(cache); - - // Add manifest entry to cache. - cache->AddEntry(manifest_entry_url, - AppCacheEntry(AppCacheEntry::MANIFEST, manifest_response_id)); - - return cache; - } - - AppCacheHost* MakeHost(int host_id, AppCacheFrontend* frontend) { - AppCacheHost* host = new AppCacheHost(host_id, frontend, service_.get()); - hosts_.push_back(host); - return host; - } - - AppCacheResponseInfo* MakeAppCacheResponseInfo( - const GURL& manifest_url, int64 response_id, - const std::string& raw_headers) { - net::HttpResponseInfo* http_info = new net::HttpResponseInfo(); - http_info->headers = new net::HttpResponseHeaders(raw_headers); - scoped_refptr<AppCacheResponseInfo> info( - new AppCacheResponseInfo(service_->storage(), manifest_url, - response_id, http_info, 0)); - response_infos_.push_back(info); - return info.get(); - } - - 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() { - RetryRequestTestJob::Verify(); - HttpHeadersRequestTestJob::Verify(); - - EXPECT_EQ(expect_group_obsolete_, group_->is_obsolete()); - EXPECT_EQ(expect_group_is_being_deleted_, group_->is_being_deleted()); - - if (expect_group_has_cache_) { - EXPECT_TRUE(group_->newest_complete_cache() != NULL); - - if (expect_non_null_update_time_) - EXPECT_TRUE(!group_->newest_complete_cache()->update_time().is_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()); - EXPECT_TRUE(group_->old_caches().end() == - std::find(group_->old_caches().begin(), - group_->old_caches().end(), expect_newest_cache_)); - } else { - // Tests that don't know which newest cache to expect contain updates - // that succeed (because the update creates a new cache whose pointer - // is unknown to the test). Check group and newest cache were stored - // when update succeeds. - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service_->storage()); - EXPECT_TRUE(storage->IsGroupStored(group_.get())); - EXPECT_TRUE(storage->IsCacheStored(group_->newest_complete_cache())); - - // Check that all entries in the newest cache were stored. - const AppCache::EntryMap& entries = - group_->newest_complete_cache()->entries(); - for (AppCache::EntryMap::const_iterator it = entries.begin(); - it != entries.end(); ++it) { - EXPECT_NE(kNoResponseId, it->second.response_id()); - - // Check that any copied entries have the expected response id - // and that entries that are not copied have a different response id. - std::map<GURL, int64>::iterator found = - expect_response_ids_.find(it->first); - if (found != expect_response_ids_.end()) { - EXPECT_EQ(found->second, it->second.response_id()); - } else if (expect_old_cache_) { - AppCacheEntry* old_entry = expect_old_cache_->GetEntry(it->first); - if (old_entry) - EXPECT_NE(old_entry->response_id(), it->second.response_id()); - } - } - } - } 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()); - } - } - - if (!frontend->expected_error_message_.empty()) { - EXPECT_EQ(frontend->expected_error_message_, - frontend->error_message_); - } - } - - // Verify expected cache contents last as some checks are asserts - // and will abort the test if they fail. - if (tested_manifest_) { - AppCache* cache = group_->newest_complete_cache(); - ASSERT_TRUE(cache != NULL); - EXPECT_EQ(group_, cache->owning_group()); - EXPECT_TRUE(cache->is_complete()); - - switch (tested_manifest_) { - case MANIFEST1: - VerifyManifest1(cache); - break; - case MANIFEST_MERGED_TYPES: - VerifyManifestMergedTypes(cache); - break; - case EMPTY_MANIFEST: - VerifyEmptyManifest(cache); - break; - case EMPTY_FILE_MANIFEST: - VerifyEmptyFileManifest(cache); - break; - case PENDING_MASTER_NO_UPDATE: - VerifyMasterEntryNoUpdate(cache); - break; - case MANIFEST_WITH_INTERCEPT: - VerifyManifestWithIntercept(cache); - break; - case NONE: - default: - break; - } - } - } - - void VerifyManifest1(AppCache* cache) { - size_t expected = 3 + expect_extra_entries_.size(); - EXPECT_EQ(expected, cache->entries().size()); - const char* kManifestPath = tested_manifest_path_override_ ? - tested_manifest_path_override_ : - "files/manifest1"; - AppCacheEntry* entry = - cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath)); - ASSERT_TRUE(entry); - EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types()); - entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1")); - ASSERT_TRUE(entry); - EXPECT_TRUE(entry->IsExplicit()); - entry = cache->GetEntry( - MockHttpServer::GetMockUrl("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()); - } - - expected = 1; - ASSERT_EQ(expected, cache->fallback_namespaces_.size()); - EXPECT_TRUE(cache->fallback_namespaces_[0] == - Namespace( - FALLBACK_NAMESPACE, - MockHttpServer::GetMockUrl("files/fallback1"), - MockHttpServer::GetMockUrl("files/fallback1a"), - false)); - - EXPECT_TRUE(cache->online_whitelist_namespaces_.empty()); - EXPECT_TRUE(cache->online_whitelist_all_); - - EXPECT_TRUE(cache->update_time_ > base::Time()); - } - - void VerifyManifestMergedTypes(AppCache* cache) { - size_t expected = 2; - EXPECT_EQ(expected, cache->entries().size()); - AppCacheEntry* entry = cache->GetEntry( - MockHttpServer::GetMockUrl("files/manifest-merged-types")); - ASSERT_TRUE(entry); - EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::MANIFEST, - entry->types()); - entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1")); - ASSERT_TRUE(entry); - EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::FALLBACK | - AppCacheEntry::MASTER, entry->types()); - - expected = 1; - ASSERT_EQ(expected, cache->fallback_namespaces_.size()); - EXPECT_TRUE(cache->fallback_namespaces_[0] == - Namespace( - FALLBACK_NAMESPACE, - MockHttpServer::GetMockUrl("files/fallback1"), - MockHttpServer::GetMockUrl("files/explicit1"), - false)); - - EXPECT_EQ(expected, cache->online_whitelist_namespaces_.size()); - EXPECT_TRUE(cache->online_whitelist_namespaces_[0] == - Namespace( - NETWORK_NAMESPACE, - MockHttpServer::GetMockUrl("files/online1"), - GURL(), false)); - EXPECT_FALSE(cache->online_whitelist_all_); - - EXPECT_TRUE(cache->update_time_ > base::Time()); - } - - void VerifyEmptyManifest(AppCache* cache) { - const char* kManifestPath = tested_manifest_path_override_ ? - tested_manifest_path_override_ : - "files/empty-manifest"; - size_t expected = 1; - EXPECT_EQ(expected, cache->entries().size()); - AppCacheEntry* entry = cache->GetEntry( - MockHttpServer::GetMockUrl(kManifestPath)); - 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::Time()); - } - - void VerifyEmptyFileManifest(AppCache* cache) { - EXPECT_EQ(size_t(2), cache->entries().size()); - AppCacheEntry* entry = cache->GetEntry( - MockHttpServer::GetMockUrl("files/empty-file-manifest")); - ASSERT_TRUE(entry); - EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types()); - - entry = cache->GetEntry( - MockHttpServer::GetMockUrl("files/empty1")); - ASSERT_TRUE(entry); - EXPECT_EQ(AppCacheEntry::EXPLICIT, entry->types()); - EXPECT_TRUE(entry->has_response_id()); - - 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::Time()); - } - - void VerifyMasterEntryNoUpdate(AppCache* cache) { - EXPECT_EQ(size_t(3), cache->entries().size()); - AppCacheEntry* entry = cache->GetEntry( - MockHttpServer::GetMockUrl("files/notmodified")); - ASSERT_TRUE(entry); - EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types()); - - entry = cache->GetEntry( - MockHttpServer::GetMockUrl("files/explicit1")); - ASSERT_TRUE(entry); - EXPECT_EQ(AppCacheEntry::MASTER, entry->types()); - EXPECT_TRUE(entry->has_response_id()); - - entry = cache->GetEntry( - MockHttpServer::GetMockUrl("files/explicit2")); - ASSERT_TRUE(entry); - EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::MASTER, entry->types()); - EXPECT_TRUE(entry->has_response_id()); - - 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::Time()); - } - - void VerifyManifestWithIntercept(AppCache* cache) { - EXPECT_EQ(2u, cache->entries().size()); - const char* kManifestPath = "files/manifest-with-intercept"; - AppCacheEntry* entry = - cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath)); - ASSERT_TRUE(entry); - EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types()); - entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/intercept1a")); - ASSERT_TRUE(entry); - EXPECT_TRUE(entry->IsIntercept()); - EXPECT_TRUE(cache->online_whitelist_namespaces_.empty()); - EXPECT_FALSE(cache->online_whitelist_all_); - EXPECT_TRUE(cache->update_time_ > base::Time()); - } - - private: - // Various manifest files used in this test. - enum TestedManifest { - NONE, - MANIFEST1, - MANIFEST_MERGED_TYPES, - EMPTY_MANIFEST, - EMPTY_FILE_MANIFEST, - PENDING_MASTER_NO_UPDATE, - MANIFEST_WITH_INTERCEPT - }; - - scoped_ptr<IOThread> io_thread_; - - scoped_ptr<MockAppCacheService> service_; - scoped_refptr<AppCacheGroup> group_; - scoped_refptr<AppCache> protect_newest_cache_; - scoped_ptr<base::WaitableEvent> event_; - - scoped_ptr<AppCacheResponseWriter> response_writer_; - - // 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_; - - // Response infos used by an async test that need to live until update job - // finishes. - std::vector<scoped_refptr<AppCacheResponseInfo> > response_infos_; - - // 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_; - bool expect_group_is_being_deleted_; - AppCache* expect_old_cache_; - AppCache* expect_newest_cache_; - bool expect_non_null_update_time_; - std::vector<MockFrontend*> frontends_; // to check expected events - TestedManifest tested_manifest_; - const char* tested_manifest_path_override_; - AppCache::EntryMap expect_extra_entries_; - std::map<GURL, int64> expect_response_ids_; -}; - -TEST_F(AppCacheUpdateJobTest, AlreadyChecking) { - MockAppCacheService service; - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"), - service.storage()->NewGroupId())); - - AppCacheUpdateJob update(&service, group.get()); - - // Pretend group is in checking state. - group->update_job_ = &update; - group->update_status_ = AppCacheGroup::CHECKING; - - update.StartUpdate(NULL, GURL()); - EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status()); - - MockFrontend mock_frontend; - AppCacheHost host(1, &mock_frontend, &service); - update.StartUpdate(&host, GURL()); - - 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) { - MockAppCacheService service; - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"), - service.storage()->NewGroupId())); - - AppCacheUpdateJob update(&service, group.get()); - - // Pretend group is in downloading state. - group->update_job_ = &update; - group->update_status_ = AppCacheGroup::DOWNLOADING; - - update.StartUpdate(NULL, GURL()); - EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status()); - - MockFrontend mock_frontend; - AppCacheHost host(1, &mock_frontend, &service); - update.StartUpdate(&host, GURL()); - - 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, ManifestMissingMimeTypeTest) { - RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestMissingMimeTypeTest); -} - -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, Bug95101Test) { - RunTestOnIOThread(&AppCacheUpdateJobTest::Bug95101Test); -} - -TEST_F(AppCacheUpdateJobTest, BasicCacheAttemptSuccess) { - RunTestOnIOThread(&AppCacheUpdateJobTest::BasicCacheAttemptSuccessTest); -} - -TEST_F(AppCacheUpdateJobTest, DownloadInterceptEntriesTest) { - RunTestOnIOThread(&AppCacheUpdateJobTest::DownloadInterceptEntriesTest); -} - -TEST_F(AppCacheUpdateJobTest, BasicUpgradeSuccess) { - RunTestOnIOThread(&AppCacheUpdateJobTest::BasicUpgradeSuccessTest); -} - -TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCache) { - RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheTest); -} - -TEST_F(AppCacheUpdateJobTest, UpgradeNoLoadFromNewestCache) { - RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNoLoadFromNewestCacheTest); -} - -TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheVaryHeader) { - RunTestOnIOThread( - &AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheVaryHeaderTest); -} - -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); -} - -TEST_F(AppCacheUpdateJobTest, EmptyFile) { - RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyFileTest); -} - -TEST_F(AppCacheUpdateJobTest, RetryRequest) { - RunTestOnIOThread(&AppCacheUpdateJobTest::RetryRequestTest); -} - -TEST_F(AppCacheUpdateJobTest, RetryNoRetryAfter) { - RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNoRetryAfterTest); -} - -TEST_F(AppCacheUpdateJobTest, RetryNonzeroRetryAfter) { - RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNonzeroRetryAfterTest); -} - -TEST_F(AppCacheUpdateJobTest, RetrySuccess) { - RunTestOnIOThread(&AppCacheUpdateJobTest::RetrySuccessTest); -} - -TEST_F(AppCacheUpdateJobTest, RetryUrl) { - RunTestOnIOThread(&AppCacheUpdateJobTest::RetryUrlTest); -} - -TEST_F(AppCacheUpdateJobTest, FailStoreNewestCache) { - RunTestOnIOThread(&AppCacheUpdateJobTest::FailStoreNewestCacheTest); -} - -TEST_F(AppCacheUpdateJobTest, MasterEntryFailStoreNewestCacheTest) { - RunTestOnIOThread( - &AppCacheUpdateJobTest::MasterEntryFailStoreNewestCacheTest); -} - -TEST_F(AppCacheUpdateJobTest, UpgradeFailStoreNewestCache) { - RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailStoreNewestCacheTest); -} - -TEST_F(AppCacheUpdateJobTest, UpgradeFailMakeGroupObsolete) { - RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMakeGroupObsoleteTest); -} - -TEST_F(AppCacheUpdateJobTest, MasterEntryFetchManifestFail) { - RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFetchManifestFailTest); -} - -TEST_F(AppCacheUpdateJobTest, MasterEntryBadManifest) { - RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryBadManifestTest); -} - -TEST_F(AppCacheUpdateJobTest, MasterEntryManifestNotFound) { - RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryManifestNotFoundTest); -} - -TEST_F(AppCacheUpdateJobTest, MasterEntryFailUrlFetch) { - RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFailUrlFetchTest); -} - -TEST_F(AppCacheUpdateJobTest, MasterEntryAllFail) { - RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryAllFailTest); -} - -TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntryAllFail) { - RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntryAllFailTest); -} - -TEST_F(AppCacheUpdateJobTest, MasterEntrySomeFail) { - RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntrySomeFailTest); -} - -TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntrySomeFail) { - RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntrySomeFailTest); -} - -TEST_F(AppCacheUpdateJobTest, MasterEntryNoUpdate) { - RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryNoUpdateTest); -} - -TEST_F(AppCacheUpdateJobTest, StartUpdateMidCacheAttempt) { - RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidCacheAttemptTest); -} - -TEST_F(AppCacheUpdateJobTest, StartUpdateMidNoUpdate) { - RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidNoUpdateTest); -} - -TEST_F(AppCacheUpdateJobTest, StartUpdateMidDownload) { - RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidDownloadTest); -} - -TEST_F(AppCacheUpdateJobTest, QueueMasterEntry) { - RunTestOnIOThread(&AppCacheUpdateJobTest::QueueMasterEntryTest); -} - -TEST_F(AppCacheUpdateJobTest, IfModifiedSince) { - RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceTest); -} - -TEST_F(AppCacheUpdateJobTest, IfModifiedSinceUpgrade) { - RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceUpgradeTest); -} - -TEST_F(AppCacheUpdateJobTest, IfNoneMatchUpgrade) { - RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchUpgradeTest); -} - -TEST_F(AppCacheUpdateJobTest, IfNoneMatchRefetch) { - RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchRefetchTest); -} - -TEST_F(AppCacheUpdateJobTest, MultipleHeadersRefetch) { - RunTestOnIOThread(&AppCacheUpdateJobTest::MultipleHeadersRefetchTest); -} - -TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsSuccess) { - RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsSuccessTest); -} - -TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsDenied) { - RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsDeniedTest); -} - -} // namespace appcache diff --git a/webkit/browser/appcache/appcache_url_request_job.h b/webkit/browser/appcache/appcache_url_request_job.h index 52af0ec..01c80a1 100644 --- a/webkit/browser/appcache/appcache_url_request_job.h +++ b/webkit/browser/appcache/appcache_url_request_job.h @@ -16,6 +16,11 @@ #include "webkit/browser/appcache/appcache_storage.h" #include "webkit/browser/webkit_storage_browser_export.h" +namespace content { +class AppCacheRequestHandlerTest; +class AppCacheURLRequestJobTest; +} + namespace net { class GrowableIOBuffer; }; @@ -92,8 +97,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheURLRequestJob virtual ~AppCacheURLRequestJob(); private: - friend class AppCacheRequestHandlerTest; - friend class AppCacheURLRequestJobTest; + friend class content::AppCacheRequestHandlerTest; + friend class content::AppCacheURLRequestJobTest; enum DeliveryType { AWAITING_DELIVERY_ORDERS, diff --git a/webkit/browser/appcache/appcache_url_request_job_unittest.cc b/webkit/browser/appcache/appcache_url_request_job_unittest.cc deleted file mode 100644 index 4445931..0000000 --- a/webkit/browser/appcache/appcache_url_request_job_unittest.cc +++ /dev/null @@ -1,820 +0,0 @@ -// Copyright (c) 2011 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 <stack> -#include <utility> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/pickle.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/base/request_priority.h" -#include "net/http/http_response_headers.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_error_job.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/browser/appcache/appcache_response.h" -#include "webkit/browser/appcache/appcache_url_request_job.h" -#include "webkit/browser/appcache/mock_appcache_service.h" - -using net::IOBuffer; -using net::WrappedIOBuffer; - -namespace appcache { - -static const char kHttpBasicHeaders[] = - "HTTP/1.0 200 OK\0Content-Length: 5\0\0"; -static const char kHttpBasicBody[] = "Hello"; - -static const int kNumBlocks = 4; -static const int kBlockSize = 1024; - -class AppCacheURLRequestJobTest : public testing::Test { - public: - - // Test Harness ------------------------------------------------------------- - // TODO(michaeln): share this test harness with AppCacheResponseTest - - class MockStorageDelegate : public AppCacheStorage::Delegate { - public: - explicit MockStorageDelegate(AppCacheURLRequestJobTest* test) - : loaded_info_id_(0), test_(test) { - } - - virtual void OnResponseInfoLoaded(AppCacheResponseInfo* info, - int64 response_id) OVERRIDE { - loaded_info_ = info; - loaded_info_id_ = response_id; - test_->ScheduleNextTask(); - } - - scoped_refptr<AppCacheResponseInfo> loaded_info_; - int64 loaded_info_id_; - AppCacheURLRequestJobTest* test_; - }; - - class MockURLRequestDelegate : public net::URLRequest::Delegate { - public: - explicit MockURLRequestDelegate(AppCacheURLRequestJobTest* test) - : test_(test), - received_data_(new net::IOBuffer(kNumBlocks * kBlockSize)), - did_receive_headers_(false), amount_received_(0), - kill_after_amount_received_(0), kill_with_io_pending_(false) { - } - - virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE { - amount_received_ = 0; - did_receive_headers_ = false; - if (request->status().is_success()) { - EXPECT_TRUE(request->response_headers()); - did_receive_headers_ = true; - received_info_ = request->response_info(); - ReadSome(request); - } else { - RequestComplete(); - } - } - - virtual void OnReadCompleted(net::URLRequest* request, - int bytes_read) OVERRIDE { - if (bytes_read > 0) { - amount_received_ += bytes_read; - - if (kill_after_amount_received_ && !kill_with_io_pending_) { - if (amount_received_ >= kill_after_amount_received_) { - request->Cancel(); - return; - } - } - - ReadSome(request); - - if (kill_after_amount_received_ && kill_with_io_pending_) { - if (amount_received_ >= kill_after_amount_received_) { - request->Cancel(); - return; - } - } - } else { - RequestComplete(); - } - } - - void ReadSome(net::URLRequest* request) { - DCHECK(amount_received_ + kBlockSize <= kNumBlocks * kBlockSize); - scoped_refptr<IOBuffer> wrapped_buffer( - new net::WrappedIOBuffer(received_data_->data() + amount_received_)); - int bytes_read = 0; - EXPECT_FALSE( - request->Read(wrapped_buffer.get(), kBlockSize, &bytes_read)); - EXPECT_EQ(0, bytes_read); - } - - void RequestComplete() { - test_->ScheduleNextTask(); - } - - AppCacheURLRequestJobTest* test_; - net::HttpResponseInfo received_info_; - scoped_refptr<net::IOBuffer> received_data_; - bool did_receive_headers_; - int amount_received_; - int kill_after_amount_received_; - bool kill_with_io_pending_; - }; - - static net::URLRequestJob* MockHttpJobFactory( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& scheme) { - if (mock_factory_job_) { - net::URLRequestJob* temp = mock_factory_job_; - mock_factory_job_ = NULL; - return temp; - } else { - return new net::URLRequestErrorJob(request, - network_delegate, - net::ERR_INTERNET_DISCONNECTED); - } - } - - // Helper callback to run a test on our io_thread. The io_thread is spun up - // once and reused for all tests. - template <class Method> - void MethodWrapper(Method method) { - SetUpTest(); - (this->*method)(); - } - - static void SetUpTestCase() { - io_thread_.reset(new base::Thread("AppCacheURLRequestJobTest Thread")); - base::Thread::Options options(base::MessageLoop::TYPE_IO, 0); - io_thread_->StartWithOptions(options); - } - - static void TearDownTestCase() { - io_thread_.reset(NULL); - } - - AppCacheURLRequestJobTest() {} - - template <class Method> - void RunTestOnIOThread(Method method) { - test_finished_event_ .reset(new base::WaitableEvent(false, false)); - io_thread_->message_loop()->PostTask( - FROM_HERE, base::Bind(&AppCacheURLRequestJobTest::MethodWrapper<Method>, - base::Unretained(this), method)); - test_finished_event_->Wait(); - } - - void SetUpTest() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); - DCHECK(task_stack_.empty()); - orig_http_factory_ = net::URLRequest::Deprecated::RegisterProtocolFactory( - "http", MockHttpJobFactory); - url_request_delegate_.reset(new MockURLRequestDelegate(this)); - storage_delegate_.reset(new MockStorageDelegate(this)); - service_.reset(new MockAppCacheService()); - expected_read_result_ = 0; - expected_write_result_ = 0; - written_response_id_ = 0; - reader_deletion_count_down_ = 0; - writer_deletion_count_down_ = 0; - } - - void TearDownTest() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); - net::URLRequest::Deprecated::RegisterProtocolFactory("http", - orig_http_factory_); - orig_http_factory_ = NULL; - request_.reset(); - url_request_delegate_.reset(); - DCHECK(!mock_factory_job_); - - while (!task_stack_.empty()) - task_stack_.pop(); - - reader_.reset(); - read_buffer_ = NULL; - read_info_buffer_ = NULL; - writer_.reset(); - write_buffer_ = NULL; - write_info_buffer_ = NULL; - storage_delegate_.reset(); - service_.reset(); - } - - void TestFinished() { - // We unwind the stack prior to finishing up to let stack - // based objects get deleted. - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&AppCacheURLRequestJobTest::TestFinishedUnwound, - base::Unretained(this))); - } - - void TestFinishedUnwound() { - TearDownTest(); - test_finished_event_->Signal(); - } - - void PushNextTask(const base::Closure& task) { - task_stack_.push(std::pair<base::Closure, bool>(task, false)); - } - - void PushNextTaskAsImmediate(const base::Closure& task) { - task_stack_.push(std::pair<base::Closure, bool>(task, true)); - } - - void ScheduleNextTask() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); - if (task_stack_.empty()) { - TestFinished(); - return; - } - base::Closure task =task_stack_.top().first; - bool immediate = task_stack_.top().second; - task_stack_.pop(); - if (immediate) - task.Run(); - else - base::MessageLoop::current()->PostTask(FROM_HERE, task); - } - - // Wrappers to call AppCacheResponseReader/Writer Read and Write methods - - void WriteBasicResponse() { - scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBasicBody)); - std::string raw_headers(kHttpBasicHeaders, arraysize(kHttpBasicHeaders)); - WriteResponse( - MakeHttpResponseInfo(raw_headers), body.get(), strlen(kHttpBasicBody)); - } - - void WriteResponse(net::HttpResponseInfo* head, - IOBuffer* body, int body_len) { - DCHECK(body); - scoped_refptr<IOBuffer> body_ref(body); - PushNextTask(base::Bind(&AppCacheURLRequestJobTest::WriteResponseBody, - base::Unretained(this), body_ref, body_len)); - WriteResponseHead(head); - } - - void WriteResponseHead(net::HttpResponseInfo* head) { - EXPECT_FALSE(writer_->IsWritePending()); - expected_write_result_ = GetHttpResponseInfoSize(head); - write_info_buffer_ = new HttpResponseInfoIOBuffer(head); - writer_->WriteInfo( - write_info_buffer_.get(), - base::Bind(&AppCacheURLRequestJobTest::OnWriteInfoComplete, - base::Unretained(this))); - } - - void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) { - EXPECT_FALSE(writer_->IsWritePending()); - write_buffer_ = io_buffer; - expected_write_result_ = buf_len; - writer_->WriteData(write_buffer_.get(), - buf_len, - base::Bind(&AppCacheURLRequestJobTest::OnWriteComplete, - base::Unretained(this))); - } - - void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer, int buf_len) { - EXPECT_FALSE(reader_->IsReadPending()); - read_buffer_ = io_buffer; - expected_read_result_ = buf_len; - reader_->ReadData(read_buffer_.get(), - buf_len, - base::Bind(&AppCacheURLRequestJobTest::OnReadComplete, - base::Unretained(this))); - } - - // AppCacheResponseReader / Writer completion callbacks - - void OnWriteInfoComplete(int result) { - EXPECT_FALSE(writer_->IsWritePending()); - EXPECT_EQ(expected_write_result_, result); - ScheduleNextTask(); - } - - void OnWriteComplete(int result) { - EXPECT_FALSE(writer_->IsWritePending()); - EXPECT_EQ(expected_write_result_, result); - ScheduleNextTask(); - } - - void OnReadInfoComplete(int result) { - EXPECT_FALSE(reader_->IsReadPending()); - EXPECT_EQ(expected_read_result_, result); - ScheduleNextTask(); - } - - void OnReadComplete(int result) { - EXPECT_FALSE(reader_->IsReadPending()); - EXPECT_EQ(expected_read_result_, result); - ScheduleNextTask(); - } - - // Helpers to work with HttpResponseInfo objects - - net::HttpResponseInfo* MakeHttpResponseInfo(const std::string& raw_headers) { - net::HttpResponseInfo* info = new net::HttpResponseInfo; - info->request_time = base::Time::Now(); - info->response_time = base::Time::Now(); - info->was_cached = false; - info->headers = new net::HttpResponseHeaders(raw_headers); - return info; - } - - int GetHttpResponseInfoSize(const net::HttpResponseInfo* info) { - Pickle pickle; - return PickleHttpResonseInfo(&pickle, info); - } - - bool CompareHttpResponseInfos(const net::HttpResponseInfo* info1, - const net::HttpResponseInfo* info2) { - Pickle pickle1; - Pickle pickle2; - PickleHttpResonseInfo(&pickle1, info1); - PickleHttpResonseInfo(&pickle2, info2); - return (pickle1.size() == pickle2.size()) && - (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size())); - } - - int PickleHttpResonseInfo(Pickle* pickle, const net::HttpResponseInfo* info) { - const bool kSkipTransientHeaders = true; - const bool kTruncated = false; - info->Persist(pickle, kSkipTransientHeaders, kTruncated); - return pickle->size(); - } - - // Helpers to fill and verify blocks of memory with a value - - void FillData(char value, char* data, int data_len) { - memset(data, value, data_len); - } - - bool CheckData(char value, const char* data, int data_len) { - for (int i = 0; i < data_len; ++i, ++data) { - if (*data != value) - return false; - } - return true; - } - - // Individual Tests --------------------------------------------------------- - // Some of the individual tests involve multiple async steps. Each test - // is delineated with a section header. - - // Basic ------------------------------------------------------------------- - void Basic() { - AppCacheStorage* storage = service_->storage(); - net::URLRequest request( - GURL("http://blah/"), net::DEFAULT_PRIORITY, NULL, &empty_context_); - scoped_refptr<AppCacheURLRequestJob> job; - - // Create an instance and see that it looks as expected. - - job = new AppCacheURLRequestJob( - &request, NULL, storage, NULL, false); - EXPECT_TRUE(job->is_waiting()); - EXPECT_FALSE(job->is_delivering_appcache_response()); - EXPECT_FALSE(job->is_delivering_network_response()); - EXPECT_FALSE(job->is_delivering_error_response()); - EXPECT_FALSE(job->has_been_started()); - EXPECT_FALSE(job->has_been_killed()); - EXPECT_EQ(GURL(), job->manifest_url()); - EXPECT_EQ(kNoCacheId, job->cache_id()); - EXPECT_FALSE(job->entry().has_response_id()); - - TestFinished(); - } - - // DeliveryOrders ----------------------------------------------------- - void DeliveryOrders() { - AppCacheStorage* storage = service_->storage(); - net::URLRequest request( - GURL("http://blah/"), net::DEFAULT_PRIORITY, NULL, &empty_context_); - scoped_refptr<AppCacheURLRequestJob> job; - - // Create an instance, give it a delivery order and see that - // it looks as expected. - - job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false); - job->DeliverErrorResponse(); - EXPECT_TRUE(job->is_delivering_error_response()); - EXPECT_FALSE(job->has_been_started()); - - job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false); - job->DeliverNetworkResponse(); - EXPECT_TRUE(job->is_delivering_network_response()); - EXPECT_FALSE(job->has_been_started()); - - job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false); - const GURL kManifestUrl("http://blah/"); - const int64 kCacheId(1); - const int64 kGroupId(1); - const AppCacheEntry kEntry(AppCacheEntry::EXPLICIT, 1); - job->DeliverAppCachedResponse(kManifestUrl, kCacheId, kGroupId, - kEntry, false); - EXPECT_FALSE(job->is_waiting()); - EXPECT_TRUE(job->is_delivering_appcache_response()); - EXPECT_FALSE(job->has_been_started()); - EXPECT_EQ(kManifestUrl, job->manifest_url()); - EXPECT_EQ(kCacheId, job->cache_id()); - EXPECT_EQ(kGroupId, job->group_id()); - EXPECT_EQ(kEntry.types(), job->entry().types()); - EXPECT_EQ(kEntry.response_id(), job->entry().response_id()); - - TestFinished(); - } - - // DeliverNetworkResponse -------------------------------------------------- - - void DeliverNetworkResponse() { - // This test has async steps. - PushNextTask( - base::Bind(&AppCacheURLRequestJobTest::VerifyDeliverNetworkResponse, - base::Unretained(this))); - - AppCacheStorage* storage = service_->storage(); - request_ = empty_context_.CreateRequest(GURL("http://blah/"), - net::DEFAULT_PRIORITY, - url_request_delegate_.get(), - NULL); - - // Setup to create an AppCacheURLRequestJob with orders to deliver - // a network response. - mock_factory_job_ = new AppCacheURLRequestJob( - request_.get(), NULL, storage, NULL, false); - mock_factory_job_->DeliverNetworkResponse(); - EXPECT_TRUE(mock_factory_job_->is_delivering_network_response()); - EXPECT_FALSE(mock_factory_job_->has_been_started()); - - // Start the request. - request_->Start(); - - // The job should have been picked up. - EXPECT_FALSE(mock_factory_job_); - // Completion is async. - } - - void VerifyDeliverNetworkResponse() { - EXPECT_EQ(request_->status().error(), - net::ERR_INTERNET_DISCONNECTED); - TestFinished(); - } - - // DeliverErrorResponse -------------------------------------------------- - - void DeliverErrorResponse() { - // This test has async steps. - PushNextTask( - base::Bind(&AppCacheURLRequestJobTest::VerifyDeliverErrorResponse, - base::Unretained(this))); - - AppCacheStorage* storage = service_->storage(); - request_ = empty_context_.CreateRequest(GURL("http://blah/"), - net::DEFAULT_PRIORITY, - url_request_delegate_.get(), - NULL); - - // Setup to create an AppCacheURLRequestJob with orders to deliver - // a network response. - mock_factory_job_ = new AppCacheURLRequestJob( - request_.get(), NULL, storage, NULL, false); - mock_factory_job_->DeliverErrorResponse(); - EXPECT_TRUE(mock_factory_job_->is_delivering_error_response()); - EXPECT_FALSE(mock_factory_job_->has_been_started()); - - // Start the request. - request_->Start(); - - // The job should have been picked up. - EXPECT_FALSE(mock_factory_job_); - // Completion is async. - } - - void VerifyDeliverErrorResponse() { - EXPECT_EQ(request_->status().error(), net::ERR_FAILED); - TestFinished(); - } - - // DeliverSmallAppCachedResponse -------------------------------------- - // "Small" being small enough to read completely in a single - // request->Read call. - - void DeliverSmallAppCachedResponse() { - // This test has several async steps. - // 1. Write a small response to response storage. - // 2. Use net::URLRequest to retrieve it. - // 3. Verify we received what we expected to receive. - - PushNextTask(base::Bind( - &AppCacheURLRequestJobTest::VerifyDeliverSmallAppCachedResponse, - base::Unretained(this))); - PushNextTask( - base::Bind(&AppCacheURLRequestJobTest::RequestAppCachedResource, - base::Unretained(this), false)); - - writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0)); - written_response_id_ = writer_->response_id(); - WriteBasicResponse(); - // Continues async - } - - void RequestAppCachedResource(bool start_after_delivery_orders) { - AppCacheStorage* storage = service_->storage(); - request_ = empty_context_.CreateRequest(GURL("http://blah/"), - net::DEFAULT_PRIORITY, - url_request_delegate_.get(), - NULL); - - // Setup to create an AppCacheURLRequestJob with orders to deliver - // a network response. - scoped_refptr<AppCacheURLRequestJob> job(new AppCacheURLRequestJob( - request_.get(), NULL, storage, NULL, false)); - - if (start_after_delivery_orders) { - job->DeliverAppCachedResponse( - GURL(), 0, 111, - AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_), - false); - EXPECT_TRUE(job->is_delivering_appcache_response()); - } - - // Start the request. - EXPECT_FALSE(job->has_been_started()); - mock_factory_job_ = job.get(); - request_->Start(); - EXPECT_FALSE(mock_factory_job_); - EXPECT_TRUE(job->has_been_started()); - - if (!start_after_delivery_orders) { - job->DeliverAppCachedResponse( - GURL(), 0, 111, - AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_), - false); - EXPECT_TRUE(job->is_delivering_appcache_response()); - } - - // Completion is async. - } - - void VerifyDeliverSmallAppCachedResponse() { - EXPECT_TRUE(request_->status().is_success()); - EXPECT_TRUE(CompareHttpResponseInfos( - write_info_buffer_->http_info.get(), - &url_request_delegate_->received_info_)); - EXPECT_EQ(5, url_request_delegate_->amount_received_); - EXPECT_EQ(0, memcmp(kHttpBasicBody, - url_request_delegate_->received_data_->data(), - strlen(kHttpBasicBody))); - TestFinished(); - } - - // DeliverLargeAppCachedResponse -------------------------------------- - // "Large" enough to require multiple calls to request->Read to complete. - - void DeliverLargeAppCachedResponse() { - // This test has several async steps. - // 1. Write a large response to response storage. - // 2. Use net::URLRequest to retrieve it. - // 3. Verify we received what we expected to receive. - - PushNextTask(base::Bind( - &AppCacheURLRequestJobTest::VerifyDeliverLargeAppCachedResponse, - base::Unretained(this))); - PushNextTask(base::Bind( - &AppCacheURLRequestJobTest::RequestAppCachedResource, - base::Unretained(this), true)); - - writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0)); - written_response_id_ = writer_->response_id(); - WriteLargeResponse(); - // Continues async - } - - void WriteLargeResponse() { - // 3, 1k blocks - static const char kHttpHeaders[] = - "HTTP/1.0 200 OK\0Content-Length: 3072\0\0"; - scoped_refptr<IOBuffer> body(new IOBuffer(kBlockSize * 3)); - char* p = body->data(); - for (int i = 0; i < 3; ++i, p += kBlockSize) - FillData(i + 1, p, kBlockSize); - std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders)); - WriteResponse( - MakeHttpResponseInfo(raw_headers), body.get(), kBlockSize * 3); - } - - void VerifyDeliverLargeAppCachedResponse() { - EXPECT_TRUE(request_->status().is_success()); - EXPECT_TRUE(CompareHttpResponseInfos( - write_info_buffer_->http_info.get(), - &url_request_delegate_->received_info_)); - EXPECT_EQ(3072, url_request_delegate_->amount_received_); - char* p = url_request_delegate_->received_data_->data(); - for (int i = 0; i < 3; ++i, p += kBlockSize) - EXPECT_TRUE(CheckData(i + 1, p, kBlockSize)); - TestFinished(); - } - - // DeliverPartialResponse -------------------------------------- - - void DeliverPartialResponse() { - // This test has several async steps. - // 1. Write a small response to response storage. - // 2. Use net::URLRequest to retrieve it a subset using a range request - // 3. Verify we received what we expected to receive. - PushNextTask(base::Bind( - &AppCacheURLRequestJobTest::VerifyDeliverPartialResponse, - base::Unretained(this))); - PushNextTask(base::Bind( - &AppCacheURLRequestJobTest::MakeRangeRequest, base::Unretained(this))); - writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0)); - written_response_id_ = writer_->response_id(); - WriteBasicResponse(); - // Continues async - } - - void MakeRangeRequest() { - AppCacheStorage* storage = service_->storage(); - request_ = empty_context_.CreateRequest(GURL("http://blah/"), - net::DEFAULT_PRIORITY, - url_request_delegate_.get(), - NULL); - - // Request a range, the 3 middle chars out of 'Hello' - net::HttpRequestHeaders extra_headers; - extra_headers.SetHeader("Range", "bytes= 1-3"); - request_->SetExtraRequestHeaders(extra_headers); - - // Create job with orders to deliver an appcached entry. - scoped_refptr<AppCacheURLRequestJob> job(new AppCacheURLRequestJob( - request_.get(), NULL, storage, NULL, false)); - job->DeliverAppCachedResponse( - GURL(), 0, 111, - AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_), - false); - EXPECT_TRUE(job->is_delivering_appcache_response()); - - // Start the request. - EXPECT_FALSE(job->has_been_started()); - mock_factory_job_ = job.get(); - request_->Start(); - EXPECT_FALSE(mock_factory_job_); - EXPECT_TRUE(job->has_been_started()); - // Completion is async. - } - - void VerifyDeliverPartialResponse() { - EXPECT_TRUE(request_->status().is_success()); - EXPECT_EQ(3, url_request_delegate_->amount_received_); - EXPECT_EQ(0, memcmp(kHttpBasicBody + 1, - url_request_delegate_->received_data_->data(), - 3)); - net::HttpResponseHeaders* headers = - url_request_delegate_->received_info_.headers.get(); - EXPECT_EQ(206, headers->response_code()); - EXPECT_EQ(3, headers->GetContentLength()); - int64 range_start, range_end, object_size; - EXPECT_TRUE( - headers->GetContentRange(&range_start, &range_end, &object_size)); - EXPECT_EQ(1, range_start); - EXPECT_EQ(3, range_end); - EXPECT_EQ(5, object_size); - TestFinished(); - } - - // CancelRequest -------------------------------------- - - void CancelRequest() { - // This test has several async steps. - // 1. Write a large response to response storage. - // 2. Use net::URLRequest to retrieve it. - // 3. Cancel the request after data starts coming in. - - PushNextTask(base::Bind( - &AppCacheURLRequestJobTest::VerifyCancel, base::Unretained(this))); - PushNextTask(base::Bind( - &AppCacheURLRequestJobTest::RequestAppCachedResource, - base::Unretained(this), true)); - - writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0)); - written_response_id_ = writer_->response_id(); - WriteLargeResponse(); - - url_request_delegate_->kill_after_amount_received_ = kBlockSize; - url_request_delegate_->kill_with_io_pending_ = false; - // Continues async - } - - void VerifyCancel() { - EXPECT_EQ(net::URLRequestStatus::CANCELED, - request_->status().status()); - TestFinished(); - } - - // CancelRequestWithIOPending -------------------------------------- - - void CancelRequestWithIOPending() { - // This test has several async steps. - // 1. Write a large response to response storage. - // 2. Use net::URLRequest to retrieve it. - // 3. Cancel the request after data starts coming in. - - PushNextTask(base::Bind( - &AppCacheURLRequestJobTest::VerifyCancel, base::Unretained(this))); - PushNextTask(base::Bind( - &AppCacheURLRequestJobTest::RequestAppCachedResource, - base::Unretained(this), true)); - - writer_.reset(service_->storage()->CreateResponseWriter(GURL(), 0)); - written_response_id_ = writer_->response_id(); - WriteLargeResponse(); - - url_request_delegate_->kill_after_amount_received_ = kBlockSize; - url_request_delegate_->kill_with_io_pending_ = true; - // Continues async - } - - - // Data members -------------------------------------------------------- - - scoped_ptr<base::WaitableEvent> test_finished_event_; - scoped_ptr<MockStorageDelegate> storage_delegate_; - scoped_ptr<MockAppCacheService> service_; - std::stack<std::pair<base::Closure, bool> > task_stack_; - - scoped_ptr<AppCacheResponseReader> reader_; - scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_; - scoped_refptr<IOBuffer> read_buffer_; - int expected_read_result_; - int reader_deletion_count_down_; - - int64 written_response_id_; - scoped_ptr<AppCacheResponseWriter> writer_; - scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_; - scoped_refptr<IOBuffer> write_buffer_; - int expected_write_result_; - int writer_deletion_count_down_; - - net::URLRequest::ProtocolFactory* orig_http_factory_; - net::URLRequestContext empty_context_; - scoped_ptr<net::URLRequest> request_; - scoped_ptr<MockURLRequestDelegate> url_request_delegate_; - - static scoped_ptr<base::Thread> io_thread_; - static AppCacheURLRequestJob* mock_factory_job_; -}; - -// static -scoped_ptr<base::Thread> AppCacheURLRequestJobTest::io_thread_; -AppCacheURLRequestJob* AppCacheURLRequestJobTest::mock_factory_job_ = NULL; - -TEST_F(AppCacheURLRequestJobTest, Basic) { - RunTestOnIOThread(&AppCacheURLRequestJobTest::Basic); -} - -TEST_F(AppCacheURLRequestJobTest, DeliveryOrders) { - RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliveryOrders); -} - -TEST_F(AppCacheURLRequestJobTest, DeliverNetworkResponse) { - RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverNetworkResponse); -} - -TEST_F(AppCacheURLRequestJobTest, DeliverErrorResponse) { - RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverErrorResponse); -} - -TEST_F(AppCacheURLRequestJobTest, DeliverSmallAppCachedResponse) { - RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverSmallAppCachedResponse); -} - -TEST_F(AppCacheURLRequestJobTest, DeliverLargeAppCachedResponse) { - RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverLargeAppCachedResponse); -} - -TEST_F(AppCacheURLRequestJobTest, DeliverPartialResponse) { - RunTestOnIOThread(&AppCacheURLRequestJobTest::DeliverPartialResponse); -} - -TEST_F(AppCacheURLRequestJobTest, CancelRequest) { - RunTestOnIOThread(&AppCacheURLRequestJobTest::CancelRequest); -} - -TEST_F(AppCacheURLRequestJobTest, CancelRequestWithIOPending) { - RunTestOnIOThread(&AppCacheURLRequestJobTest::CancelRequestWithIOPending); -} - -} // namespace appcache diff --git a/webkit/browser/appcache/manifest_parser_unittest.cc b/webkit/browser/appcache/manifest_parser_unittest.cc deleted file mode 100644 index 4df076f..0000000 --- a/webkit/browser/appcache/manifest_parser_unittest.cc +++ /dev/null @@ -1,472 +0,0 @@ -// Copyright (c) 2010 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 "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" -#include "webkit/browser/appcache/manifest_parser.h" - -namespace appcache { - -class AppCacheManifestParserTest : public testing::Test { -}; - -TEST(AppCacheManifestParserTest, NoData) { - GURL url; - Manifest manifest; - EXPECT_FALSE(ParseManifest(url, "", 0, manifest)); - EXPECT_FALSE(ParseManifest(url, "CACHE MANIFEST\r", 0, manifest)); // 0 len -} - -TEST(AppCacheManifestParserTest, CheckSignature) { - GURL url; - Manifest manifest; - - const std::string kBadSignatures[] = { - "foo", - "CACHE MANIFEST;V2\r", // not followed by whitespace - "CACHE MANIFEST#bad\r", // no whitespace before comment - "cache manifest ", // wrong case - "#CACHE MANIFEST\r", // comment - "xCACHE MANIFEST\n", // bad first char - " CACHE MANIFEST\r", // begins with whitespace - "\xEF\xBE\xBF" "CACHE MANIFEST\r", // bad UTF-8 BOM value - }; - - for (size_t i = 0; i < arraysize(kBadSignatures); ++i) { - const std::string bad = kBadSignatures[i]; - EXPECT_FALSE(ParseManifest(url, bad.c_str(), bad.length(), manifest)); - } - - const std::string kGoodSignatures[] = { - "CACHE MANIFEST", - "CACHE MANIFEST ", - "CACHE MANIFEST\r", - "CACHE MANIFEST\n", - "CACHE MANIFEST\r\n", - "CACHE MANIFEST\t# ignore me\r", - "CACHE MANIFEST ignore\r\n", - "CHROMIUM CACHE MANIFEST\r\n", - "\xEF\xBB\xBF" "CACHE MANIFEST \r\n", // BOM present - }; - - for (size_t i = 0; i < arraysize(kGoodSignatures); ++i) { - const std::string good = kGoodSignatures[i]; - EXPECT_TRUE(ParseManifest(url, good.c_str(), good.length(), manifest)); - } -} - -TEST(AppCacheManifestParserTest, NoManifestUrl) { - Manifest manifest; - const std::string kData("CACHE MANIFEST\r" - "relative/tobase.com\r" - "http://absolute.com/addme.com"); - const GURL kUrl; - EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); - EXPECT_TRUE(manifest.explicit_urls.empty()); - EXPECT_TRUE(manifest.fallback_namespaces.empty()); - EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); - EXPECT_FALSE(manifest.online_whitelist_all); -} - -TEST(AppCacheManifestParserTest, ExplicitUrls) { - Manifest manifest; - const GURL kUrl("http://www.foo.com"); - const std::string kData("CACHE MANIFEST\r" - "relative/one\r" - "# some comment\r" - "http://www.foo.com/two#strip\r\n" - "NETWORK:\r" - " \t CACHE:\r" - "HTTP://www.diff.com/three\r" - "FALLBACK:\r" - " \t # another comment with leading whitespace\n" - "IGNORE:\r" - "http://www.foo.com/ignore\r" - "CACHE: \r" - "garbage:#!@\r" - "https://www.foo.com/diffscheme \t \r" - " \t relative/four#stripme\n\r" - "*\r"); - - EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); - EXPECT_TRUE(manifest.fallback_namespaces.empty()); - EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); - EXPECT_FALSE(manifest.online_whitelist_all); - - base::hash_set<std::string> urls = manifest.explicit_urls; - const size_t kExpected = 5; - ASSERT_EQ(kExpected, urls.size()); - EXPECT_TRUE(urls.find("http://www.foo.com/relative/one") != urls.end()); - EXPECT_TRUE(urls.find("http://www.foo.com/two") != urls.end()); - EXPECT_TRUE(urls.find("http://www.diff.com/three") != urls.end()); - EXPECT_TRUE(urls.find("http://www.foo.com/relative/four") != urls.end()); - - // Wildcard is treated as a relative URL in explicit section. - EXPECT_TRUE(urls.find("http://www.foo.com/*") != urls.end()); -} - -TEST(AppCacheManifestParserTest, WhitelistUrls) { - Manifest manifest; - const GURL kUrl("http://www.bar.com"); - const std::string kData("CACHE MANIFEST\r" - "NETWORK:\r" - "relative/one\r" - "# a comment\r" - "http://www.bar.com/two\r" - "HTTP://www.diff.com/three#strip\n\r" - "FALLBACK:\r" - "garbage\r" - "UNKNOWN:\r" - "http://www.bar.com/ignore\r" - "CACHE:\r" - "NETWORK:\r" - "https://www.wrongscheme.com\n" - "relative/four#stripref \t \r" - "http://www.five.com\r\n" - "*foo\r"); - - EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); - EXPECT_TRUE(manifest.explicit_urls.empty()); - EXPECT_TRUE(manifest.fallback_namespaces.empty()); - EXPECT_TRUE(manifest.intercept_namespaces.empty()); - EXPECT_FALSE(manifest.online_whitelist_all); - - const NamespaceVector& online = manifest.online_whitelist_namespaces; - const size_t kExpected = 6; - ASSERT_EQ(kExpected, online.size()); - EXPECT_EQ(NETWORK_NAMESPACE, online[0].type); - EXPECT_FALSE(online[0].is_pattern); - EXPECT_TRUE(online[0].target_url.is_empty()); - EXPECT_EQ(GURL("http://www.bar.com/relative/one"), online[0].namespace_url); - EXPECT_EQ(GURL("http://www.bar.com/two"), online[1].namespace_url); - EXPECT_EQ(GURL("http://www.diff.com/three"), online[2].namespace_url); - EXPECT_EQ(GURL("http://www.bar.com/relative/four"), online[3].namespace_url); - EXPECT_EQ(GURL("http://www.five.com"), online[4].namespace_url); - EXPECT_EQ(GURL("http://www.bar.com/*foo"), online[5].namespace_url); -} - -TEST(AppCacheManifestParserTest, FallbackUrls) { - Manifest manifest; - const GURL kUrl("http://glorp.com"); - const std::string kData("CACHE MANIFEST\r" - "# a comment\r" - "CACHE:\r" - "NETWORK:\r" - "UNKNOWN:\r" - "FALLBACK:\r" - "relative/one \t \t http://glorp.com/onefb \t \r" - "*\r" - "https://glorp.com/wrong http://glorp.com/wrongfb\r" - "http://glorp.com/two#strip relative/twofb\r" - "HTTP://glorp.com/three relative/threefb#strip\n" - "http://glorp.com/three http://glorp.com/three-dup\r" - "http://glorp.com/solo \t \r\n" - "http://diff.com/ignore http://glorp.com/wronghost\r" - "http://glorp.com/wronghost http://diff.com/ohwell\r" - "relative/badscheme ftp://glorp.com/ignored\r" - "garbage\r\n" - "CACHE:\r" - "# only fallback urls in this test\r" - "FALLBACK:\n" - "relative/four#strip relative/fourfb#strip\r" - "http://www.glorp.com/notsame relative/skipped\r"); - - EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); - EXPECT_TRUE(manifest.explicit_urls.empty()); - EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); - EXPECT_FALSE(manifest.online_whitelist_all); - - const NamespaceVector& fallbacks = manifest.fallback_namespaces; - const size_t kExpected = 5; - ASSERT_EQ(kExpected, fallbacks.size()); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[0].type); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[1].type); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[2].type); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[3].type); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[4].type); - EXPECT_EQ(GURL("http://glorp.com/relative/one"), - fallbacks[0].namespace_url); - EXPECT_EQ(GURL("http://glorp.com/onefb"), - fallbacks[0].target_url); - EXPECT_EQ(GURL("http://glorp.com/two"), - fallbacks[1].namespace_url); - EXPECT_EQ(GURL("http://glorp.com/relative/twofb"), - fallbacks[1].target_url); - EXPECT_EQ(GURL("http://glorp.com/three"), - fallbacks[2].namespace_url); - EXPECT_EQ(GURL("http://glorp.com/relative/threefb"), - fallbacks[2].target_url); - EXPECT_EQ(GURL("http://glorp.com/three"), // duplicates are stored - fallbacks[3].namespace_url); - EXPECT_EQ(GURL("http://glorp.com/three-dup"), - fallbacks[3].target_url); - EXPECT_EQ(GURL("http://glorp.com/relative/four"), - fallbacks[4].namespace_url); - EXPECT_EQ(GURL("http://glorp.com/relative/fourfb"), - fallbacks[4].target_url); - - EXPECT_TRUE(manifest.intercept_namespaces.empty()); -} - -TEST(AppCacheManifestParserTest, FallbackUrlsWithPort) { - Manifest manifest; - const GURL kUrl("http://www.portme.com:1234"); - const std::string kData("CACHE MANIFEST\r" - "FALLBACK:\r" - "http://www.portme.com:1234/one relative/onefb\r" - "HTTP://www.portme.com:9876/wrong http://www.portme.com:1234/ignore\r" - "http://www.portme.com:1234/stillwrong http://www.portme.com:42/boo\r" - "relative/two relative/twofb\r" - "http://www.portme.com:1234/three HTTP://www.portme.com:1234/threefb\r" - "http://www.portme.com/noport http://www.portme.com:1234/skipped\r" - "http://www.portme.com:1234/skipme http://www.portme.com/noport\r"); - - EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); - EXPECT_TRUE(manifest.explicit_urls.empty()); - EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); - EXPECT_FALSE(manifest.online_whitelist_all); - - const NamespaceVector& fallbacks = manifest.fallback_namespaces; - const size_t kExpected = 3; - ASSERT_EQ(kExpected, fallbacks.size()); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[0].type); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[1].type); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[2].type); - EXPECT_EQ(GURL("http://www.portme.com:1234/one"), - fallbacks[0].namespace_url); - EXPECT_EQ(GURL("http://www.portme.com:1234/relative/onefb"), - fallbacks[0].target_url); - EXPECT_EQ(GURL("http://www.portme.com:1234/relative/two"), - fallbacks[1].namespace_url); - EXPECT_EQ(GURL("http://www.portme.com:1234/relative/twofb"), - fallbacks[1].target_url); - EXPECT_EQ(GURL("http://www.portme.com:1234/three"), - fallbacks[2].namespace_url); - EXPECT_EQ(GURL("http://www.portme.com:1234/threefb"), - fallbacks[2].target_url); - - EXPECT_TRUE(manifest.intercept_namespaces.empty()); -} - -TEST(AppCacheManifestParserTest, InterceptUrls) { - Manifest manifest; - const GURL kUrl("http://www.portme.com:1234"); - const std::string kData("CHROMIUM CACHE MANIFEST\r" - "CHROMIUM-INTERCEPT:\r" - "http://www.portme.com:1234/one return relative/int1\r" - "HTTP://www.portme.com:9/wrong return http://www.portme.com:1234/ignore\r" - "http://www.portme.com:1234/wrong return http://www.portme.com:9/boo\r" - "relative/two return relative/int2\r" - "relative/three wrong relative/threefb\r" - "http://www.portme.com:1234/three return HTTP://www.portme.com:1234/int3\r" - "http://www.portme.com/noport return http://www.portme.com:1234/skipped\r" - "http://www.portme.com:1234/skipme return http://www.portme.com/noport\r" - "relative/wrong/again missing/intercept_type\r"); - - EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); - EXPECT_TRUE(manifest.fallback_namespaces.empty()); - EXPECT_TRUE(manifest.explicit_urls.empty()); - EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); - EXPECT_FALSE(manifest.online_whitelist_all); - - const NamespaceVector& intercepts = manifest.intercept_namespaces; - const size_t kExpected = 3; - ASSERT_EQ(kExpected, intercepts.size()); - EXPECT_EQ(INTERCEPT_NAMESPACE, intercepts[0].type); - EXPECT_EQ(INTERCEPT_NAMESPACE, intercepts[1].type); - EXPECT_EQ(INTERCEPT_NAMESPACE, intercepts[2].type); - EXPECT_EQ(GURL("http://www.portme.com:1234/one"), - intercepts[0].namespace_url); - EXPECT_EQ(GURL("http://www.portme.com:1234/relative/int1"), - intercepts[0].target_url); - EXPECT_EQ(GURL("http://www.portme.com:1234/relative/two"), - intercepts[1].namespace_url); - EXPECT_EQ(GURL("http://www.portme.com:1234/relative/int2"), - intercepts[1].target_url); - EXPECT_EQ(GURL("http://www.portme.com:1234/three"), - intercepts[2].namespace_url); - EXPECT_EQ(GURL("http://www.portme.com:1234/int3"), - intercepts[2].target_url); -} - -TEST(AppCacheManifestParserTest, ComboUrls) { - Manifest manifest; - const GURL kUrl("http://combo.com:42"); - const std::string kData("CACHE MANIFEST\r" - "relative/explicit-1\r" - "# some comment\r" - "http://combo.com:99/explicit-2#strip\r" - "NETWORK:\r" - "http://combo.com/whitelist-1\r" - "HTTP://www.diff.com/whitelist-2#strip\r" - "*\r" - "CACHE:\n\r" - "http://www.diff.com/explicit-3\r" - "FALLBACK:\r" - "http://combo.com:42/fallback-1 http://combo.com:42/fallback-1b\r" - "relative/fallback-2 relative/fallback-2b\r" - "UNKNOWN:\r\n" - "http://combo.com/ignoreme\r" - "relative/still-ignored\r" - "NETWORK:\r\n" - "relative/whitelist-3#strip\r" - "http://combo.com:99/whitelist-4\r"); - EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); - EXPECT_TRUE(manifest.online_whitelist_all); - - base::hash_set<std::string> urls = manifest.explicit_urls; - size_t expected = 3; - ASSERT_EQ(expected, urls.size()); - EXPECT_TRUE(urls.find("http://combo.com:42/relative/explicit-1") != - urls.end()); - EXPECT_TRUE(urls.find("http://combo.com:99/explicit-2") != urls.end()); - EXPECT_TRUE(urls.find("http://www.diff.com/explicit-3") != urls.end()); - - const NamespaceVector& online = manifest.online_whitelist_namespaces; - expected = 4; - ASSERT_EQ(expected, online.size()); - EXPECT_EQ(GURL("http://combo.com/whitelist-1"), - online[0].namespace_url); - EXPECT_EQ(GURL("http://www.diff.com/whitelist-2"), - online[1].namespace_url); - EXPECT_EQ(GURL("http://combo.com:42/relative/whitelist-3"), - online[2].namespace_url); - EXPECT_EQ(GURL("http://combo.com:99/whitelist-4"), - online[3].namespace_url); - - const NamespaceVector& fallbacks = manifest.fallback_namespaces; - expected = 2; - ASSERT_EQ(expected, fallbacks.size()); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[0].type); - EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[1].type); - EXPECT_EQ(GURL("http://combo.com:42/fallback-1"), - fallbacks[0].namespace_url); - EXPECT_EQ(GURL("http://combo.com:42/fallback-1b"), - fallbacks[0].target_url); - EXPECT_EQ(GURL("http://combo.com:42/relative/fallback-2"), - fallbacks[1].namespace_url); - EXPECT_EQ(GURL("http://combo.com:42/relative/fallback-2b"), - fallbacks[1].target_url); - - EXPECT_TRUE(manifest.intercept_namespaces.empty()); -} - -TEST(AppCacheManifestParserTest, UnusualUtf8) { - Manifest manifest; - const GURL kUrl("http://bad.com"); - const std::string kData("CACHE MANIFEST\r" - "\xC0" "invalidutf8\r" - "nonbmp" "\xF1\x84\xAB\xBC\r"); - EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); - - base::hash_set<std::string> urls = manifest.explicit_urls; - EXPECT_TRUE(urls.find("http://bad.com/%EF%BF%BDinvalidutf8") != urls.end()); - EXPECT_TRUE(urls.find("http://bad.com/nonbmp%F1%84%AB%BC") != urls.end()); -} - -TEST(AppCacheManifestParserTest, IgnoreAfterSpace) { - Manifest manifest; - const GURL kUrl("http://smorg.borg"); - const std::string kData( - "CACHE MANIFEST\r" - "resource.txt this stuff after the white space should be ignored\r"); - EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); - - base::hash_set<std::string> urls = manifest.explicit_urls; - EXPECT_TRUE(urls.find("http://smorg.borg/resource.txt") != urls.end()); -} - -TEST(AppCacheManifestParserTest, DifferentOriginUrlWithSecureScheme) { - Manifest manifest; - const GURL kUrl("https://www.foo.com"); - const std::string kData("CACHE MANIFEST\r" - "CACHE: \r" - "relative/secureschemesameorigin\r" - "https://www.foo.com/secureschemesameorigin\r" - "http://www.xyz.com/secureschemedifforigin\r" - "https://www.xyz.com/secureschemedifforigin\r"); - - EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); - EXPECT_TRUE(manifest.fallback_namespaces.empty()); - EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); - - base::hash_set<std::string> urls = manifest.explicit_urls; - const size_t kExpected = 3; - ASSERT_EQ(kExpected, urls.size()); - EXPECT_TRUE(urls.find("https://www.foo.com/relative/secureschemesameorigin") - != urls.end()); - EXPECT_TRUE(urls.find("https://www.foo.com/secureschemesameorigin") != - urls.end()); - EXPECT_FALSE(urls.find("http://www.xyz.com/secureschemedifforigin") != - urls.end()); - EXPECT_TRUE(urls.find("https://www.xyz.com/secureschemedifforigin") != - urls.end()); -} - -TEST(AppCacheManifestParserTest, PatternMatching) { - const GURL kUrl("http://foo.com/manifest"); - const std::string kManifestBody( - "CACHE MANIFEST\r" - "CACHE: \r" - "http://foo.com/page.html\r" - "CHROMIUM-INTERCEPT:\r" - "http://foo.com/intercept_prefix return /prefix\r" - "http://foo.com/intercept_pattern return /pattern isPattern\r" - "http://foo.com/*/intercept_pattern?query return /pattern isPattern\r" - "FALLBACK:\r" - "http://foo.com/fallback_prefix /prefix wrongAnnotation\r" - "http://foo.com/fallback_pattern* /pattern\tisPattern \r" - "NETWORK:\r" - "*\r" - "isPattern\r" // should not be interpretted as a pattern - "http://foo.com/network_pattern* isPattern\r"); - - - Manifest manifest; - EXPECT_TRUE(ParseManifest(kUrl, kManifestBody.c_str(), - kManifestBody.length(), manifest)); - EXPECT_TRUE(manifest.online_whitelist_all); - EXPECT_EQ(1u, manifest.explicit_urls.size()); - EXPECT_EQ(3u, manifest.intercept_namespaces.size()); - EXPECT_EQ(2u, manifest.fallback_namespaces.size()); - EXPECT_EQ(2u, manifest.online_whitelist_namespaces.size()); - EXPECT_EQ(INTERCEPT_NAMESPACE, manifest.intercept_namespaces[0].type); - EXPECT_EQ(FALLBACK_NAMESPACE, manifest.fallback_namespaces[0].type); - EXPECT_EQ(NETWORK_NAMESPACE, manifest.online_whitelist_namespaces[0].type); - EXPECT_FALSE(manifest.intercept_namespaces[0].is_pattern); - EXPECT_TRUE(manifest.intercept_namespaces[1].is_pattern); - EXPECT_TRUE(manifest.intercept_namespaces[2].is_pattern); - EXPECT_FALSE(manifest.fallback_namespaces[0].is_pattern); - EXPECT_TRUE(manifest.fallback_namespaces[1].is_pattern); - EXPECT_FALSE(manifest.online_whitelist_namespaces[0].is_pattern); - EXPECT_TRUE(manifest.online_whitelist_namespaces[1].is_pattern); - EXPECT_EQ( - GURL("http://foo.com/*/intercept_pattern?query"), - manifest.intercept_namespaces[2].namespace_url); - EXPECT_EQ( - GURL("http://foo.com/pattern"), - manifest.intercept_namespaces[2].target_url); - EXPECT_EQ( - GURL("http://foo.com/fallback_pattern*"), - manifest.fallback_namespaces[1].namespace_url); - EXPECT_EQ( - GURL("http://foo.com/pattern"), - manifest.fallback_namespaces[1].target_url); - EXPECT_EQ( - GURL("http://foo.com/isPattern"), - manifest.online_whitelist_namespaces[0].namespace_url); - EXPECT_EQ( - GURL(), - manifest.online_whitelist_namespaces[0].target_url); - EXPECT_EQ( - GURL("http://foo.com/network_pattern*"), - manifest.online_whitelist_namespaces[1].namespace_url); - EXPECT_EQ( - GURL(), - manifest.online_whitelist_namespaces[1].target_url); -} - -} // namespace appcache diff --git a/webkit/browser/appcache/mock_appcache_storage.h b/webkit/browser/appcache/mock_appcache_storage.h index 375c20f..3c65d8d 100644 --- a/webkit/browser/appcache/mock_appcache_storage.h +++ b/webkit/browser/appcache/mock_appcache_storage.h @@ -21,7 +21,24 @@ #include "webkit/browser/appcache/appcache_storage.h" namespace content { +FORWARD_DECLARE_TEST(AppCacheServiceTest, DeleteAppCachesForOrigin); +FORWARD_DECLARE_TEST(MockAppCacheStorageTest, BasicFindMainResponse); +FORWARD_DECLARE_TEST(MockAppCacheStorageTest, + BasicFindMainFallbackResponse); +FORWARD_DECLARE_TEST(MockAppCacheStorageTest, CreateGroup); +FORWARD_DECLARE_TEST(MockAppCacheStorageTest, FindMainResponseExclusions); +FORWARD_DECLARE_TEST(MockAppCacheStorageTest, + FindMainResponseWithMultipleCandidates); +FORWARD_DECLARE_TEST(MockAppCacheStorageTest, LoadCache_FarHit); +FORWARD_DECLARE_TEST(MockAppCacheStorageTest, LoadGroupAndCache_FarHit); +FORWARD_DECLARE_TEST(MockAppCacheStorageTest, MakeGroupObsolete); +FORWARD_DECLARE_TEST(MockAppCacheStorageTest, StoreNewGroup); +FORWARD_DECLARE_TEST(MockAppCacheStorageTest, StoreExistingGroup); +FORWARD_DECLARE_TEST(MockAppCacheStorageTest, + StoreExistingGroupExistingCache); class AppCacheRequestHandlerTest; +class AppCacheServiceTest; +class MockAppCacheStorageTest; } namespace appcache { @@ -67,8 +84,9 @@ class MockAppCacheStorage : public AppCacheStorage { private: friend class content::AppCacheRequestHandlerTest; - friend class AppCacheServiceTest; - friend class AppCacheUpdateJobTest; + friend class content::AppCacheServiceTest; + friend class content::AppCacheUpdateJobTest; + friend class content::MockAppCacheStorageTest; typedef base::hash_map<int64, scoped_refptr<AppCache> > StoredCacheMap; typedef std::map<GURL, scoped_refptr<AppCacheGroup> > StoredGroupMap; @@ -199,21 +217,26 @@ class MockAppCacheStorage : public AppCacheStorage { base::WeakPtrFactory<MockAppCacheStorage> weak_factory_; - FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, BasicFindMainResponse); - FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, + FRIEND_TEST_ALL_PREFIXES(content::MockAppCacheStorageTest, + BasicFindMainResponse); + FRIEND_TEST_ALL_PREFIXES(content::MockAppCacheStorageTest, BasicFindMainFallbackResponse); - FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, CreateGroup); - FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, FindMainResponseExclusions); - FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, + FRIEND_TEST_ALL_PREFIXES(content::MockAppCacheStorageTest, CreateGroup); + FRIEND_TEST_ALL_PREFIXES(content::MockAppCacheStorageTest, + FindMainResponseExclusions); + FRIEND_TEST_ALL_PREFIXES(content::MockAppCacheStorageTest, FindMainResponseWithMultipleCandidates); - FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, LoadCache_FarHit); - FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, LoadGroupAndCache_FarHit); - FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, MakeGroupObsolete); - FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, StoreNewGroup); - FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, StoreExistingGroup); - FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, + FRIEND_TEST_ALL_PREFIXES(content::MockAppCacheStorageTest, LoadCache_FarHit); + FRIEND_TEST_ALL_PREFIXES(content::MockAppCacheStorageTest, + LoadGroupAndCache_FarHit); + FRIEND_TEST_ALL_PREFIXES(content::MockAppCacheStorageTest, MakeGroupObsolete); + FRIEND_TEST_ALL_PREFIXES(content::MockAppCacheStorageTest, StoreNewGroup); + FRIEND_TEST_ALL_PREFIXES(content::MockAppCacheStorageTest, + StoreExistingGroup); + FRIEND_TEST_ALL_PREFIXES(content::MockAppCacheStorageTest, StoreExistingGroupExistingCache); - FRIEND_TEST_ALL_PREFIXES(AppCacheServiceTest, DeleteAppCachesForOrigin); + FRIEND_TEST_ALL_PREFIXES(content::AppCacheServiceTest, + DeleteAppCachesForOrigin); DISALLOW_COPY_AND_ASSIGN(MockAppCacheStorage); }; diff --git a/webkit/browser/appcache/mock_appcache_storage_unittest.cc b/webkit/browser/appcache/mock_appcache_storage_unittest.cc deleted file mode 100644 index ade1820..0000000 --- a/webkit/browser/appcache/mock_appcache_storage_unittest.cc +++ /dev/null @@ -1,631 +0,0 @@ -// 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 "base/run_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_response.h" -#include "webkit/browser/appcache/appcache_storage.h" -#include "webkit/browser/appcache/mock_appcache_service.h" - -namespace appcache { - -class MockAppCacheStorageTest : public testing::Test { - public: - class MockStorageDelegate : public AppCacheStorage::Delegate { - public: - explicit MockStorageDelegate() - : loaded_cache_id_(0), stored_group_success_(false), - obsoleted_success_(false), found_cache_id_(kNoCacheId) { - } - - virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) OVERRIDE { - loaded_cache_ = cache; - loaded_cache_id_ = cache_id; - } - - virtual void OnGroupLoaded(AppCacheGroup* group, - const GURL& manifest_url) OVERRIDE { - loaded_group_ = group; - loaded_manifest_url_ = manifest_url; - } - - virtual void OnGroupAndNewestCacheStored( - AppCacheGroup* group, AppCache* newest_cache, bool success, - bool would_exceed_quota) OVERRIDE { - stored_group_ = group; - stored_group_success_ = success; - } - - virtual void OnGroupMadeObsolete(AppCacheGroup* group, - bool success, - int response_code) OVERRIDE { - obsoleted_group_ = group; - obsoleted_success_ = success; - } - - virtual void OnMainResponseFound(const GURL& url, - const AppCacheEntry& entry, - const GURL& fallback_url, - const AppCacheEntry& fallback_entry, - int64 cache_id, - int64 group_id, - const GURL& manifest_url) OVERRIDE { - found_url_ = url; - found_entry_ = entry; - found_fallback_url_ = fallback_url; - found_fallback_entry_ = fallback_entry; - found_cache_id_ = cache_id; - found_manifest_url_ = manifest_url; - } - - scoped_refptr<AppCache> loaded_cache_; - int64 loaded_cache_id_; - scoped_refptr<AppCacheGroup> loaded_group_; - GURL loaded_manifest_url_; - scoped_refptr<AppCacheGroup> stored_group_; - bool stored_group_success_; - scoped_refptr<AppCacheGroup> obsoleted_group_; - bool obsoleted_success_; - GURL found_url_; - AppCacheEntry found_entry_; - GURL found_fallback_url_; - AppCacheEntry found_fallback_entry_; - int64 found_cache_id_; - GURL found_manifest_url_; - }; - - private: - base::MessageLoop message_loop_; -}; - -TEST_F(MockAppCacheStorageTest, LoadCache_Miss) { - // Attempt to load a cache that doesn't exist. Should - // complete asyncly. - MockAppCacheService service; - MockStorageDelegate delegate; - service.storage()->LoadCache(111, &delegate); - EXPECT_NE(111, delegate.loaded_cache_id_); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_EQ(111, delegate.loaded_cache_id_); - EXPECT_FALSE(delegate.loaded_cache_.get()); -} - -TEST_F(MockAppCacheStorageTest, LoadCache_NearHit) { - // Attempt to load a cache that is currently in use - // and does not require loading from disk. This - // load should complete syncly. - MockAppCacheService service; - - // Setup some preconditions. Make an 'unstored' cache for - // us to load. The ctor should put it in the working set. - int64 cache_id = service.storage()->NewCacheId(); - scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); - - // Conduct the test. - MockStorageDelegate delegate; - service.storage()->LoadCache(cache_id, &delegate); - EXPECT_EQ(cache_id, delegate.loaded_cache_id_); - EXPECT_EQ(cache.get(), delegate.loaded_cache_.get()); -} - -TEST_F(MockAppCacheStorageTest, CreateGroup) { - // Attempt to load/create a group that doesn't exist. - // Should complete asyncly. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - MockStorageDelegate delegate; - GURL manifest_url("http://blah/"); - service.storage()->LoadOrCreateGroup(manifest_url, &delegate); - EXPECT_NE(manifest_url, delegate.loaded_manifest_url_); - EXPECT_FALSE(delegate.loaded_group_.get()); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_); - EXPECT_TRUE(delegate.loaded_group_.get()); - EXPECT_TRUE(delegate.loaded_group_->HasOneRef()); - EXPECT_FALSE(delegate.loaded_group_->newest_complete_cache()); - EXPECT_TRUE(storage->stored_groups_.empty()); -} - -TEST_F(MockAppCacheStorageTest, LoadGroup_NearHit) { - // Attempt to load a group that is currently in use - // and does not require loading from disk. This - // load should complete syncly. - MockAppCacheService service; - MockStorageDelegate delegate; - - // Setup some preconditions. Create a group that appears - // to be "unstored" and "currently in use". - GURL manifest_url("http://blah/"); - service.storage()->LoadOrCreateGroup(manifest_url, &delegate); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_); - EXPECT_TRUE(delegate.loaded_group_.get()); - - // Reset our delegate, and take a reference to the new group. - scoped_refptr<AppCacheGroup> group; - group.swap(delegate.loaded_group_); - delegate.loaded_manifest_url_ = GURL(); - - // Conduct the test. - service.storage()->LoadOrCreateGroup(manifest_url, &delegate); - EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_); - EXPECT_EQ(group.get(), delegate.loaded_group_.get()); -} - -TEST_F(MockAppCacheStorageTest, LoadGroupAndCache_FarHit) { - // Attempt to load a cache that is not currently in use - // and does require loading from disk. This - // load should complete asyncly. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - - // Setup some preconditions. Create a group and newest cache that - // appears to be "stored" and "not currently in use". - GURL manifest_url("http://blah/"); - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), manifest_url, 111)); - int64 cache_id = storage->NewCacheId(); - scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); - cache->set_complete(true); - group->AddCache(cache.get()); - storage->AddStoredGroup(group.get()); - storage->AddStoredCache(cache.get()); - - // Drop the references from above so the only refs to these - // objects are from within the storage class. This is to make - // these objects appear as "not currently in use". - AppCache* cache_ptr = cache.get(); - AppCacheGroup* group_ptr = group.get(); - cache = NULL; - group = NULL; - - // Setup a delegate to receive completion callbacks. - MockStorageDelegate delegate; - - // Conduct the cache load test. - EXPECT_NE(cache_id, delegate.loaded_cache_id_); - EXPECT_NE(cache_ptr, delegate.loaded_cache_.get()); - storage->LoadCache(cache_id, &delegate); - EXPECT_NE(cache_id, delegate.loaded_cache_id_); - EXPECT_NE(cache_ptr, delegate.loaded_cache_.get()); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_EQ(cache_id, delegate.loaded_cache_id_); - EXPECT_EQ(cache_ptr, delegate.loaded_cache_.get()); - delegate.loaded_cache_ = NULL; - - // Conduct the group load test. - EXPECT_NE(manifest_url, delegate.loaded_manifest_url_); - EXPECT_FALSE(delegate.loaded_group_.get()); - storage->LoadOrCreateGroup(manifest_url, &delegate); - EXPECT_NE(manifest_url, delegate.loaded_manifest_url_); - EXPECT_FALSE(delegate.loaded_group_.get()); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_); - EXPECT_EQ(group_ptr, delegate.loaded_group_.get()); -} - -TEST_F(MockAppCacheStorageTest, StoreNewGroup) { - // Store a group and its newest cache. Should complete asyncly. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - - // Setup some preconditions. Create a group and newest cache that - // appears to be "unstored". - GURL manifest_url("http://blah/"); - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), manifest_url, 111)); - int64 cache_id = storage->NewCacheId(); - scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); - // 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. - - // Conduct the store test. - MockStorageDelegate delegate; - EXPECT_TRUE(storage->stored_caches_.empty()); - EXPECT_TRUE(storage->stored_groups_.empty()); - storage->StoreGroupAndNewestCache(group.get(), cache.get(), &delegate); - EXPECT_FALSE(delegate.stored_group_success_); - EXPECT_TRUE(storage->stored_caches_.empty()); - EXPECT_TRUE(storage->stored_groups_.empty()); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_TRUE(delegate.stored_group_success_); - EXPECT_FALSE(storage->stored_caches_.empty()); - EXPECT_FALSE(storage->stored_groups_.empty()); - EXPECT_EQ(cache, group->newest_complete_cache()); - EXPECT_TRUE(cache->is_complete()); -} - -TEST_F(MockAppCacheStorageTest, StoreExistingGroup) { - // Store a group and its newest cache. Should complete asyncly. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - - // Setup some preconditions. Create a group and old complete cache - // that appear to be "stored", and a newest unstored complete cache. - GURL manifest_url("http://blah/"); - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), manifest_url, 111)); - int64 old_cache_id = storage->NewCacheId(); - scoped_refptr<AppCache> old_cache( - new AppCache(service.storage(), old_cache_id)); - old_cache->set_complete(true); - group->AddCache(old_cache.get()); - storage->AddStoredGroup(group.get()); - storage->AddStoredCache(old_cache.get()); - int64 new_cache_id = storage->NewCacheId(); - scoped_refptr<AppCache> new_cache( - new AppCache(service.storage(), new_cache_id)); - // Hold our refs to simulate the UpdateJob holding these refs. - - // Conduct the test. - MockStorageDelegate delegate; - EXPECT_EQ(size_t(1), storage->stored_caches_.size()); - EXPECT_EQ(size_t(1), storage->stored_groups_.size()); - EXPECT_TRUE(storage->IsCacheStored(old_cache.get())); - EXPECT_FALSE(storage->IsCacheStored(new_cache.get())); - storage->StoreGroupAndNewestCache(group.get(), new_cache.get(), &delegate); - EXPECT_FALSE(delegate.stored_group_success_); - EXPECT_EQ(size_t(1), storage->stored_caches_.size()); - EXPECT_EQ(size_t(1), storage->stored_groups_.size()); - EXPECT_TRUE(storage->IsCacheStored(old_cache.get())); - EXPECT_FALSE(storage->IsCacheStored(new_cache.get())); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_TRUE(delegate.stored_group_success_); - EXPECT_EQ(size_t(1), storage->stored_caches_.size()); - EXPECT_EQ(size_t(1), storage->stored_groups_.size()); - EXPECT_FALSE(storage->IsCacheStored(old_cache.get())); - EXPECT_TRUE(storage->IsCacheStored(new_cache.get())); - EXPECT_EQ(new_cache.get(), group->newest_complete_cache()); - EXPECT_TRUE(new_cache->is_complete()); -} - -TEST_F(MockAppCacheStorageTest, StoreExistingGroupExistingCache) { - // Store a group with updates to its existing newest complete cache. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - - // Setup some preconditions. Create a group and a complete cache that - // appear to be "stored". - GURL manifest_url("http://blah"); - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), manifest_url, 111)); - int64 cache_id = storage->NewCacheId(); - scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); - cache->set_complete(true); - group->AddCache(cache.get()); - storage->AddStoredGroup(group.get()); - storage->AddStoredCache(cache.get()); - // Hold our refs to simulate the UpdateJob holding these refs. - - // Change the group's newest cache. - EXPECT_EQ(cache, group->newest_complete_cache()); - GURL entry_url("http://blah/blah"); - cache->AddEntry(entry_url, AppCacheEntry(AppCacheEntry::MASTER)); - - // Conduct the test. - MockStorageDelegate delegate; - EXPECT_EQ(size_t(1), storage->stored_caches_.size()); - EXPECT_EQ(size_t(1), storage->stored_groups_.size()); - EXPECT_TRUE(storage->IsCacheStored(cache.get())); - storage->StoreGroupAndNewestCache(group.get(), cache.get(), &delegate); - EXPECT_FALSE(delegate.stored_group_success_); - EXPECT_EQ(size_t(1), storage->stored_caches_.size()); - EXPECT_EQ(size_t(1), storage->stored_groups_.size()); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_TRUE(delegate.stored_group_success_); - EXPECT_EQ(size_t(1), storage->stored_caches_.size()); - EXPECT_EQ(size_t(1), storage->stored_groups_.size()); - EXPECT_TRUE(storage->IsCacheStored(cache.get())); - EXPECT_EQ(cache, group->newest_complete_cache()); - EXPECT_TRUE(cache->GetEntry(entry_url)); -} - -TEST_F(MockAppCacheStorageTest, MakeGroupObsolete) { - // Make a group obsolete, should complete asyncly. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - - // Setup some preconditions. Create a group and newest cache that - // appears to be "stored" and "currently in use". - GURL manifest_url("http://blah/"); - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), manifest_url, 111)); - int64 cache_id = storage->NewCacheId(); - scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); - cache->set_complete(true); - group->AddCache(cache.get()); - storage->AddStoredGroup(group.get()); - storage->AddStoredCache(cache.get()); - // Hold our refs to simulate the UpdateJob holding these refs. - - // Conduct the test. - MockStorageDelegate delegate; - EXPECT_FALSE(group->is_obsolete()); - EXPECT_EQ(size_t(1), storage->stored_caches_.size()); - EXPECT_EQ(size_t(1), storage->stored_groups_.size()); - EXPECT_FALSE(cache->HasOneRef()); - EXPECT_FALSE(group->HasOneRef()); - storage->MakeGroupObsolete(group.get(), &delegate, 0); - EXPECT_FALSE(group->is_obsolete()); - EXPECT_EQ(size_t(1), storage->stored_caches_.size()); - EXPECT_EQ(size_t(1), storage->stored_groups_.size()); - EXPECT_FALSE(cache->HasOneRef()); - EXPECT_FALSE(group->HasOneRef()); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_TRUE(delegate.obsoleted_success_); - EXPECT_EQ(group.get(), delegate.obsoleted_group_.get()); - EXPECT_TRUE(group->is_obsolete()); - EXPECT_TRUE(storage->stored_caches_.empty()); - EXPECT_TRUE(storage->stored_groups_.empty()); - EXPECT_TRUE(cache->HasOneRef()); - EXPECT_FALSE(group->HasOneRef()); - delegate.obsoleted_group_ = NULL; - cache = NULL; - EXPECT_TRUE(group->HasOneRef()); -} - -TEST_F(MockAppCacheStorageTest, MarkEntryAsForeign) { - // Should complete syncly. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - - // Setup some preconditions. Create a cache with an entry. - GURL entry_url("http://blah/entry"); - int64 cache_id = storage->NewCacheId(); - scoped_refptr<AppCache> cache(new AppCache(service.storage(), cache_id)); - cache->AddEntry(entry_url, AppCacheEntry(AppCacheEntry::EXPLICIT)); - - // Conduct the test. - MockStorageDelegate delegate; - EXPECT_FALSE(cache->GetEntry(entry_url)->IsForeign()); - storage->MarkEntryAsForeign(entry_url, cache_id); - EXPECT_TRUE(cache->GetEntry(entry_url)->IsForeign()); - EXPECT_TRUE(cache->GetEntry(entry_url)->IsExplicit()); -} - -TEST_F(MockAppCacheStorageTest, FindNoMainResponse) { - // Should complete asyncly. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - - // Conduct the test. - MockStorageDelegate delegate; - GURL url("http://blah/some_url"); - EXPECT_NE(url, delegate.found_url_); - storage->FindResponseForMainRequest(url, GURL(), &delegate); - EXPECT_NE(url, delegate.found_url_); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_EQ(url, delegate.found_url_); - EXPECT_TRUE(delegate.found_manifest_url_.is_empty()); - EXPECT_EQ(kNoCacheId, delegate.found_cache_id_); - EXPECT_EQ(kNoResponseId, delegate.found_entry_.response_id()); - EXPECT_EQ(kNoResponseId, delegate.found_fallback_entry_.response_id()); - EXPECT_TRUE(delegate.found_fallback_url_.is_empty()); - EXPECT_EQ(0, delegate.found_entry_.types()); - EXPECT_EQ(0, delegate.found_fallback_entry_.types()); -} - -TEST_F(MockAppCacheStorageTest, BasicFindMainResponse) { - // Should complete asyncly. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - - // Setup some preconditions. Create a complete cache with an entry. - const int64 kCacheId = storage->NewCacheId(); - const GURL kEntryUrl("http://blah/entry"); - const GURL kManifestUrl("http://blah/manifest"); - const int64 kResponseId = 1; - scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId)); - cache->AddEntry( - kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId)); - cache->set_complete(true); - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), kManifestUrl, 111)); - group->AddCache(cache.get()); - storage->AddStoredGroup(group.get()); - storage->AddStoredCache(cache.get()); - - // Conduct the test. - MockStorageDelegate delegate; - EXPECT_NE(kEntryUrl, delegate.found_url_); - storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate); - EXPECT_NE(kEntryUrl, delegate.found_url_); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_EQ(kEntryUrl, delegate.found_url_); - EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_); - EXPECT_EQ(kCacheId, delegate.found_cache_id_); - EXPECT_EQ(kResponseId, delegate.found_entry_.response_id()); - EXPECT_TRUE(delegate.found_entry_.IsExplicit()); - EXPECT_FALSE(delegate.found_fallback_entry_.has_response_id()); -} - -TEST_F(MockAppCacheStorageTest, BasicFindMainFallbackResponse) { - // Should complete asyncly. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - - // Setup some preconditions. Create a complete cache with a - // fallback namespace and entry. - const int64 kCacheId = storage->NewCacheId(); - const GURL kFallbackEntryUrl1("http://blah/fallback_entry1"); - const GURL kFallbackNamespaceUrl1("http://blah/fallback_namespace/"); - const GURL kFallbackEntryUrl2("http://blah/fallback_entry2"); - const GURL kFallbackNamespaceUrl2("http://blah/fallback_namespace/longer"); - const GURL kManifestUrl("http://blah/manifest"); - const int64 kResponseId1 = 1; - const int64 kResponseId2 = 2; - - Manifest manifest; - manifest.fallback_namespaces.push_back( - Namespace(FALLBACK_NAMESPACE, kFallbackNamespaceUrl1, - kFallbackEntryUrl1, false)); - manifest.fallback_namespaces.push_back( - Namespace(FALLBACK_NAMESPACE, kFallbackNamespaceUrl2, - kFallbackEntryUrl2, false)); - - scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId)); - cache->InitializeWithManifest(&manifest); - cache->AddEntry(kFallbackEntryUrl1, - AppCacheEntry(AppCacheEntry::FALLBACK, kResponseId1)); - cache->AddEntry(kFallbackEntryUrl2, - AppCacheEntry(AppCacheEntry::FALLBACK, kResponseId2)); - cache->set_complete(true); - - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), kManifestUrl, 111)); - group->AddCache(cache.get()); - storage->AddStoredGroup(group.get()); - storage->AddStoredCache(cache.get()); - - // The test url is in both fallback namespace urls, but should match - // the longer of the two. - const GURL kTestUrl("http://blah/fallback_namespace/longer/test"); - - // Conduct the test. - MockStorageDelegate delegate; - EXPECT_NE(kTestUrl, delegate.found_url_); - storage->FindResponseForMainRequest(kTestUrl, GURL(), &delegate); - EXPECT_NE(kTestUrl, delegate.found_url_); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_EQ(kTestUrl, delegate.found_url_); - EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_); - EXPECT_EQ(kCacheId, delegate.found_cache_id_); - EXPECT_FALSE(delegate.found_entry_.has_response_id()); - EXPECT_EQ(kResponseId2, delegate.found_fallback_entry_.response_id()); - EXPECT_EQ(kFallbackEntryUrl2, delegate.found_fallback_url_); - EXPECT_TRUE(delegate.found_fallback_entry_.IsFallback()); -} - -TEST_F(MockAppCacheStorageTest, FindMainResponseWithMultipleCandidates) { - // Should complete asyncly. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - - // Setup some preconditions. Create 2 complete caches with an entry - // for the same url. - - const GURL kEntryUrl("http://blah/entry"); - const int64 kCacheId1 = storage->NewCacheId(); - const int64 kCacheId2 = storage->NewCacheId(); - const GURL kManifestUrl1("http://blah/manifest1"); - const GURL kManifestUrl2("http://blah/manifest2"); - const int64 kResponseId1 = 1; - const int64 kResponseId2 = 2; - - // The first cache. - scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId1)); - cache->AddEntry( - kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId1)); - cache->set_complete(true); - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), kManifestUrl1, 111)); - group->AddCache(cache.get()); - storage->AddStoredGroup(group.get()); - storage->AddStoredCache(cache.get()); - // Drop our references to cache1 so it appears as "not in use". - cache = NULL; - group = NULL; - - // The second cache. - cache = new AppCache(service.storage(), kCacheId2); - cache->AddEntry( - kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId2)); - cache->set_complete(true); - group = new AppCacheGroup(service.storage(), kManifestUrl2, 222); - group->AddCache(cache.get()); - storage->AddStoredGroup(group.get()); - storage->AddStoredCache(cache.get()); - - // Conduct the test, we should find the response from the second cache - // since it's "in use". - MockStorageDelegate delegate; - EXPECT_NE(kEntryUrl, delegate.found_url_); - storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate); - EXPECT_NE(kEntryUrl, delegate.found_url_); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_EQ(kEntryUrl, delegate.found_url_); - EXPECT_EQ(kManifestUrl2, delegate.found_manifest_url_); - EXPECT_EQ(kCacheId2, delegate.found_cache_id_); - EXPECT_EQ(kResponseId2, delegate.found_entry_.response_id()); - EXPECT_TRUE(delegate.found_entry_.IsExplicit()); - EXPECT_FALSE(delegate.found_fallback_entry_.has_response_id()); -} - -TEST_F(MockAppCacheStorageTest, FindMainResponseExclusions) { - // Should complete asyncly. - MockAppCacheService service; - MockAppCacheStorage* storage = - reinterpret_cast<MockAppCacheStorage*>(service.storage()); - - // Setup some preconditions. Create a complete cache with a - // foreign entry and an online namespace. - - const int64 kCacheId = storage->NewCacheId(); - const GURL kEntryUrl("http://blah/entry"); - const GURL kManifestUrl("http://blah/manifest"); - const GURL kOnlineNamespaceUrl("http://blah/online_namespace"); - const int64 kResponseId = 1; - - Manifest manifest; - manifest.online_whitelist_namespaces.push_back( - Namespace(NETWORK_NAMESPACE, kOnlineNamespaceUrl, - GURL(), false)); - scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId)); - cache->InitializeWithManifest(&manifest); - cache->AddEntry( - kEntryUrl, - AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN, - kResponseId)); - cache->set_complete(true); - scoped_refptr<AppCacheGroup> group( - new AppCacheGroup(service.storage(), kManifestUrl, 111)); - group->AddCache(cache.get()); - storage->AddStoredGroup(group.get()); - storage->AddStoredCache(cache.get()); - - MockStorageDelegate delegate; - - // We should not find anything for the foreign entry. - EXPECT_NE(kEntryUrl, delegate.found_url_); - storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate); - EXPECT_NE(kEntryUrl, delegate.found_url_); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_EQ(kEntryUrl, delegate.found_url_); - EXPECT_TRUE(delegate.found_manifest_url_.is_empty()); - EXPECT_EQ(kNoCacheId, delegate.found_cache_id_); - EXPECT_EQ(kNoResponseId, delegate.found_entry_.response_id()); - EXPECT_EQ(kNoResponseId, delegate.found_fallback_entry_.response_id()); - EXPECT_TRUE(delegate.found_fallback_url_.is_empty()); - EXPECT_EQ(0, delegate.found_entry_.types()); - EXPECT_EQ(0, delegate.found_fallback_entry_.types()); - - // We should not find anything for the online namespace. - EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_); - storage->FindResponseForMainRequest(kOnlineNamespaceUrl, GURL(), &delegate); - EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_); - base::RunLoop().RunUntilIdle(); // Do async task execution. - EXPECT_EQ(kOnlineNamespaceUrl, delegate.found_url_); - EXPECT_TRUE(delegate.found_manifest_url_.is_empty()); - EXPECT_EQ(kNoCacheId, delegate.found_cache_id_); - EXPECT_EQ(kNoResponseId, delegate.found_entry_.response_id()); - EXPECT_EQ(kNoResponseId, delegate.found_fallback_entry_.response_id()); - EXPECT_TRUE(delegate.found_fallback_url_.is_empty()); - EXPECT_EQ(0, delegate.found_entry_.types()); - EXPECT_EQ(0, delegate.found_fallback_entry_.types()); -} - -} // namespace appcache |