Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 #include <iterator> | 6 #include <iterator> |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "app/sql/connection.h" | 9 #include "app/sql/connection.h" |
| 10 #include "app/sql/meta_table.h" | |
| 10 #include "app/sql/statement.h" | 11 #include "app/sql/statement.h" |
| 11 #include "app/sql/transaction.h" | 12 #include "app/sql/transaction.h" |
| 12 #include "base/bind.h" | 13 #include "base/bind.h" |
| 13 #include "base/callback.h" | 14 #include "base/callback.h" |
| 14 #include "base/file_util.h" | 15 #include "base/file_util.h" |
| 15 #include "base/scoped_temp_dir.h" | 16 #include "base/scoped_temp_dir.h" |
| 16 #include "googleurl/src/gurl.h" | 17 #include "googleurl/src/gurl.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 18 #include "webkit/quota/mock_special_storage_policy.h" | 19 #include "webkit/quota/mock_special_storage_policy.h" |
| 19 #include "webkit/quota/quota_database.h" | 20 #include "webkit/quota/quota_database.h" |
| 20 | 21 |
| 22 namespace quota { | |
| 21 namespace { | 23 namespace { |
| 22 | 24 |
| 23 const base::Time kZeroTime; | 25 const base::Time kZeroTime; |
| 24 | 26 |
| 25 class TestErrorDelegate : public sql::ErrorDelegate { | 27 class TestErrorDelegate : public sql::ErrorDelegate { |
| 26 public: | 28 public: |
| 27 virtual ~TestErrorDelegate() { } | 29 virtual ~TestErrorDelegate() { } |
| 28 virtual int OnError( | 30 virtual int OnError( |
| 29 int error, sql::Connection* connection, sql::Statement* stmt) { | 31 int error, sql::Connection* connection, sql::Statement* stmt) { |
| 30 return error; | 32 return error; |
| 31 } | 33 } |
| 32 }; | 34 }; |
| 35 | |
| 33 } // namespace | 36 } // namespace |
| 34 | 37 |
| 35 namespace quota { | 38 namespace v2 { |
| 39 | |
| 40 // Definitions for version 2 database schema. | |
| 41 | |
| 42 const int kCurrentVersion = 2; | |
| 43 const int kCompatibleVersion = 2; | |
| 44 | |
| 45 const char kHostQuotaTable[] = "HostQuotaTable"; | |
| 46 const char kOriginLastAccessTable[] = "OriginLastAccessTable"; | |
| 47 | |
| 48 const QuotaDatabase::TableSchema kTables[] = { | |
| 49 { kHostQuotaTable, | |
| 50 "(host TEXT NOT NULL," | |
| 51 " type INTEGER NOT NULL," | |
| 52 " quota INTEGER," | |
| 53 " UNIQUE(host, type))" }, | |
| 54 { kOriginLastAccessTable, | |
| 55 "(origin TEXT NOT NULL," | |
| 56 " type INTEGER NOT NULL," | |
| 57 " used_count INTEGER," | |
| 58 " last_access_time INTEGER," | |
| 59 " UNIQUE(origin, type))" }, | |
| 60 }; | |
| 61 | |
| 62 const QuotaDatabase::IndexSchema kIndexes[] = { | |
| 63 { "HostIndex", | |
| 64 kHostQuotaTable, | |
| 65 "(host)", | |
| 66 false }, | |
| 67 { "OriginLastAccessIndex", | |
| 68 kOriginLastAccessTable, | |
| 69 "(origin, last_access_time)", | |
| 70 false }, | |
| 71 }; | |
| 72 | |
| 73 } // namespace v2 | |
| 36 | 74 |
| 37 class QuotaDatabaseTest : public testing::Test { | 75 class QuotaDatabaseTest : public testing::Test { |
| 38 protected: | 76 protected: |
| 39 typedef QuotaDatabase::QuotaTableEntry QuotaTableEntry; | 77 typedef QuotaDatabase::QuotaTableEntry QuotaTableEntry; |
| 40 typedef QuotaDatabase::QuotaTableCallback QuotaTableCallback; | 78 typedef QuotaDatabase::QuotaTableCallback QuotaTableCallback; |
| 41 typedef QuotaDatabase::LastAccessTimeTableEntry LastAccessTimeTableEntry; | 79 typedef QuotaDatabase::OriginInfoTableEntry OriginInfoTableEntry; |
| 42 typedef QuotaDatabase::LastAccessTimeTableCallback | 80 typedef QuotaDatabase::OriginInfoTableCallback |
| 43 LastAccessTimeTableCallback; | 81 OriginInfoTableCallback; |
| 44 | 82 |
| 45 template <typename Iterator> | |
| 46 bool AssignQuotaTable( | |
| 47 QuotaDatabase* quota_database, Iterator itr, Iterator end) { | |
| 48 if (!quota_database->LazyOpen(true)) | |
| 49 return false; | |
| 50 | |
| 51 for (; itr != end; ++itr) { | |
| 52 const char* kSql = | |
| 53 "INSERT INTO HostQuotaTable" | |
| 54 " (host, type, quota)" | |
| 55 " VALUES (?, ?, ?)"; | |
| 56 sql::Statement statement; | |
| 57 statement.Assign( | |
| 58 quota_database->db_->GetCachedStatement( | |
| 59 SQL_FROM_HERE, kSql)); | |
| 60 EXPECT_TRUE(statement.is_valid()); | |
| 61 | |
| 62 statement.BindString(0, itr->host); | |
| 63 statement.BindInt(1, static_cast<int>(itr->type)); | |
| 64 statement.BindInt64(2, itr->quota); | |
| 65 if (!statement.Run()) | |
| 66 return false; | |
| 67 } | |
| 68 | |
| 69 quota_database->Commit(); | |
| 70 return true; | |
| 71 } | |
| 72 | |
| 73 template <typename Iterator> | |
| 74 bool AssignLastAccessTimeTable( | |
| 75 QuotaDatabase* quota_database, Iterator itr, Iterator end) { | |
| 76 if (!quota_database->LazyOpen(true)) | |
| 77 return false; | |
| 78 | |
| 79 for (; itr != end; ++itr) { | |
| 80 const char* kSql = | |
| 81 "INSERT INTO OriginLastAccessTable" | |
| 82 " (origin, type, used_count, last_access_time)" | |
| 83 " VALUES (?, ?, ?, ?)"; | |
| 84 sql::Statement statement; | |
| 85 statement.Assign( | |
| 86 quota_database->db_->GetCachedStatement( | |
| 87 SQL_FROM_HERE, kSql)); | |
| 88 EXPECT_TRUE(statement.is_valid()); | |
| 89 | |
| 90 statement.BindString(0, itr->origin.spec()); | |
| 91 statement.BindInt(1, static_cast<int>(itr->type)); | |
| 92 statement.BindInt(2, itr->used_count); | |
| 93 statement.BindInt64(3, itr->last_access_time.ToInternalValue()); | |
| 94 if (!statement.Run()) | |
| 95 return false; | |
| 96 } | |
| 97 | |
| 98 quota_database->Commit(); | |
| 99 return true; | |
| 100 } | |
| 101 | 83 |
| 102 void LazyOpen(const FilePath& kDbFile) { | 84 void LazyOpen(const FilePath& kDbFile) { |
| 103 QuotaDatabase db(kDbFile); | 85 QuotaDatabase db(kDbFile); |
| 104 EXPECT_FALSE(db.LazyOpen(false)); | 86 EXPECT_FALSE(db.LazyOpen(false)); |
| 105 ASSERT_TRUE(db.LazyOpen(true)); | 87 ASSERT_TRUE(db.LazyOpen(true)); |
| 106 EXPECT_TRUE(db.db_.get()); | 88 EXPECT_TRUE(db.db_.get()); |
| 107 EXPECT_TRUE(kDbFile.empty() || file_util::PathExists(kDbFile)); | 89 EXPECT_TRUE(kDbFile.empty() || file_util::PathExists(kDbFile)); |
| 108 } | 90 } |
| 109 | 91 |
| 92 void UpgradeSchema(const FilePath& kDbFile) { | |
|
michaeln
2011/07/01 00:17:39
Might be good to be explicit about what versions y
kinuko
2011/07/04 07:43:52
Done.
| |
| 93 const QuotaTableEntry entries[] = { | |
| 94 { "a", kStorageTypeTemporary, 1 }, | |
| 95 { "b", kStorageTypeTemporary, 2 }, | |
| 96 { "c", kStorageTypePersistent, 3 }, | |
| 97 }; | |
| 98 | |
| 99 CreateV2Database(kDbFile, entries, ARRAYSIZE_UNSAFE(entries)); | |
| 100 | |
| 101 QuotaDatabase db(kDbFile); | |
| 102 EXPECT_TRUE(db.LazyOpen(true)); | |
| 103 EXPECT_TRUE(db.db_.get()); | |
| 104 | |
| 105 typedef EntryVerifier<QuotaTableEntry> Verifier; | |
| 106 Verifier verifier(entries, entries + ARRAYSIZE_UNSAFE(entries)); | |
| 107 EXPECT_TRUE(db.DumpQuotaTable( | |
| 108 new QuotaTableCallback( | |
| 109 base::Bind(&Verifier::Run, | |
| 110 base::Unretained(&verifier))))); | |
| 111 EXPECT_TRUE(verifier.table.empty()); | |
|
michaeln
2011/07/01 00:17:39
it took me a moment to realize how the verifier wo
| |
| 112 } | |
| 113 | |
| 110 void HostQuota(const FilePath& kDbFile) { | 114 void HostQuota(const FilePath& kDbFile) { |
| 111 QuotaDatabase db(kDbFile); | 115 QuotaDatabase db(kDbFile); |
| 112 ASSERT_TRUE(db.LazyOpen(true)); | 116 ASSERT_TRUE(db.LazyOpen(true)); |
| 113 | 117 |
| 114 const char* kHost = "foo.com"; | 118 const char* kHost = "foo.com"; |
| 115 const int kQuota1 = 13579; | 119 const int kQuota1 = 13579; |
| 116 const int kQuota2 = kQuota1 + 1024; | 120 const int kQuota2 = kQuota1 + 1024; |
| 117 | 121 |
| 118 int64 quota = -1; | 122 int64 quota = -1; |
| 119 EXPECT_FALSE(db.GetHostQuota(kHost, kStorageTypeTemporary, "a)); | 123 EXPECT_FALSE(db.GetHostQuota(kHost, kStorageTypeTemporary, "a)); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 216 | 220 |
| 217 exceptions.insert(kOrigin3); | 221 exceptions.insert(kOrigin3); |
| 218 EXPECT_TRUE(db.GetLRUOrigin(kStorageTypeTemporary, exceptions, | 222 EXPECT_TRUE(db.GetLRUOrigin(kStorageTypeTemporary, exceptions, |
| 219 NULL, &origin)); | 223 NULL, &origin)); |
| 220 EXPECT_TRUE(origin.is_empty()); | 224 EXPECT_TRUE(origin.is_empty()); |
| 221 | 225 |
| 222 EXPECT_TRUE(db.SetOriginLastAccessTime( | 226 EXPECT_TRUE(db.SetOriginLastAccessTime( |
| 223 kOrigin1, kStorageTypeTemporary, base::Time::Now())); | 227 kOrigin1, kStorageTypeTemporary, base::Time::Now())); |
| 224 | 228 |
| 225 // Delete origin/type last access time information. | 229 // Delete origin/type last access time information. |
| 226 EXPECT_TRUE(db.DeleteOriginLastAccessTime(kOrigin3, kStorageTypeTemporary)); | 230 EXPECT_TRUE(db.DeleteOriginInfo(kOrigin3, kStorageTypeTemporary)); |
| 227 | 231 |
| 228 // Querying again to see if the deletion has worked. | 232 // Querying again to see if the deletion has worked. |
| 229 exceptions.clear(); | 233 exceptions.clear(); |
| 230 EXPECT_TRUE(db.GetLRUOrigin(kStorageTypeTemporary, exceptions, | 234 EXPECT_TRUE(db.GetLRUOrigin(kStorageTypeTemporary, exceptions, |
| 231 NULL, &origin)); | 235 NULL, &origin)); |
| 232 EXPECT_EQ(kOrigin2.spec(), origin.spec()); | 236 EXPECT_EQ(kOrigin2.spec(), origin.spec()); |
| 233 | 237 |
| 234 exceptions.insert(kOrigin1); | 238 exceptions.insert(kOrigin1); |
| 235 exceptions.insert(kOrigin2); | 239 exceptions.insert(kOrigin2); |
| 236 EXPECT_TRUE(db.GetLRUOrigin(kStorageTypeTemporary, exceptions, | 240 EXPECT_TRUE(db.GetLRUOrigin(kStorageTypeTemporary, exceptions, |
| 237 NULL, &origin)); | 241 NULL, &origin)); |
| 238 EXPECT_TRUE(origin.is_empty()); | 242 EXPECT_TRUE(origin.is_empty()); |
| 239 } | 243 } |
| 240 | 244 |
| 241 void RegisterOrigins(const FilePath& kDbFile) { | 245 void OriginLastModifiedSince(const FilePath& kDbFile) { |
| 246 QuotaDatabase db(kDbFile); | |
| 247 ASSERT_TRUE(db.LazyOpen(true)); | |
| 248 | |
| 249 std::set<GURL> origins; | |
| 250 EXPECT_TRUE(db.GetOriginsModifiedSince( | |
| 251 kStorageTypeTemporary, &origins, base::Time())); | |
| 252 EXPECT_TRUE(origins.empty()); | |
| 253 | |
| 254 const GURL kOrigin1("http://a/"); | |
| 255 const GURL kOrigin2("http://b/"); | |
| 256 const GURL kOrigin3("http://c/"); | |
| 257 | |
| 258 // Report last mod time for the test origins. | |
| 259 EXPECT_TRUE(db.SetOriginLastModifiedTime( | |
| 260 kOrigin1, kStorageTypeTemporary, base::Time::FromInternalValue(10))); | |
| 261 EXPECT_TRUE(db.SetOriginLastModifiedTime( | |
| 262 kOrigin2, kStorageTypeTemporary, base::Time::FromInternalValue(20))); | |
| 263 EXPECT_TRUE(db.SetOriginLastModifiedTime( | |
| 264 kOrigin3, kStorageTypeTemporary, base::Time::FromInternalValue(30))); | |
| 265 | |
| 266 EXPECT_TRUE(db.GetOriginsModifiedSince( | |
| 267 kStorageTypeTemporary, &origins, base::Time::FromInternalValue(15))); | |
| 268 EXPECT_EQ(2U, origins.size()); | |
| 269 EXPECT_EQ(0U, origins.count(kOrigin1)); | |
| 270 EXPECT_EQ(1U, origins.count(kOrigin2)); | |
| 271 EXPECT_EQ(1U, origins.count(kOrigin3)); | |
| 272 | |
| 273 EXPECT_TRUE(db.GetOriginsModifiedSince( | |
| 274 kStorageTypeTemporary, &origins, base::Time::FromInternalValue(25))); | |
| 275 EXPECT_EQ(1U, origins.size()); | |
| 276 EXPECT_EQ(0U, origins.count(kOrigin1)); | |
| 277 EXPECT_EQ(0U, origins.count(kOrigin2)); | |
| 278 EXPECT_EQ(1U, origins.count(kOrigin3)); | |
| 279 | |
| 280 EXPECT_TRUE(db.GetOriginsModifiedSince( | |
| 281 kStorageTypeTemporary, &origins, base::Time::FromInternalValue(35))); | |
| 282 EXPECT_TRUE(origins.empty()); | |
| 283 | |
| 284 // Update origin1's mod time but for persistent storage. | |
| 285 EXPECT_TRUE(db.SetOriginLastModifiedTime( | |
| 286 kOrigin1, kStorageTypePersistent, base::Time::FromInternalValue(40))); | |
| 287 | |
| 288 // Must have no effects on temporary origins info. | |
| 289 EXPECT_TRUE(db.GetOriginsModifiedSince( | |
| 290 kStorageTypeTemporary, &origins, base::Time::FromInternalValue(15))); | |
| 291 EXPECT_EQ(2U, origins.size()); | |
| 292 EXPECT_EQ(0U, origins.count(kOrigin1)); | |
| 293 EXPECT_EQ(1U, origins.count(kOrigin2)); | |
| 294 EXPECT_EQ(1U, origins.count(kOrigin3)); | |
| 295 | |
| 296 // One more update for persistent origin2. | |
| 297 EXPECT_TRUE(db.SetOriginLastModifiedTime( | |
| 298 kOrigin2, kStorageTypePersistent, base::Time::FromInternalValue(50))); | |
| 299 | |
| 300 EXPECT_TRUE(db.GetOriginsModifiedSince( | |
| 301 kStorageTypePersistent, &origins, base::Time::FromInternalValue(35))); | |
| 302 EXPECT_EQ(2U, origins.size()); | |
| 303 EXPECT_EQ(1U, origins.count(kOrigin1)); | |
| 304 EXPECT_EQ(1U, origins.count(kOrigin2)); | |
| 305 EXPECT_EQ(0U, origins.count(kOrigin3)); | |
| 306 | |
| 307 EXPECT_TRUE(db.GetOriginsModifiedSince( | |
| 308 kStorageTypePersistent, &origins, base::Time::FromInternalValue(45))); | |
| 309 EXPECT_EQ(1U, origins.size()); | |
| 310 EXPECT_EQ(0U, origins.count(kOrigin1)); | |
| 311 EXPECT_EQ(1U, origins.count(kOrigin2)); | |
| 312 EXPECT_EQ(0U, origins.count(kOrigin3)); | |
| 313 } | |
| 314 | |
| 315 void RegisterInitialOriginInfo(const FilePath& kDbFile) { | |
| 242 QuotaDatabase db(kDbFile); | 316 QuotaDatabase db(kDbFile); |
| 243 | 317 |
| 244 const GURL kOrigins[] = { | 318 const GURL kOrigins[] = { |
| 245 GURL("http://a/"), | 319 GURL("http://a/"), |
| 246 GURL("http://b/"), | 320 GURL("http://b/"), |
| 247 GURL("http://c/") }; | 321 GURL("http://c/") }; |
| 248 std::set<GURL> origins(kOrigins, kOrigins + ARRAYSIZE_UNSAFE(kOrigins)); | 322 std::set<GURL> origins(kOrigins, kOrigins + ARRAYSIZE_UNSAFE(kOrigins)); |
| 249 | 323 |
| 250 EXPECT_TRUE(db.RegisterOrigins(origins, | 324 EXPECT_TRUE(db.RegisterInitialOriginInfo(origins, kStorageTypeTemporary)); |
| 251 kStorageTypeTemporary, | |
| 252 base::Time())); | |
| 253 | 325 |
| 254 int used_count = -1; | 326 int used_count = -1; |
| 255 EXPECT_TRUE(db.FindOriginUsedCount(GURL("http://a/"), | 327 EXPECT_TRUE(db.FindOriginUsedCount(GURL("http://a/"), |
| 256 kStorageTypeTemporary, | 328 kStorageTypeTemporary, |
| 257 &used_count)); | 329 &used_count)); |
| 258 EXPECT_EQ(0, used_count); | 330 EXPECT_EQ(0, used_count); |
| 259 | 331 |
| 260 EXPECT_TRUE(db.SetOriginLastAccessTime( | 332 EXPECT_TRUE(db.SetOriginLastAccessTime( |
| 261 GURL("http://a/"), kStorageTypeTemporary, | 333 GURL("http://a/"), kStorageTypeTemporary, |
| 262 base::Time::FromDoubleT(1.0))); | 334 base::Time::FromDoubleT(1.0))); |
| 263 used_count = -1; | 335 used_count = -1; |
| 264 EXPECT_TRUE(db.FindOriginUsedCount(GURL("http://a/"), | 336 EXPECT_TRUE(db.FindOriginUsedCount(GURL("http://a/"), |
| 265 kStorageTypeTemporary, | 337 kStorageTypeTemporary, |
| 266 &used_count)); | 338 &used_count)); |
| 267 EXPECT_EQ(1, used_count); | 339 EXPECT_EQ(1, used_count); |
| 268 | 340 |
| 269 EXPECT_TRUE(db.RegisterOrigins(origins, | 341 EXPECT_TRUE(db.RegisterInitialOriginInfo(origins, kStorageTypeTemporary)); |
| 270 kStorageTypeTemporary, | |
| 271 base::Time())); | |
| 272 | 342 |
| 273 used_count = -1; | 343 used_count = -1; |
| 274 EXPECT_TRUE(db.FindOriginUsedCount(GURL("http://a/"), | 344 EXPECT_TRUE(db.FindOriginUsedCount(GURL("http://a/"), |
| 275 kStorageTypeTemporary, | 345 kStorageTypeTemporary, |
| 276 &used_count)); | 346 &used_count)); |
| 277 EXPECT_EQ(1, used_count); | 347 EXPECT_EQ(1, used_count); |
| 278 } | 348 } |
| 279 | 349 |
| 280 template <typename EntryType> | 350 template <typename EntryType> |
| 281 struct EntryVerifier { | 351 struct EntryVerifier { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 294 void DumpQuotaTable(const FilePath& kDbFile) { | 364 void DumpQuotaTable(const FilePath& kDbFile) { |
| 295 QuotaTableEntry kTableEntries[] = { | 365 QuotaTableEntry kTableEntries[] = { |
| 296 {"http://go/", kStorageTypeTemporary, 1}, | 366 {"http://go/", kStorageTypeTemporary, 1}, |
| 297 {"http://oo/", kStorageTypeTemporary, 2}, | 367 {"http://oo/", kStorageTypeTemporary, 2}, |
| 298 {"http://gle/", kStorageTypePersistent, 3} | 368 {"http://gle/", kStorageTypePersistent, 3} |
| 299 }; | 369 }; |
| 300 QuotaTableEntry* begin = kTableEntries; | 370 QuotaTableEntry* begin = kTableEntries; |
| 301 QuotaTableEntry* end = kTableEntries + ARRAYSIZE_UNSAFE(kTableEntries); | 371 QuotaTableEntry* end = kTableEntries + ARRAYSIZE_UNSAFE(kTableEntries); |
| 302 | 372 |
| 303 QuotaDatabase db(kDbFile); | 373 QuotaDatabase db(kDbFile); |
| 304 EXPECT_TRUE(AssignQuotaTable(&db, begin, end)); | 374 EXPECT_TRUE(db.LazyOpen(true)); |
| 375 AssignQuotaTable(db.db_.get(), begin, end); | |
| 376 db.Commit(); | |
| 305 | 377 |
| 306 typedef EntryVerifier<QuotaTableEntry> Verifier; | 378 typedef EntryVerifier<QuotaTableEntry> Verifier; |
| 307 Verifier verifier(begin, end); | 379 Verifier verifier(begin, end); |
| 308 EXPECT_TRUE(db.DumpQuotaTable( | 380 EXPECT_TRUE(db.DumpQuotaTable( |
| 309 new QuotaTableCallback( | 381 new QuotaTableCallback( |
| 310 base::Bind(&Verifier::Run, | 382 base::Bind(&Verifier::Run, |
| 311 base::Unretained(&verifier))))); | 383 base::Unretained(&verifier))))); |
| 312 EXPECT_TRUE(verifier.table.empty()); | 384 EXPECT_TRUE(verifier.table.empty()); |
| 313 } | 385 } |
| 314 | 386 |
| 315 void DumpLastAccessTimeTable(const FilePath& kDbFile) { | 387 void DumpOriginInfoTable(const FilePath& kDbFile) { |
| 316 base::Time now(base::Time::Now()); | 388 base::Time now(base::Time::Now()); |
| 317 LastAccessTimeTableEntry kTableEntries[] = { | 389 OriginInfoTableEntry kTableEntries[] = { |
| 318 {GURL("http://go/"), kStorageTypeTemporary, 2147483647, now}, | 390 {GURL("http://go/"), kStorageTypeTemporary, 2147483647, now, now}, |
| 319 {GURL("http://oo/"), kStorageTypeTemporary, 0, now}, | 391 {GURL("http://oo/"), kStorageTypeTemporary, 0, now, now}, |
| 320 {GURL("http://gle/"), kStorageTypeTemporary, 1, now}, | 392 {GURL("http://gle/"), kStorageTypeTemporary, 1, now, now}, |
| 321 }; | 393 }; |
| 322 LastAccessTimeTableEntry* begin = kTableEntries; | 394 OriginInfoTableEntry* begin = kTableEntries; |
| 323 LastAccessTimeTableEntry* end = kTableEntries + | 395 OriginInfoTableEntry* end = kTableEntries + ARRAYSIZE_UNSAFE(kTableEntries); |
| 324 ARRAYSIZE_UNSAFE(kTableEntries); | |
| 325 | 396 |
| 326 QuotaDatabase db(kDbFile); | 397 QuotaDatabase db(kDbFile); |
| 327 EXPECT_TRUE(AssignLastAccessTimeTable(&db, begin, end)); | 398 EXPECT_TRUE(db.LazyOpen(true)); |
| 399 AssignOriginInfoTable(db.db_.get(), begin, end); | |
| 400 db.Commit(); | |
| 328 | 401 |
| 329 typedef EntryVerifier<LastAccessTimeTableEntry> Verifier; | 402 typedef EntryVerifier<OriginInfoTableEntry> Verifier; |
| 330 Verifier verifier(begin, end); | 403 Verifier verifier(begin, end); |
| 331 EXPECT_TRUE(db.DumpLastAccessTimeTable( | 404 EXPECT_TRUE(db.DumpOriginInfoTable( |
| 332 new LastAccessTimeTableCallback( | 405 new OriginInfoTableCallback( |
| 333 base::Bind(&Verifier::Run, | 406 base::Bind(&Verifier::Run, |
| 334 base::Unretained(&verifier))))); | 407 base::Unretained(&verifier))))); |
| 335 EXPECT_TRUE(verifier.table.empty()); | 408 EXPECT_TRUE(verifier.table.empty()); |
| 336 } | 409 } |
| 410 | |
| 411 private: | |
| 412 template <typename Iterator> | |
| 413 void AssignQuotaTable(sql::Connection* db, Iterator itr, Iterator end) { | |
| 414 ASSERT_NE(db, (sql::Connection*)NULL); | |
| 415 for (; itr != end; ++itr) { | |
| 416 const char* kSql = | |
| 417 "INSERT INTO HostQuotaTable" | |
| 418 " (host, type, quota)" | |
| 419 " VALUES (?, ?, ?)"; | |
| 420 sql::Statement statement; | |
| 421 statement.Assign(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | |
| 422 ASSERT_TRUE(statement.is_valid()); | |
| 423 | |
| 424 statement.BindString(0, itr->host); | |
| 425 statement.BindInt(1, static_cast<int>(itr->type)); | |
| 426 statement.BindInt64(2, itr->quota); | |
| 427 EXPECT_TRUE(statement.Run()); | |
| 428 } | |
| 429 } | |
| 430 | |
| 431 template <typename Iterator> | |
| 432 void AssignOriginInfoTable(sql::Connection* db, Iterator itr, Iterator end) { | |
| 433 ASSERT_NE(db, (sql::Connection*)NULL); | |
| 434 for (; itr != end; ++itr) { | |
| 435 const char* kSql = | |
| 436 "INSERT INTO OriginInfoTable" | |
| 437 " (origin, type, used_count, last_access_time, last_modified_time)" | |
| 438 " VALUES (?, ?, ?, ?, ?)"; | |
| 439 sql::Statement statement; | |
| 440 statement.Assign(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | |
| 441 ASSERT_TRUE(statement.is_valid()); | |
| 442 | |
| 443 statement.BindString(0, itr->origin.spec()); | |
| 444 statement.BindInt(1, static_cast<int>(itr->type)); | |
| 445 statement.BindInt(2, itr->used_count); | |
| 446 statement.BindInt64(3, itr->last_access_time.ToInternalValue()); | |
| 447 statement.BindInt64(4, itr->last_modified_time.ToInternalValue()); | |
| 448 EXPECT_TRUE(statement.Run()); | |
| 449 } | |
| 450 } | |
| 451 | |
| 452 bool OpenDatabase(sql::Connection* db, const FilePath& kDbFile) { | |
| 453 if (kDbFile.empty()) { | |
| 454 db->OpenInMemory(); | |
| 455 return true; | |
| 456 } | |
| 457 if (!file_util::CreateDirectory(kDbFile.DirName())) | |
| 458 return false; | |
| 459 if (!db->Open(kDbFile)) | |
| 460 return false; | |
| 461 db->Preload(); | |
| 462 return true; | |
| 463 } | |
| 464 | |
| 465 // Create V2 database and populate some data. | |
| 466 void CreateV2Database( | |
| 467 const FilePath& kDbFile, | |
| 468 const QuotaTableEntry* entries, | |
| 469 size_t entries_size) { | |
| 470 scoped_ptr<sql::Connection> db(new sql::Connection); | |
| 471 scoped_ptr<sql::MetaTable> meta_table(new sql::MetaTable); | |
| 472 | |
| 473 ASSERT_TRUE(OpenDatabase(db.get(), kDbFile)); | |
| 474 EXPECT_TRUE(QuotaDatabase::CreateSchema( | |
| 475 db.get(), meta_table.get(), | |
| 476 v2::kCurrentVersion, v2::kCompatibleVersion, | |
| 477 v2::kTables, ARRAYSIZE_UNSAFE(v2::kTables), | |
| 478 v2::kIndexes, ARRAYSIZE_UNSAFE(v2::kIndexes))); | |
| 479 | |
| 480 // V2 and V3 QuotaTable are compatible, so we can simply use | |
| 481 // AssignQuotaTable to poplulate v2 database here. | |
| 482 db->BeginTransaction(); | |
| 483 AssignQuotaTable(db.get(), entries, entries + entries_size); | |
| 484 db->CommitTransaction(); | |
| 485 } | |
| 337 }; | 486 }; |
| 338 | 487 |
| 339 TEST_F(QuotaDatabaseTest, LazyOpen) { | 488 TEST_F(QuotaDatabaseTest, LazyOpen) { |
| 340 ScopedTempDir data_dir; | 489 ScopedTempDir data_dir; |
| 341 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); | 490 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); |
| 342 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); | 491 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); |
| 343 LazyOpen(kDbFile); | 492 LazyOpen(kDbFile); |
| 344 LazyOpen(FilePath()); | 493 LazyOpen(FilePath()); |
| 345 } | 494 } |
| 346 | 495 |
| 496 TEST_F(QuotaDatabaseTest, UpgradeSchema) { | |
| 497 ScopedTempDir data_dir; | |
| 498 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); | |
| 499 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); | |
| 500 UpgradeSchema(kDbFile); | |
| 501 } | |
| 502 | |
| 347 TEST_F(QuotaDatabaseTest, HostQuota) { | 503 TEST_F(QuotaDatabaseTest, HostQuota) { |
| 348 ScopedTempDir data_dir; | 504 ScopedTempDir data_dir; |
| 349 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); | 505 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); |
| 350 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); | 506 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); |
| 351 HostQuota(kDbFile); | 507 HostQuota(kDbFile); |
| 352 HostQuota(FilePath()); | 508 HostQuota(FilePath()); |
| 353 } | 509 } |
| 354 | 510 |
| 355 TEST_F(QuotaDatabaseTest, GlobalQuota) { | 511 TEST_F(QuotaDatabaseTest, GlobalQuota) { |
| 356 ScopedTempDir data_dir; | 512 ScopedTempDir data_dir; |
| 357 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); | 513 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); |
| 358 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); | 514 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); |
| 359 GlobalQuota(kDbFile); | 515 GlobalQuota(kDbFile); |
| 360 GlobalQuota(FilePath()); | 516 GlobalQuota(FilePath()); |
| 361 } | 517 } |
| 362 | 518 |
| 363 TEST_F(QuotaDatabaseTest, OriginLastAccessTimeLRU) { | 519 TEST_F(QuotaDatabaseTest, OriginLastAccessTimeLRU) { |
| 364 ScopedTempDir data_dir; | 520 ScopedTempDir data_dir; |
| 365 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); | 521 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); |
| 366 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); | 522 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); |
| 367 OriginLastAccessTimeLRU(kDbFile); | 523 OriginLastAccessTimeLRU(kDbFile); |
| 368 OriginLastAccessTimeLRU(FilePath()); | 524 OriginLastAccessTimeLRU(FilePath()); |
| 369 } | 525 } |
| 370 | 526 |
| 527 TEST_F(QuotaDatabaseTest, OriginLastModifiedSince) { | |
| 528 ScopedTempDir data_dir; | |
| 529 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); | |
| 530 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); | |
| 531 OriginLastModifiedSince(kDbFile); | |
| 532 OriginLastModifiedSince(FilePath()); | |
| 533 } | |
| 534 | |
| 371 TEST_F(QuotaDatabaseTest, BootstrapFlag) { | 535 TEST_F(QuotaDatabaseTest, BootstrapFlag) { |
| 372 ScopedTempDir data_dir; | 536 ScopedTempDir data_dir; |
| 373 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); | 537 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); |
| 374 | 538 |
| 375 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); | 539 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); |
| 376 QuotaDatabase db(kDbFile); | 540 QuotaDatabase db(kDbFile); |
| 377 | 541 |
| 378 EXPECT_FALSE(db.IsOriginDatabaseBootstrapped()); | 542 EXPECT_FALSE(db.IsOriginDatabaseBootstrapped()); |
| 379 EXPECT_TRUE(db.SetOriginDatabaseBootstrapped(true)); | 543 EXPECT_TRUE(db.SetOriginDatabaseBootstrapped(true)); |
| 380 EXPECT_TRUE(db.IsOriginDatabaseBootstrapped()); | 544 EXPECT_TRUE(db.IsOriginDatabaseBootstrapped()); |
| 381 EXPECT_TRUE(db.SetOriginDatabaseBootstrapped(false)); | 545 EXPECT_TRUE(db.SetOriginDatabaseBootstrapped(false)); |
| 382 EXPECT_FALSE(db.IsOriginDatabaseBootstrapped()); | 546 EXPECT_FALSE(db.IsOriginDatabaseBootstrapped()); |
| 383 } | 547 } |
| 384 | 548 |
| 385 TEST_F(QuotaDatabaseTest, RegisterOrigins) { | 549 TEST_F(QuotaDatabaseTest, RegisterInitialOriginInfo) { |
| 386 ScopedTempDir data_dir; | 550 ScopedTempDir data_dir; |
| 387 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); | 551 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); |
| 388 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); | 552 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); |
| 389 RegisterOrigins(kDbFile); | 553 RegisterInitialOriginInfo(kDbFile); |
| 390 RegisterOrigins(FilePath()); | 554 RegisterInitialOriginInfo(FilePath()); |
| 391 } | 555 } |
| 392 | 556 |
| 393 TEST_F(QuotaDatabaseTest, DumpQuotaTable) { | 557 TEST_F(QuotaDatabaseTest, DumpQuotaTable) { |
| 394 ScopedTempDir data_dir; | 558 ScopedTempDir data_dir; |
| 395 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); | 559 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); |
| 396 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); | 560 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); |
| 397 DumpQuotaTable(kDbFile); | 561 DumpQuotaTable(kDbFile); |
| 398 DumpQuotaTable(FilePath()); | 562 DumpQuotaTable(FilePath()); |
| 399 } | 563 } |
| 400 | 564 |
| 401 TEST_F(QuotaDatabaseTest, DumpLastAccessTimeTable) { | 565 TEST_F(QuotaDatabaseTest, DumpOriginInfoTable) { |
| 402 ScopedTempDir data_dir; | 566 ScopedTempDir data_dir; |
| 403 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); | 567 ASSERT_TRUE(data_dir.CreateUniqueTempDir()); |
| 404 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); | 568 const FilePath kDbFile = data_dir.path().AppendASCII("quota_manager.db"); |
| 405 DumpLastAccessTimeTable(kDbFile); | 569 DumpOriginInfoTable(kDbFile); |
| 406 DumpLastAccessTimeTable(FilePath()); | 570 DumpOriginInfoTable(FilePath()); |
| 407 } | 571 } |
| 408 } // namespace quota | 572 } // namespace quota |
| OLD | NEW |