Index: webkit/appcache/appcache_database_unittest.cc |
=================================================================== |
--- webkit/appcache/appcache_database_unittest.cc (revision 113546) |
+++ webkit/appcache/appcache_database_unittest.cc (working copy) |
@@ -6,7 +6,11 @@ |
#include "base/file_util.h" |
#include "base/scoped_temp_dir.h" |
+#include "base/stringprintf.h" |
#include "sql/connection.h" |
+#include "sql/meta_table.h" |
+#include "sql/statement.h" |
+#include "sql/transaction.h" |
#include "webkit/appcache/appcache_database.h" |
#include "webkit/appcache/appcache_entry.h" |
@@ -322,7 +326,7 @@ |
EXPECT_EQ(kOrigin2, record.origin); |
} |
-TEST(AppCacheDatabaseTest, FallbackNameSpaceRecords) { |
+TEST(AppCacheDatabaseTest, NamespaceRecords) { |
const FilePath kEmptyPath; |
AppCacheDatabase db(kEmptyPath); |
EXPECT_TRUE(db.LazyOpen(true)); |
@@ -339,87 +343,88 @@ |
const GURL kBarFallbackEntry("http://bar/entry"); |
const GURL kBarOrigin(kBarNameSpace1.GetOrigin()); |
- const AppCacheDatabase::FallbackNameSpaceRecord kZeroRecord; |
- AppCacheDatabase::FallbackNameSpaceRecord record; |
- std::vector<AppCacheDatabase::FallbackNameSpaceRecord> records; |
+ 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.FindFallbackNameSpacesForCache(1, &records)); |
- EXPECT_TRUE(records.empty()); |
- EXPECT_TRUE(db.FindFallbackNameSpacesForOrigin(kFooOrigin, &records)); |
- EXPECT_TRUE(records.empty()); |
- EXPECT_TRUE(db.DeleteFallbackNameSpacesForCache(1)); |
+ 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_url = kFooNameSpace1; |
- record.fallback_entry_url = kFooFallbackEntry; |
- EXPECT_TRUE(db.InsertFallbackNameSpace(&record)); |
- EXPECT_FALSE(db.InsertFallbackNameSpace(&record)); |
+ record.target_url = kFooFallbackEntry; |
+ EXPECT_TRUE(db.InsertNamespace(&record)); |
+ EXPECT_FALSE(db.InsertNamespace(&record)); |
record.cache_id = 2; |
record.origin = kFooOrigin; |
record.namespace_url = kFooNameSpace2; |
- record.fallback_entry_url = kFooFallbackEntry; |
- EXPECT_TRUE(db.InsertFallbackNameSpace(&record)); |
+ record.target_url = kFooFallbackEntry; |
+ EXPECT_TRUE(db.InsertNamespace(&record)); |
- records.clear(); |
- EXPECT_TRUE(db.FindFallbackNameSpacesForCache(1, &records)); |
- EXPECT_EQ(1U, records.size()); |
- EXPECT_EQ(1, records[0].cache_id); |
- EXPECT_EQ(kFooOrigin, records[0].origin); |
- EXPECT_EQ(kFooNameSpace1, records[0].namespace_url); |
- EXPECT_EQ(kFooFallbackEntry, records[0].fallback_entry_url); |
+ 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_url); |
+ EXPECT_EQ(kFooFallbackEntry, fallbacks[0].target_url); |
- records.clear(); |
- EXPECT_TRUE(db.FindFallbackNameSpacesForCache(2, &records)); |
- EXPECT_EQ(1U, records.size()); |
- EXPECT_EQ(2, records[0].cache_id); |
- EXPECT_EQ(kFooOrigin, records[0].origin); |
- EXPECT_EQ(kFooNameSpace2, records[0].namespace_url); |
- EXPECT_EQ(kFooFallbackEntry, records[0].fallback_entry_url); |
+ 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_url); |
+ EXPECT_EQ(kFooFallbackEntry, fallbacks[0].target_url); |
- records.clear(); |
- EXPECT_TRUE(db.FindFallbackNameSpacesForOrigin(kFooOrigin, &records)); |
- EXPECT_EQ(2U, records.size()); |
- EXPECT_EQ(1, records[0].cache_id); |
- EXPECT_EQ(kFooOrigin, records[0].origin); |
- EXPECT_EQ(kFooNameSpace1, records[0].namespace_url); |
- EXPECT_EQ(kFooFallbackEntry, records[0].fallback_entry_url); |
- EXPECT_EQ(2, records[1].cache_id); |
- EXPECT_EQ(kFooOrigin, records[1].origin); |
- EXPECT_EQ(kFooNameSpace2, records[1].namespace_url); |
- EXPECT_EQ(kFooFallbackEntry, records[1].fallback_entry_url); |
+ 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_url); |
+ EXPECT_EQ(kFooFallbackEntry, fallbacks[0].target_url); |
+ EXPECT_EQ(2, fallbacks[1].cache_id); |
+ EXPECT_EQ(kFooOrigin, fallbacks[1].origin); |
+ EXPECT_EQ(kFooNameSpace2, fallbacks[1].namespace_url); |
+ EXPECT_EQ(kFooFallbackEntry, fallbacks[1].target_url); |
- EXPECT_TRUE(db.DeleteFallbackNameSpacesForCache(1)); |
- records.clear(); |
- EXPECT_TRUE(db.FindFallbackNameSpacesForOrigin(kFooOrigin, &records)); |
- EXPECT_EQ(1U, records.size()); |
- EXPECT_EQ(2, records[0].cache_id); |
- EXPECT_EQ(kFooOrigin, records[0].origin); |
- EXPECT_EQ(kFooNameSpace2, records[0].namespace_url); |
- EXPECT_EQ(kFooFallbackEntry, records[0].fallback_entry_url); |
+ 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_url); |
+ EXPECT_EQ(kFooFallbackEntry, fallbacks[0].target_url); |
// Two more records for the same cache in the Bar origin. |
record.cache_id = 3; |
record.origin = kBarOrigin; |
record.namespace_url = kBarNameSpace1; |
- record.fallback_entry_url = kBarFallbackEntry; |
- EXPECT_TRUE(db.InsertFallbackNameSpace(&record)); |
+ record.target_url = kBarFallbackEntry; |
+ EXPECT_TRUE(db.InsertNamespace(&record)); |
record.cache_id = 3; |
record.origin = kBarOrigin; |
record.namespace_url = kBarNameSpace2; |
- record.fallback_entry_url = kBarFallbackEntry; |
- EXPECT_TRUE(db.InsertFallbackNameSpace(&record)); |
+ record.target_url = kBarFallbackEntry; |
+ EXPECT_TRUE(db.InsertNamespace(&record)); |
- records.clear(); |
- EXPECT_TRUE(db.FindFallbackNameSpacesForCache(3, &records)); |
- EXPECT_EQ(2U, records.size()); |
- records.clear(); |
- EXPECT_TRUE(db.FindFallbackNameSpacesForOrigin(kBarOrigin, &records)); |
- EXPECT_EQ(2U, records.size()); |
+ fallbacks.clear(); |
+ EXPECT_TRUE(db.FindNamespacesForCache(3, &intercepts, &fallbacks)); |
+ EXPECT_EQ(2U, fallbacks.size()); |
+ fallbacks.clear(); |
+ EXPECT_TRUE(db.FindNamespacesForOrigin(kBarOrigin, &intercepts, &fallbacks)); |
+ EXPECT_EQ(2U, fallbacks.size()); |
} |
TEST(AppCacheDatabaseTest, OnlineWhiteListRecords) { |
@@ -613,4 +618,220 @@ |
EXPECT_EQ(5000, usage_map[kOtherOrigin]); |
} |
+TEST(AppCacheDatabaseTest, UpgradeSchema3to4) { |
+ // Real file on disk for this test. |
+ ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ const FilePath kDbFile = temp_dir.path().AppendASCII("upgrade.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(); |
+ } |
+ |
+ 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_EQ(4, db.meta_table_->GetVersionNumber()); |
+ EXPECT_EQ(4, 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].type); |
+ EXPECT_EQ(kMockOrigin, fallbacks[i].origin); |
+ EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_url); |
+ EXPECT_EQ(expected_target_url, fallbacks[i].target_url); |
+ } |
+} |
+ |
} // namespace appcache |