| Index: webkit/quota/quota_database_unittest.cc
|
| diff --git a/webkit/quota/quota_database_unittest.cc b/webkit/quota/quota_database_unittest.cc
|
| index f126f31dda0ad4bc8beb2fc679c9e95ae76db2e6..2793b12238e82dfadf135f6451333341525daed5 100644
|
| --- a/webkit/quota/quota_database_unittest.cc
|
| +++ b/webkit/quota/quota_database_unittest.cc
|
| @@ -7,6 +7,7 @@
|
| #include <set>
|
|
|
| #include "app/sql/connection.h"
|
| +#include "app/sql/meta_table.h"
|
| #include "app/sql/statement.h"
|
| #include "app/sql/transaction.h"
|
| #include "base/bind.h"
|
| @@ -18,6 +19,7 @@
|
| #include "webkit/quota/mock_special_storage_policy.h"
|
| #include "webkit/quota/quota_database.h"
|
|
|
| +namespace quota {
|
| namespace {
|
|
|
| const base::Time kZeroTime;
|
| @@ -30,74 +32,16 @@ class TestErrorDelegate : public sql::ErrorDelegate {
|
| return error;
|
| }
|
| };
|
| -} // namespace
|
|
|
| -namespace quota {
|
| +} // namespace
|
|
|
| class QuotaDatabaseTest : public testing::Test {
|
| protected:
|
| typedef QuotaDatabase::QuotaTableEntry QuotaTableEntry;
|
| typedef QuotaDatabase::QuotaTableCallback QuotaTableCallback;
|
| - typedef QuotaDatabase::LastAccessTimeTableEntry LastAccessTimeTableEntry;
|
| - typedef QuotaDatabase::LastAccessTimeTableCallback
|
| - LastAccessTimeTableCallback;
|
| -
|
| - template <typename Iterator>
|
| - bool AssignQuotaTable(
|
| - QuotaDatabase* quota_database, Iterator itr, Iterator end) {
|
| - if (!quota_database->LazyOpen(true))
|
| - return false;
|
| -
|
| - for (; itr != end; ++itr) {
|
| - const char* kSql =
|
| - "INSERT INTO HostQuotaTable"
|
| - " (host, type, quota)"
|
| - " VALUES (?, ?, ?)";
|
| - sql::Statement statement;
|
| - statement.Assign(
|
| - quota_database->db_->GetCachedStatement(
|
| - SQL_FROM_HERE, kSql));
|
| - EXPECT_TRUE(statement.is_valid());
|
| -
|
| - statement.BindString(0, itr->host);
|
| - statement.BindInt(1, static_cast<int>(itr->type));
|
| - statement.BindInt64(2, itr->quota);
|
| - if (!statement.Run())
|
| - return false;
|
| - }
|
| -
|
| - quota_database->Commit();
|
| - return true;
|
| - }
|
| -
|
| - template <typename Iterator>
|
| - bool AssignLastAccessTimeTable(
|
| - QuotaDatabase* quota_database, Iterator itr, Iterator end) {
|
| - if (!quota_database->LazyOpen(true))
|
| - return false;
|
| -
|
| - for (; itr != end; ++itr) {
|
| - const char* kSql =
|
| - "INSERT INTO OriginLastAccessTable"
|
| - " (origin, type, used_count, last_access_time)"
|
| - " VALUES (?, ?, ?, ?)";
|
| - sql::Statement statement;
|
| - statement.Assign(
|
| - quota_database->db_->GetCachedStatement(
|
| - SQL_FROM_HERE, kSql));
|
| - EXPECT_TRUE(statement.is_valid());
|
| -
|
| - statement.BindString(0, itr->origin.spec());
|
| - statement.BindInt(1, static_cast<int>(itr->type));
|
| - statement.BindInt(2, itr->used_count);
|
| - statement.BindInt64(3, itr->last_access_time.ToInternalValue());
|
| - if (!statement.Run())
|
| - return false;
|
| - }
|
| -
|
| - quota_database->Commit();
|
| - return true;
|
| - }
|
| + typedef QuotaDatabase::OriginInfoTableEntry OriginInfoTableEntry;
|
| + typedef QuotaDatabase::OriginInfoTableCallback
|
| + OriginInfoTableCallback;
|
|
|
| void LazyOpen(const FilePath& kDbFile) {
|
| QuotaDatabase db(kDbFile);
|
| @@ -107,6 +51,28 @@ class QuotaDatabaseTest : public testing::Test {
|
| EXPECT_TRUE(kDbFile.empty() || file_util::PathExists(kDbFile));
|
| }
|
|
|
| + void UpgradeSchemaV2toV3(const FilePath& kDbFile) {
|
| + const QuotaTableEntry entries[] = {
|
| + { "a", kStorageTypeTemporary, 1 },
|
| + { "b", kStorageTypeTemporary, 2 },
|
| + { "c", kStorageTypePersistent, 3 },
|
| + };
|
| +
|
| + CreateV2Database(kDbFile, entries, ARRAYSIZE_UNSAFE(entries));
|
| +
|
| + QuotaDatabase db(kDbFile);
|
| + EXPECT_TRUE(db.LazyOpen(true));
|
| + EXPECT_TRUE(db.db_.get());
|
| +
|
| + typedef EntryVerifier<QuotaTableEntry> Verifier;
|
| + Verifier verifier(entries, entries + ARRAYSIZE_UNSAFE(entries));
|
| + EXPECT_TRUE(db.DumpQuotaTable(
|
| + new QuotaTableCallback(
|
| + base::Bind(&Verifier::Run,
|
| + base::Unretained(&verifier)))));
|
| + EXPECT_TRUE(verifier.table.empty());
|
| + }
|
| +
|
| void HostQuota(const FilePath& kDbFile) {
|
| QuotaDatabase db(kDbFile);
|
| ASSERT_TRUE(db.LazyOpen(true));
|
| @@ -223,7 +189,7 @@ class QuotaDatabaseTest : public testing::Test {
|
| kOrigin1, kStorageTypeTemporary, base::Time::Now()));
|
|
|
| // Delete origin/type last access time information.
|
| - EXPECT_TRUE(db.DeleteOriginLastAccessTime(kOrigin3, kStorageTypeTemporary));
|
| + EXPECT_TRUE(db.DeleteOriginInfo(kOrigin3, kStorageTypeTemporary));
|
|
|
| // Querying again to see if the deletion has worked.
|
| exceptions.clear();
|
| @@ -238,7 +204,77 @@ class QuotaDatabaseTest : public testing::Test {
|
| EXPECT_TRUE(origin.is_empty());
|
| }
|
|
|
| - void RegisterOrigins(const FilePath& kDbFile) {
|
| + void OriginLastModifiedSince(const FilePath& kDbFile) {
|
| + QuotaDatabase db(kDbFile);
|
| + ASSERT_TRUE(db.LazyOpen(true));
|
| +
|
| + std::set<GURL> origins;
|
| + EXPECT_TRUE(db.GetOriginsModifiedSince(
|
| + kStorageTypeTemporary, &origins, base::Time()));
|
| + EXPECT_TRUE(origins.empty());
|
| +
|
| + const GURL kOrigin1("http://a/");
|
| + const GURL kOrigin2("http://b/");
|
| + const GURL kOrigin3("http://c/");
|
| +
|
| + // Report last mod time for the test origins.
|
| + EXPECT_TRUE(db.SetOriginLastModifiedTime(
|
| + kOrigin1, kStorageTypeTemporary, base::Time::FromInternalValue(10)));
|
| + EXPECT_TRUE(db.SetOriginLastModifiedTime(
|
| + kOrigin2, kStorageTypeTemporary, base::Time::FromInternalValue(20)));
|
| + EXPECT_TRUE(db.SetOriginLastModifiedTime(
|
| + kOrigin3, kStorageTypeTemporary, base::Time::FromInternalValue(30)));
|
| +
|
| + EXPECT_TRUE(db.GetOriginsModifiedSince(
|
| + kStorageTypeTemporary, &origins, base::Time::FromInternalValue(15)));
|
| + EXPECT_EQ(2U, origins.size());
|
| + EXPECT_EQ(0U, origins.count(kOrigin1));
|
| + EXPECT_EQ(1U, origins.count(kOrigin2));
|
| + EXPECT_EQ(1U, origins.count(kOrigin3));
|
| +
|
| + EXPECT_TRUE(db.GetOriginsModifiedSince(
|
| + kStorageTypeTemporary, &origins, base::Time::FromInternalValue(25)));
|
| + EXPECT_EQ(1U, origins.size());
|
| + EXPECT_EQ(0U, origins.count(kOrigin1));
|
| + EXPECT_EQ(0U, origins.count(kOrigin2));
|
| + EXPECT_EQ(1U, origins.count(kOrigin3));
|
| +
|
| + EXPECT_TRUE(db.GetOriginsModifiedSince(
|
| + kStorageTypeTemporary, &origins, base::Time::FromInternalValue(35)));
|
| + EXPECT_TRUE(origins.empty());
|
| +
|
| + // Update origin1's mod time but for persistent storage.
|
| + EXPECT_TRUE(db.SetOriginLastModifiedTime(
|
| + kOrigin1, kStorageTypePersistent, base::Time::FromInternalValue(40)));
|
| +
|
| + // Must have no effects on temporary origins info.
|
| + EXPECT_TRUE(db.GetOriginsModifiedSince(
|
| + kStorageTypeTemporary, &origins, base::Time::FromInternalValue(15)));
|
| + EXPECT_EQ(2U, origins.size());
|
| + EXPECT_EQ(0U, origins.count(kOrigin1));
|
| + EXPECT_EQ(1U, origins.count(kOrigin2));
|
| + EXPECT_EQ(1U, origins.count(kOrigin3));
|
| +
|
| + // One more update for persistent origin2.
|
| + EXPECT_TRUE(db.SetOriginLastModifiedTime(
|
| + kOrigin2, kStorageTypePersistent, base::Time::FromInternalValue(50)));
|
| +
|
| + EXPECT_TRUE(db.GetOriginsModifiedSince(
|
| + kStorageTypePersistent, &origins, base::Time::FromInternalValue(35)));
|
| + EXPECT_EQ(2U, origins.size());
|
| + EXPECT_EQ(1U, origins.count(kOrigin1));
|
| + EXPECT_EQ(1U, origins.count(kOrigin2));
|
| + EXPECT_EQ(0U, origins.count(kOrigin3));
|
| +
|
| + EXPECT_TRUE(db.GetOriginsModifiedSince(
|
| + kStorageTypePersistent, &origins, base::Time::FromInternalValue(45)));
|
| + EXPECT_EQ(1U, origins.size());
|
| + EXPECT_EQ(0U, origins.count(kOrigin1));
|
| + EXPECT_EQ(1U, origins.count(kOrigin2));
|
| + EXPECT_EQ(0U, origins.count(kOrigin3));
|
| + }
|
| +
|
| + void RegisterInitialOriginInfo(const FilePath& kDbFile) {
|
| QuotaDatabase db(kDbFile);
|
|
|
| const GURL kOrigins[] = {
|
| @@ -247,9 +283,7 @@ class QuotaDatabaseTest : public testing::Test {
|
| GURL("http://c/") };
|
| std::set<GURL> origins(kOrigins, kOrigins + ARRAYSIZE_UNSAFE(kOrigins));
|
|
|
| - EXPECT_TRUE(db.RegisterOrigins(origins,
|
| - kStorageTypeTemporary,
|
| - base::Time()));
|
| + EXPECT_TRUE(db.RegisterInitialOriginInfo(origins, kStorageTypeTemporary));
|
|
|
| int used_count = -1;
|
| EXPECT_TRUE(db.FindOriginUsedCount(GURL("http://a/"),
|
| @@ -266,9 +300,7 @@ class QuotaDatabaseTest : public testing::Test {
|
| &used_count));
|
| EXPECT_EQ(1, used_count);
|
|
|
| - EXPECT_TRUE(db.RegisterOrigins(origins,
|
| - kStorageTypeTemporary,
|
| - base::Time()));
|
| + EXPECT_TRUE(db.RegisterInitialOriginInfo(origins, kStorageTypeTemporary));
|
|
|
| used_count = -1;
|
| EXPECT_TRUE(db.FindOriginUsedCount(GURL("http://a/"),
|
| @@ -301,7 +333,9 @@ class QuotaDatabaseTest : public testing::Test {
|
| QuotaTableEntry* end = kTableEntries + ARRAYSIZE_UNSAFE(kTableEntries);
|
|
|
| QuotaDatabase db(kDbFile);
|
| - EXPECT_TRUE(AssignQuotaTable(&db, begin, end));
|
| + EXPECT_TRUE(db.LazyOpen(true));
|
| + AssignQuotaTable(db.db_.get(), begin, end);
|
| + db.Commit();
|
|
|
| typedef EntryVerifier<QuotaTableEntry> Verifier;
|
| Verifier verifier(begin, end);
|
| @@ -312,28 +346,134 @@ class QuotaDatabaseTest : public testing::Test {
|
| EXPECT_TRUE(verifier.table.empty());
|
| }
|
|
|
| - void DumpLastAccessTimeTable(const FilePath& kDbFile) {
|
| + void DumpOriginInfoTable(const FilePath& kDbFile) {
|
| base::Time now(base::Time::Now());
|
| - LastAccessTimeTableEntry kTableEntries[] = {
|
| - {GURL("http://go/"), kStorageTypeTemporary, 2147483647, now},
|
| - {GURL("http://oo/"), kStorageTypeTemporary, 0, now},
|
| - {GURL("http://gle/"), kStorageTypeTemporary, 1, now},
|
| + OriginInfoTableEntry kTableEntries[] = {
|
| + {GURL("http://go/"), kStorageTypeTemporary, 2147483647, now, now},
|
| + {GURL("http://oo/"), kStorageTypeTemporary, 0, now, now},
|
| + {GURL("http://gle/"), kStorageTypeTemporary, 1, now, now},
|
| };
|
| - LastAccessTimeTableEntry* begin = kTableEntries;
|
| - LastAccessTimeTableEntry* end = kTableEntries +
|
| - ARRAYSIZE_UNSAFE(kTableEntries);
|
| + OriginInfoTableEntry* begin = kTableEntries;
|
| + OriginInfoTableEntry* end = kTableEntries + ARRAYSIZE_UNSAFE(kTableEntries);
|
|
|
| QuotaDatabase db(kDbFile);
|
| - EXPECT_TRUE(AssignLastAccessTimeTable(&db, begin, end));
|
| + EXPECT_TRUE(db.LazyOpen(true));
|
| + AssignOriginInfoTable(db.db_.get(), begin, end);
|
| + db.Commit();
|
|
|
| - typedef EntryVerifier<LastAccessTimeTableEntry> Verifier;
|
| + typedef EntryVerifier<OriginInfoTableEntry> Verifier;
|
| Verifier verifier(begin, end);
|
| - EXPECT_TRUE(db.DumpLastAccessTimeTable(
|
| - new LastAccessTimeTableCallback(
|
| + EXPECT_TRUE(db.DumpOriginInfoTable(
|
| + new OriginInfoTableCallback(
|
| base::Bind(&Verifier::Run,
|
| base::Unretained(&verifier)))));
|
| EXPECT_TRUE(verifier.table.empty());
|
| }
|
| +
|
| + private:
|
| + template <typename Iterator>
|
| + void AssignQuotaTable(sql::Connection* db, Iterator itr, Iterator end) {
|
| + ASSERT_NE(db, (sql::Connection*)NULL);
|
| + for (; itr != end; ++itr) {
|
| + const char* kSql =
|
| + "INSERT INTO HostQuotaTable"
|
| + " (host, type, quota)"
|
| + " VALUES (?, ?, ?)";
|
| + sql::Statement statement;
|
| + statement.Assign(db->GetCachedStatement(SQL_FROM_HERE, kSql));
|
| + ASSERT_TRUE(statement.is_valid());
|
| +
|
| + statement.BindString(0, itr->host);
|
| + statement.BindInt(1, static_cast<int>(itr->type));
|
| + statement.BindInt64(2, itr->quota);
|
| + EXPECT_TRUE(statement.Run());
|
| + }
|
| + }
|
| +
|
| + template <typename Iterator>
|
| + void AssignOriginInfoTable(sql::Connection* db, Iterator itr, Iterator end) {
|
| + ASSERT_NE(db, (sql::Connection*)NULL);
|
| + for (; itr != end; ++itr) {
|
| + const char* kSql =
|
| + "INSERT INTO OriginInfoTable"
|
| + " (origin, type, used_count, last_access_time, last_modified_time)"
|
| + " VALUES (?, ?, ?, ?, ?)";
|
| + sql::Statement statement;
|
| + statement.Assign(db->GetCachedStatement(SQL_FROM_HERE, kSql));
|
| + ASSERT_TRUE(statement.is_valid());
|
| +
|
| + statement.BindString(0, itr->origin.spec());
|
| + statement.BindInt(1, static_cast<int>(itr->type));
|
| + statement.BindInt(2, itr->used_count);
|
| + statement.BindInt64(3, itr->last_access_time.ToInternalValue());
|
| + statement.BindInt64(4, itr->last_modified_time.ToInternalValue());
|
| + EXPECT_TRUE(statement.Run());
|
| + }
|
| + }
|
| +
|
| + bool OpenDatabase(sql::Connection* db, const FilePath& kDbFile) {
|
| + if (kDbFile.empty()) {
|
| + db->OpenInMemory();
|
| + return true;
|
| + }
|
| + if (!file_util::CreateDirectory(kDbFile.DirName()))
|
| + return false;
|
| + if (!db->Open(kDbFile))
|
| + return false;
|
| + db->Preload();
|
| + return true;
|
| + }
|
| +
|
| + // Create V2 database and populate some data.
|
| + void CreateV2Database(
|
| + const FilePath& kDbFile,
|
| + const QuotaTableEntry* entries,
|
| + size_t entries_size) {
|
| + scoped_ptr<sql::Connection> db(new sql::Connection);
|
| + scoped_ptr<sql::MetaTable> meta_table(new sql::MetaTable);
|
| +
|
| + // V2 schema definitions.
|
| + static const int kCurrentVersion = 2;
|
| + static const int kCompatibleVersion = 2;
|
| + static const char kHostQuotaTable[] = "HostQuotaTable";
|
| + static const char kOriginLastAccessTable[] = "OriginLastAccessTable";
|
| + static const QuotaDatabase::TableSchema kTables[] = {
|
| + { kHostQuotaTable,
|
| + "(host TEXT NOT NULL,"
|
| + " type INTEGER NOT NULL,"
|
| + " quota INTEGER,"
|
| + " UNIQUE(host, type))" },
|
| + { kOriginLastAccessTable,
|
| + "(origin TEXT NOT NULL,"
|
| + " type INTEGER NOT NULL,"
|
| + " used_count INTEGER,"
|
| + " last_access_time INTEGER,"
|
| + " UNIQUE(origin, type))" },
|
| + };
|
| + static const QuotaDatabase::IndexSchema kIndexes[] = {
|
| + { "HostIndex",
|
| + kHostQuotaTable,
|
| + "(host)",
|
| + false },
|
| + { "OriginLastAccessIndex",
|
| + kOriginLastAccessTable,
|
| + "(origin, last_access_time)",
|
| + false },
|
| + };
|
| +
|
| + ASSERT_TRUE(OpenDatabase(db.get(), kDbFile));
|
| + EXPECT_TRUE(QuotaDatabase::CreateSchema(
|
| + db.get(), meta_table.get(),
|
| + kCurrentVersion, kCompatibleVersion,
|
| + kTables, ARRAYSIZE_UNSAFE(kTables),
|
| + kIndexes, ARRAYSIZE_UNSAFE(kIndexes)));
|
| +
|
| + // V2 and V3 QuotaTable are compatible, so we can simply use
|
| + // AssignQuotaTable to poplulate v2 database here.
|
| + db->BeginTransaction();
|
| + AssignQuotaTable(db.get(), entries, entries + entries_size);
|
| + db->CommitTransaction();
|
| + }
|
| };
|
|
|
| TEST_F(QuotaDatabaseTest, LazyOpen) {
|
| @@ -344,6 +484,13 @@ TEST_F(QuotaDatabaseTest, LazyOpen) {
|
| LazyOpen(FilePath());
|
| }
|
|
|
| +TEST_F(QuotaDatabaseTest, UpgradeSchema) {
|
| + ScopedTempDir data_dir;
|
| + ASSERT_TRUE(data_dir.CreateUniqueTempDir());
|
| + const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db");
|
| + UpgradeSchemaV2toV3(kDbFile);
|
| +}
|
| +
|
| TEST_F(QuotaDatabaseTest, HostQuota) {
|
| ScopedTempDir data_dir;
|
| ASSERT_TRUE(data_dir.CreateUniqueTempDir());
|
| @@ -368,6 +515,14 @@ TEST_F(QuotaDatabaseTest, OriginLastAccessTimeLRU) {
|
| OriginLastAccessTimeLRU(FilePath());
|
| }
|
|
|
| +TEST_F(QuotaDatabaseTest, OriginLastModifiedSince) {
|
| + ScopedTempDir data_dir;
|
| + ASSERT_TRUE(data_dir.CreateUniqueTempDir());
|
| + const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db");
|
| + OriginLastModifiedSince(kDbFile);
|
| + OriginLastModifiedSince(FilePath());
|
| +}
|
| +
|
| TEST_F(QuotaDatabaseTest, BootstrapFlag) {
|
| ScopedTempDir data_dir;
|
| ASSERT_TRUE(data_dir.CreateUniqueTempDir());
|
| @@ -382,12 +537,12 @@ TEST_F(QuotaDatabaseTest, BootstrapFlag) {
|
| EXPECT_FALSE(db.IsOriginDatabaseBootstrapped());
|
| }
|
|
|
| -TEST_F(QuotaDatabaseTest, RegisterOrigins) {
|
| +TEST_F(QuotaDatabaseTest, RegisterInitialOriginInfo) {
|
| ScopedTempDir data_dir;
|
| ASSERT_TRUE(data_dir.CreateUniqueTempDir());
|
| const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db");
|
| - RegisterOrigins(kDbFile);
|
| - RegisterOrigins(FilePath());
|
| + RegisterInitialOriginInfo(kDbFile);
|
| + RegisterInitialOriginInfo(FilePath());
|
| }
|
|
|
| TEST_F(QuotaDatabaseTest, DumpQuotaTable) {
|
| @@ -398,11 +553,11 @@ TEST_F(QuotaDatabaseTest, DumpQuotaTable) {
|
| DumpQuotaTable(FilePath());
|
| }
|
|
|
| -TEST_F(QuotaDatabaseTest, DumpLastAccessTimeTable) {
|
| +TEST_F(QuotaDatabaseTest, DumpOriginInfoTable) {
|
| ScopedTempDir data_dir;
|
| ASSERT_TRUE(data_dir.CreateUniqueTempDir());
|
| const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db");
|
| - DumpLastAccessTimeTable(kDbFile);
|
| - DumpLastAccessTimeTable(FilePath());
|
| + DumpOriginInfoTable(kDbFile);
|
| + DumpOriginInfoTable(FilePath());
|
| }
|
| } // namespace quota
|
|
|