1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/bind.h" 6 #include "base/file_util.h" 7 #include "base/files/scoped_temp_dir.h" 8 #include "base/strings/stringprintf.h" 9 #include "sql/connection.h" 10 #include "sql/meta_table.h" 11 #include "sql/statement.h" 12 #include "sql/test/scoped_error_ignorer.h" 13 #include "sql/transaction.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 #include "third_party/sqlite/sqlite3.h" 16 #include "webkit/browser/appcache/appcache_database.h" 17 #include "webkit/browser/appcache/appcache_entry.h" 18 19 namespace { 20 21 const base::Time kZeroTime; 22 23 } // namespace 24 25 namespace appcache { 26 27 class AppCacheDatabaseTest {}; 28 29 TEST(AppCacheDatabaseTest, LazyOpen) { 30 // Use an empty file path to use an in-memory sqlite database. 31 const base::FilePath kEmptyPath; 32 AppCacheDatabase db(kEmptyPath); 33 34 EXPECT_FALSE(db.LazyOpen(false)); 35 EXPECT_TRUE(db.LazyOpen(true)); 36 37 int64 group_id, cache_id, response_id, deleteable_response_rowid; 38 group_id = cache_id = response_id = deleteable_response_rowid = 0; 39 EXPECT_TRUE(db.FindLastStorageIds(&group_id, &cache_id, &response_id, 40 &deleteable_response_rowid)); 41 EXPECT_EQ(0, group_id); 42 EXPECT_EQ(0, cache_id); 43 EXPECT_EQ(0, response_id); 44 EXPECT_EQ(0, deleteable_response_rowid); 45 46 std::set<GURL> origins; 47 EXPECT_TRUE(db.FindOriginsWithGroups(&origins)); 48 EXPECT_TRUE(origins.empty()); 49 } 50 51 TEST(AppCacheDatabaseTest, ReCreate) { 52 // Real files on disk for this test. 53 base::ScopedTempDir temp_dir; 54 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 55 const base::FilePath kDbFile = temp_dir.path().AppendASCII("appcache.db"); 56 const base::FilePath kNestedDir = temp_dir.path().AppendASCII("nested"); 57 const base::FilePath kOtherFile = kNestedDir.AppendASCII("other_file"); 58 EXPECT_TRUE(file_util::CreateDirectory(kNestedDir)); 59 EXPECT_EQ(3, file_util::WriteFile(kOtherFile, "foo", 3)); 60 61 AppCacheDatabase db(kDbFile); 62 EXPECT_FALSE(db.LazyOpen(false)); 63 EXPECT_TRUE(db.LazyOpen(true)); 64 65 EXPECT_TRUE(base::PathExists(kDbFile)); 66 EXPECT_TRUE(base::DirectoryExists(kNestedDir)); 67 EXPECT_TRUE(base::PathExists(kOtherFile)); 68 69 EXPECT_TRUE(db.DeleteExistingAndCreateNewDatabase()); 70 71 EXPECT_TRUE(base::PathExists(kDbFile)); 72 EXPECT_FALSE(base::DirectoryExists(kNestedDir)); 73 EXPECT_FALSE(base::PathExists(kOtherFile)); 74 } 75 76 TEST(AppCacheDatabaseTest, ExperimentalFlags) { 77 const char kExperimentFlagsKey[] = "ExperimentFlags"; 78 std::string kInjectedFlags("exp1,exp2"); 79 80 // Real files on disk for this test. 81 base::ScopedTempDir temp_dir; 82 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 83 const base::FilePath kDbFile = temp_dir.path().AppendASCII("appcache.db"); 84 const base::FilePath kOtherFile = temp_dir.path().AppendASCII("other_file"); 85 EXPECT_EQ(3, file_util::WriteFile(kOtherFile, "foo", 3)); 86 EXPECT_TRUE(base::PathExists(kOtherFile)); 87 88 AppCacheDatabase db(kDbFile); 89 EXPECT_TRUE(db.LazyOpen(true)); 90 91 // Inject a non empty flags value, and verify it got there. 92 EXPECT_TRUE(db.meta_table_->SetValue(kExperimentFlagsKey, kInjectedFlags)); 93 std::string flags; 94 EXPECT_TRUE(db.meta_table_->GetValue(kExperimentFlagsKey, &flags)); 95 EXPECT_EQ(kInjectedFlags, flags); 96 db.CloseConnection(); 97 98 // If flags don't match the expected value, empty string by default, 99 // the database should be recreated and other files should be cleared out. 100 EXPECT_TRUE(db.LazyOpen(false)); 101 EXPECT_TRUE(db.meta_table_->GetValue(kExperimentFlagsKey, &flags)); 102 EXPECT_TRUE(flags.empty()); 103 EXPECT_FALSE(base::PathExists(kOtherFile)); 104 } 105 106 TEST(AppCacheDatabaseTest, EntryRecords) { 107 const base::FilePath kEmptyPath; 108 AppCacheDatabase db(kEmptyPath); 109 EXPECT_TRUE(db.LazyOpen(true)); 110 111 sql::ScopedErrorIgnorer ignore_errors; 112 // TODO(shess): Suppressing SQLITE_CONSTRAINT because the code 113 // expects that and handles the resulting error. Consider revising 114 // the code to use INSERT OR IGNORE (which would not throw 115 // SQLITE_CONSTRAINT) and then check ChangeCount() to see if any 116 // changes were made. 117 ignore_errors.IgnoreError(SQLITE_CONSTRAINT); 118 119 AppCacheDatabase::EntryRecord entry; 120 121 entry.cache_id = 1; 122 entry.url = GURL("http://blah/1"); 123 entry.flags = AppCacheEntry::MASTER; 124 entry.response_id = 1; 125 entry.response_size = 100; 126 EXPECT_TRUE(db.InsertEntry(&entry)); 127 EXPECT_FALSE(db.InsertEntry(&entry)); 128 129 entry.cache_id = 2; 130 entry.url = GURL("http://blah/2"); 131 entry.flags = AppCacheEntry::EXPLICIT; 132 entry.response_id = 2; 133 entry.response_size = 200; 134 EXPECT_TRUE(db.InsertEntry(&entry)); 135 136 entry.cache_id = 2; 137 entry.url = GURL("http://blah/3"); 138 entry.flags = AppCacheEntry::MANIFEST; 139 entry.response_id = 3; 140 entry.response_size = 300; 141 EXPECT_TRUE(db.InsertEntry(&entry)); 142 143 std::vector<AppCacheDatabase::EntryRecord> found; 144 145 EXPECT_TRUE(db.FindEntriesForCache(1, &found)); 146 EXPECT_EQ(1U, found.size()); 147 EXPECT_EQ(1, found[0].cache_id); 148 EXPECT_EQ(GURL("http://blah/1"), found[0].url); 149 EXPECT_EQ(AppCacheEntry::MASTER, found[0].flags); 150 EXPECT_EQ(1, found[0].response_id); 151 EXPECT_EQ(100, found[0].response_size); 152 found.clear(); 153 154 EXPECT_TRUE(db.AddEntryFlags(GURL("http://blah/1"), 1, 155 AppCacheEntry::FOREIGN)); 156 EXPECT_TRUE(db.FindEntriesForCache(1, &found)); 157 EXPECT_EQ(1U, found.size()); 158 EXPECT_EQ(AppCacheEntry::MASTER | AppCacheEntry::FOREIGN, found[0].flags); 159 found.clear(); 160 161 EXPECT_TRUE(db.FindEntriesForCache(2, &found)); 162 EXPECT_EQ(2U, found.size()); 163 EXPECT_EQ(2, found[0].cache_id); 164 EXPECT_EQ(GURL("http://blah/2"), found[0].url); 165 EXPECT_EQ(AppCacheEntry::EXPLICIT, found[0].flags); 166 EXPECT_EQ(2, found[0].response_id); 167 EXPECT_EQ(200, found[0].response_size); 168 EXPECT_EQ(2, found[1].cache_id); 169 EXPECT_EQ(GURL("http://blah/3"), found[1].url); 170 EXPECT_EQ(AppCacheEntry::MANIFEST, found[1].flags); 171 EXPECT_EQ(3, found[1].response_id); 172 EXPECT_EQ(300, found[1].response_size); 173 found.clear(); 174 175 EXPECT_TRUE(db.DeleteEntriesForCache(2)); 176 EXPECT_TRUE(db.FindEntriesForCache(2, &found)); 177 EXPECT_TRUE(found.empty()); 178 found.clear(); 179 180 EXPECT_TRUE(db.DeleteEntriesForCache(1)); 181 EXPECT_FALSE(db.AddEntryFlags(GURL("http://blah/1"), 1, 182 AppCacheEntry::FOREIGN)); 183 184 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 185 } 186 187 TEST(AppCacheDatabaseTest, CacheRecords) { 188 const base::FilePath kEmptyPath; 189 AppCacheDatabase db(kEmptyPath); 190 EXPECT_TRUE(db.LazyOpen(true)); 191 192 sql::ScopedErrorIgnorer ignore_errors; 193 // TODO(shess): See EntryRecords test. 194 ignore_errors.IgnoreError(SQLITE_CONSTRAINT); 195 196 const AppCacheDatabase::CacheRecord kZeroRecord; 197 AppCacheDatabase::CacheRecord record; 198 EXPECT_FALSE(db.FindCache(1, &record)); 199 200 record.cache_id = 1; 201 record.group_id = 1; 202 record.online_wildcard = true; 203 record.update_time = kZeroTime; 204 record.cache_size = 100; 205 EXPECT_TRUE(db.InsertCache(&record)); 206 EXPECT_FALSE(db.InsertCache(&record)); 207 208 record = kZeroRecord; 209 EXPECT_TRUE(db.FindCache(1, &record)); 210 EXPECT_EQ(1, record.cache_id); 211 EXPECT_EQ(1, record.group_id); 212 EXPECT_TRUE(record.online_wildcard); 213 EXPECT_TRUE(kZeroTime == record.update_time); 214 EXPECT_EQ(100, record.cache_size); 215 216 record = kZeroRecord; 217 EXPECT_TRUE(db.FindCacheForGroup(1, &record)); 218 EXPECT_EQ(1, record.cache_id); 219 EXPECT_EQ(1, record.group_id); 220 EXPECT_TRUE(record.online_wildcard); 221 EXPECT_TRUE(kZeroTime == record.update_time); 222 EXPECT_EQ(100, record.cache_size); 223 224 EXPECT_TRUE(db.DeleteCache(1)); 225 EXPECT_FALSE(db.FindCache(1, &record)); 226 EXPECT_FALSE(db.FindCacheForGroup(1, &record)); 227 228 EXPECT_TRUE(db.DeleteCache(1)); 229 230 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 231 } 232 233 TEST(AppCacheDatabaseTest, GroupRecords) { 234 const base::FilePath kEmptyPath; 235 AppCacheDatabase db(kEmptyPath); 236 EXPECT_TRUE(db.LazyOpen(true)); 237 238 sql::ScopedErrorIgnorer ignore_errors; 239 // TODO(shess): See EntryRecords test. 240 ignore_errors.IgnoreError(SQLITE_CONSTRAINT); 241 242 const GURL kManifestUrl("http://blah/manifest"); 243 const GURL kOrigin(kManifestUrl.GetOrigin()); 244 const base::Time kLastAccessTime = base::Time::Now(); 245 const base::Time kCreationTime = 246 kLastAccessTime - base::TimeDelta::FromDays(7); 247 248 const AppCacheDatabase::GroupRecord kZeroRecord; 249 AppCacheDatabase::GroupRecord record; 250 std::vector<AppCacheDatabase::GroupRecord> records; 251 252 // Behavior with an empty table 253 EXPECT_FALSE(db.FindGroup(1, &record)); 254 EXPECT_FALSE(db.FindGroupForManifestUrl(kManifestUrl, &record)); 255 EXPECT_TRUE(db.DeleteGroup(1)); 256 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records)); 257 EXPECT_TRUE(records.empty()); 258 EXPECT_FALSE(db.FindGroupForCache(1, &record)); 259 260 record.group_id = 1; 261 record.manifest_url = kManifestUrl; 262 record.origin = kOrigin; 263 record.last_access_time = kLastAccessTime; 264 record.creation_time = kCreationTime; 265 EXPECT_TRUE(db.InsertGroup(&record)); 266 EXPECT_FALSE(db.InsertGroup(&record)); 267 268 record.group_id = 2; 269 EXPECT_FALSE(db.InsertGroup(&record)); 270 271 record = kZeroRecord; 272 EXPECT_TRUE(db.FindGroup(1, &record)); 273 EXPECT_EQ(1, record.group_id); 274 EXPECT_EQ(kManifestUrl, record.manifest_url); 275 EXPECT_EQ(kOrigin, record.origin); 276 EXPECT_EQ(kCreationTime.ToInternalValue(), 277 record.creation_time.ToInternalValue()); 278 EXPECT_EQ(kLastAccessTime.ToInternalValue(), 279 record.last_access_time.ToInternalValue()); 280 281 record = kZeroRecord; 282 EXPECT_TRUE(db.FindGroupForManifestUrl(kManifestUrl, &record)); 283 EXPECT_EQ(1, record.group_id); 284 EXPECT_EQ(kManifestUrl, record.manifest_url); 285 EXPECT_EQ(kOrigin, record.origin); 286 EXPECT_EQ(kCreationTime.ToInternalValue(), 287 record.creation_time.ToInternalValue()); 288 EXPECT_EQ(kLastAccessTime.ToInternalValue(), 289 record.last_access_time.ToInternalValue()); 290 291 record.group_id = 2; 292 record.manifest_url = kOrigin; 293 record.origin = kOrigin; 294 record.last_access_time = kLastAccessTime; 295 record.creation_time = kCreationTime; 296 EXPECT_TRUE(db.InsertGroup(&record)); 297 298 record = kZeroRecord; 299 EXPECT_TRUE(db.FindGroupForManifestUrl(kOrigin, &record)); 300 EXPECT_EQ(2, record.group_id); 301 EXPECT_EQ(kOrigin, record.manifest_url); 302 EXPECT_EQ(kOrigin, record.origin); 303 EXPECT_EQ(kCreationTime.ToInternalValue(), 304 record.creation_time.ToInternalValue()); 305 EXPECT_EQ(kLastAccessTime.ToInternalValue(), 306 record.last_access_time.ToInternalValue()); 307 308 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records)); 309 EXPECT_EQ(2U, records.size()); 310 EXPECT_EQ(1, records[0].group_id); 311 EXPECT_EQ(kManifestUrl, records[0].manifest_url); 312 EXPECT_EQ(kOrigin, records[0].origin); 313 EXPECT_EQ(2, records[1].group_id); 314 EXPECT_EQ(kOrigin, records[1].manifest_url); 315 EXPECT_EQ(kOrigin, records[1].origin); 316 317 EXPECT_TRUE(db.DeleteGroup(1)); 318 319 records.clear(); 320 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records)); 321 EXPECT_EQ(1U, records.size()); 322 EXPECT_EQ(2, records[0].group_id); 323 EXPECT_EQ(kOrigin, records[0].manifest_url); 324 EXPECT_EQ(kOrigin, records[0].origin); 325 EXPECT_EQ(kCreationTime.ToInternalValue(), 326 record.creation_time.ToInternalValue()); 327 EXPECT_EQ(kLastAccessTime.ToInternalValue(), 328 record.last_access_time.ToInternalValue()); 329 330 std::set<GURL> origins; 331 EXPECT_TRUE(db.FindOriginsWithGroups(&origins)); 332 EXPECT_EQ(1U, origins.size()); 333 EXPECT_EQ(kOrigin, *(origins.begin())); 334 335 const GURL kManifest2("http://blah2/manifest"); 336 const GURL kOrigin2(kManifest2.GetOrigin()); 337 record.group_id = 1; 338 record.manifest_url = kManifest2; 339 record.origin = kOrigin2; 340 EXPECT_TRUE(db.InsertGroup(&record)); 341 342 origins.clear(); 343 EXPECT_TRUE(db.FindOriginsWithGroups(&origins)); 344 EXPECT_EQ(2U, origins.size()); 345 EXPECT_TRUE(origins.end() != origins.find(kOrigin)); 346 EXPECT_TRUE(origins.end() != origins.find(kOrigin2)); 347 348 AppCacheDatabase::CacheRecord cache_record; 349 cache_record.cache_id = 1; 350 cache_record.group_id = 1; 351 cache_record.online_wildcard = true; 352 cache_record.update_time = kZeroTime; 353 EXPECT_TRUE(db.InsertCache(&cache_record)); 354 355 record = kZeroRecord; 356 EXPECT_TRUE(db.FindGroupForCache(1, &record)); 357 EXPECT_EQ(1, record.group_id); 358 EXPECT_EQ(kManifest2, record.manifest_url); 359 EXPECT_EQ(kOrigin2, record.origin); 360 361 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 362 } 363 364 TEST(AppCacheDatabaseTest, NamespaceRecords) { 365 const base::FilePath kEmptyPath; 366 AppCacheDatabase db(kEmptyPath); 367 EXPECT_TRUE(db.LazyOpen(true)); 368 369 sql::ScopedErrorIgnorer ignore_errors; 370 // TODO(shess): See EntryRecords test. 371 ignore_errors.IgnoreError(SQLITE_CONSTRAINT); 372 373 const GURL kFooNameSpace1("http://foo/namespace1"); 374 const GURL kFooNameSpace2("http://foo/namespace2"); 375 const GURL kFooFallbackEntry("http://foo/entry"); 376 const GURL kFooOrigin(kFooNameSpace1.GetOrigin()); 377 const GURL kBarNameSpace1("http://bar/namespace1"); 378 const GURL kBarNameSpace2("http://bar/namespace2"); 379 const GURL kBarFallbackEntry("http://bar/entry"); 380 const GURL kBarOrigin(kBarNameSpace1.GetOrigin()); 381 382 const AppCacheDatabase::NamespaceRecord kZeroRecord; 383 AppCacheDatabase::NamespaceRecord record; 384 std::vector<AppCacheDatabase::NamespaceRecord> intercepts; 385 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks; 386 387 // Behavior with an empty table 388 EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks)); 389 EXPECT_TRUE(fallbacks.empty()); 390 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks)); 391 EXPECT_TRUE(fallbacks.empty()); 392 EXPECT_TRUE(db.DeleteNamespacesForCache(1)); 393 394 // Two records for two differenent caches in the Foo origin. 395 record.cache_id = 1; 396 record.origin = kFooOrigin; 397 record.namespace_.namespace_url = kFooNameSpace1; 398 record.namespace_.target_url = kFooFallbackEntry; 399 EXPECT_TRUE(db.InsertNamespace(&record)); 400 EXPECT_FALSE(db.InsertNamespace(&record)); 401 402 record.cache_id = 2; 403 record.origin = kFooOrigin; 404 record.namespace_.namespace_url = kFooNameSpace2; 405 record.namespace_.target_url = kFooFallbackEntry; 406 EXPECT_TRUE(db.InsertNamespace(&record)); 407 408 fallbacks.clear(); 409 EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks)); 410 EXPECT_EQ(1U, fallbacks.size()); 411 EXPECT_EQ(1, fallbacks[0].cache_id); 412 EXPECT_EQ(kFooOrigin, fallbacks[0].origin); 413 EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url); 414 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url); 415 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern); 416 417 fallbacks.clear(); 418 EXPECT_TRUE(db.FindNamespacesForCache(2, &intercepts, &fallbacks)); 419 EXPECT_EQ(1U, fallbacks.size()); 420 EXPECT_EQ(2, fallbacks[0].cache_id); 421 EXPECT_EQ(kFooOrigin, fallbacks[0].origin); 422 EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url); 423 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url); 424 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern); 425 426 fallbacks.clear(); 427 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks)); 428 EXPECT_EQ(2U, fallbacks.size()); 429 EXPECT_EQ(1, fallbacks[0].cache_id); 430 EXPECT_EQ(kFooOrigin, fallbacks[0].origin); 431 EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url); 432 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url); 433 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern); 434 EXPECT_EQ(2, fallbacks[1].cache_id); 435 EXPECT_EQ(kFooOrigin, fallbacks[1].origin); 436 EXPECT_EQ(kFooNameSpace2, fallbacks[1].namespace_.namespace_url); 437 EXPECT_EQ(kFooFallbackEntry, fallbacks[1].namespace_.target_url); 438 EXPECT_FALSE(fallbacks[1].namespace_.is_pattern); 439 440 EXPECT_TRUE(db.DeleteNamespacesForCache(1)); 441 fallbacks.clear(); 442 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks)); 443 EXPECT_EQ(1U, fallbacks.size()); 444 EXPECT_EQ(2, fallbacks[0].cache_id); 445 EXPECT_EQ(kFooOrigin, fallbacks[0].origin); 446 EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url); 447 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url); 448 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern); 449 450 // Two more records for the same cache in the Bar origin. 451 record.cache_id = 3; 452 record.origin = kBarOrigin; 453 record.namespace_.namespace_url = kBarNameSpace1; 454 record.namespace_.target_url = kBarFallbackEntry; 455 record.namespace_.is_pattern = true; 456 EXPECT_TRUE(db.InsertNamespace(&record)); 457 458 record.cache_id = 3; 459 record.origin = kBarOrigin; 460 record.namespace_.namespace_url = kBarNameSpace2; 461 record.namespace_.target_url = kBarFallbackEntry; 462 record.namespace_.is_pattern = true; 463 EXPECT_TRUE(db.InsertNamespace(&record)); 464 465 fallbacks.clear(); 466 EXPECT_TRUE(db.FindNamespacesForCache(3, &intercepts, &fallbacks)); 467 EXPECT_EQ(2U, fallbacks.size()); 468 EXPECT_TRUE(fallbacks[0].namespace_.is_pattern); 469 EXPECT_TRUE(fallbacks[1].namespace_.is_pattern); 470 471 fallbacks.clear(); 472 EXPECT_TRUE(db.FindNamespacesForOrigin(kBarOrigin, &intercepts, &fallbacks)); 473 EXPECT_EQ(2U, fallbacks.size()); 474 EXPECT_TRUE(fallbacks[0].namespace_.is_pattern); 475 EXPECT_TRUE(fallbacks[1].namespace_.is_pattern); 476 477 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 478 } 479 480 TEST(AppCacheDatabaseTest, OnlineWhiteListRecords) { 481 const base::FilePath kEmptyPath; 482 AppCacheDatabase db(kEmptyPath); 483 EXPECT_TRUE(db.LazyOpen(true)); 484 485 const GURL kFooNameSpace1("http://foo/namespace1"); 486 const GURL kFooNameSpace2("http://foo/namespace2"); 487 const GURL kBarNameSpace1("http://bar/namespace1"); 488 489 const AppCacheDatabase::OnlineWhiteListRecord kZeroRecord; 490 AppCacheDatabase::OnlineWhiteListRecord record; 491 std::vector<AppCacheDatabase::OnlineWhiteListRecord> records; 492 493 // Behavior with an empty table 494 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records)); 495 EXPECT_TRUE(records.empty()); 496 EXPECT_TRUE(db.DeleteOnlineWhiteListForCache(1)); 497 498 record.cache_id = 1; 499 record.namespace_url = kFooNameSpace1; 500 EXPECT_TRUE(db.InsertOnlineWhiteList(&record)); 501 record.namespace_url = kFooNameSpace2; 502 record.is_pattern = true; 503 EXPECT_TRUE(db.InsertOnlineWhiteList(&record)); 504 records.clear(); 505 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records)); 506 EXPECT_EQ(2U, records.size()); 507 EXPECT_EQ(1, records[0].cache_id); 508 EXPECT_EQ(kFooNameSpace1, records[0].namespace_url); 509 EXPECT_FALSE(records[0].is_pattern); 510 EXPECT_EQ(1, records[1].cache_id); 511 EXPECT_EQ(kFooNameSpace2, records[1].namespace_url); 512 EXPECT_TRUE(records[1].is_pattern); 513 514 record.cache_id = 2; 515 record.namespace_url = kBarNameSpace1; 516 EXPECT_TRUE(db.InsertOnlineWhiteList(&record)); 517 records.clear(); 518 EXPECT_TRUE(db.FindOnlineWhiteListForCache(2, &records)); 519 EXPECT_EQ(1U, records.size()); 520 521 EXPECT_TRUE(db.DeleteOnlineWhiteListForCache(1)); 522 records.clear(); 523 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records)); 524 EXPECT_TRUE(records.empty()); 525 } 526 527 TEST(AppCacheDatabaseTest, DeletableResponseIds) { 528 const base::FilePath kEmptyPath; 529 AppCacheDatabase db(kEmptyPath); 530 EXPECT_TRUE(db.LazyOpen(true)); 531 532 sql::ScopedErrorIgnorer ignore_errors; 533 // TODO(shess): See EntryRecords test. 534 ignore_errors.IgnoreError(SQLITE_CONSTRAINT); 535 536 std::vector<int64> ids; 537 538 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100)); 539 EXPECT_TRUE(ids.empty()); 540 ids.push_back(0); 541 EXPECT_TRUE(db.DeleteDeletableResponseIds(ids)); 542 EXPECT_TRUE(db.InsertDeletableResponseIds(ids)); 543 544 ids.clear(); 545 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100)); 546 EXPECT_EQ(1U, ids.size()); 547 EXPECT_EQ(0, ids[0]); 548 549 int64 unused, deleteable_response_rowid; 550 unused = deleteable_response_rowid = 0; 551 EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused, 552 &deleteable_response_rowid)); 553 EXPECT_EQ(1, deleteable_response_rowid); 554 555 556 // Expected to fail due to the duplicate id, 0 is already in the table. 557 ids.clear(); 558 ids.push_back(0); 559 ids.push_back(1); 560 EXPECT_FALSE(db.InsertDeletableResponseIds(ids)); 561 562 ids.clear(); 563 for (int i = 1; i < 10; ++i) 564 ids.push_back(i); 565 EXPECT_TRUE(db.InsertDeletableResponseIds(ids)); 566 EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused, 567 &deleteable_response_rowid)); 568 EXPECT_EQ(10, deleteable_response_rowid); 569 570 ids.clear(); 571 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100)); 572 EXPECT_EQ(10U, ids.size()); 573 for (int i = 0; i < 10; ++i) 574 EXPECT_EQ(i, ids[i]); 575 576 // Ensure the limit is respected. 577 ids.clear(); 578 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 5)); 579 EXPECT_EQ(5U, ids.size()); 580 for (int i = 0; i < static_cast<int>(ids.size()); ++i) 581 EXPECT_EQ(i, ids[i]); 582 583 // Ensure the max_rowid is respected (the first rowid is 1). 584 ids.clear(); 585 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, 5, 100)); 586 EXPECT_EQ(5U, ids.size()); 587 for (int i = 0; i < static_cast<int>(ids.size()); ++i) 588 EXPECT_EQ(i, ids[i]); 589 590 // Ensure that we can delete from the table. 591 EXPECT_TRUE(db.DeleteDeletableResponseIds(ids)); 592 ids.clear(); 593 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100)); 594 EXPECT_EQ(5U, ids.size()); 595 for (int i = 0; i < static_cast<int>(ids.size()); ++i) 596 EXPECT_EQ(i + 5, ids[i]); 597 598 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 599 } 600 601 TEST(AppCacheDatabaseTest, OriginUsage) { 602 const GURL kManifestUrl("http://blah/manifest"); 603 const GURL kManifestUrl2("http://blah/manifest2"); 604 const GURL kOrigin(kManifestUrl.GetOrigin()); 605 const GURL kOtherOriginManifestUrl("http://other/manifest"); 606 const GURL kOtherOrigin(kOtherOriginManifestUrl.GetOrigin()); 607 608 const base::FilePath kEmptyPath; 609 AppCacheDatabase db(kEmptyPath); 610 EXPECT_TRUE(db.LazyOpen(true)); 611 612 std::vector<AppCacheDatabase::CacheRecord> cache_records; 613 EXPECT_EQ(0, db.GetOriginUsage(kOrigin)); 614 EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records)); 615 EXPECT_TRUE(cache_records.empty()); 616 617 AppCacheDatabase::GroupRecord group_record; 618 group_record.group_id = 1; 619 group_record.manifest_url = kManifestUrl; 620 group_record.origin = kOrigin; 621 EXPECT_TRUE(db.InsertGroup(&group_record)); 622 AppCacheDatabase::CacheRecord cache_record; 623 cache_record.cache_id = 1; 624 cache_record.group_id = 1; 625 cache_record.online_wildcard = true; 626 cache_record.update_time = kZeroTime; 627 cache_record.cache_size = 100; 628 EXPECT_TRUE(db.InsertCache(&cache_record)); 629 630 EXPECT_EQ(100, db.GetOriginUsage(kOrigin)); 631 632 group_record.group_id = 2; 633 group_record.manifest_url = kManifestUrl2; 634 group_record.origin = kOrigin; 635 EXPECT_TRUE(db.InsertGroup(&group_record)); 636 cache_record.cache_id = 2; 637 cache_record.group_id = 2; 638 cache_record.online_wildcard = true; 639 cache_record.update_time = kZeroTime; 640 cache_record.cache_size = 1000; 641 EXPECT_TRUE(db.InsertCache(&cache_record)); 642 643 EXPECT_EQ(1100, db.GetOriginUsage(kOrigin)); 644 645 group_record.group_id = 3; 646 group_record.manifest_url = kOtherOriginManifestUrl; 647 group_record.origin = kOtherOrigin; 648 EXPECT_TRUE(db.InsertGroup(&group_record)); 649 cache_record.cache_id = 3; 650 cache_record.group_id = 3; 651 cache_record.online_wildcard = true; 652 cache_record.update_time = kZeroTime; 653 cache_record.cache_size = 5000; 654 EXPECT_TRUE(db.InsertCache(&cache_record)); 655 656 EXPECT_EQ(5000, db.GetOriginUsage(kOtherOrigin)); 657 658 EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records)); 659 EXPECT_EQ(2U, cache_records.size()); 660 cache_records.clear(); 661 EXPECT_TRUE(db.FindCachesForOrigin(kOtherOrigin, &cache_records)); 662 EXPECT_EQ(1U, cache_records.size()); 663 664 std::map<GURL, int64> usage_map; 665 EXPECT_TRUE(db.GetAllOriginUsage(&usage_map)); 666 EXPECT_EQ(2U, usage_map.size()); 667 EXPECT_EQ(1100, usage_map[kOrigin]); 668 EXPECT_EQ(5000, usage_map[kOtherOrigin]); 669 } 670 671 TEST(AppCacheDatabaseTest, UpgradeSchema3to5) { 672 // Real file on disk for this test. 673 base::ScopedTempDir temp_dir; 674 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 675 const base::FilePath kDbFile = temp_dir.path().AppendASCII("upgrade3.db"); 676 677 const GURL kMockOrigin("http://mockorigin/"); 678 const char kNamespaceUrlFormat[] = "namespace%d"; 679 const char kTargetUrlFormat[] = "target%d"; 680 const int kNumNamespaces = 10; 681 682 // Create a v3 schema based database containing some fallback records. 683 { 684 const int kVersion3 = 3; 685 const char kGroupsTable[] = "Groups"; 686 const char kCachesTable[] = "Caches"; 687 const char kEntriesTable[] = "Entries"; 688 const char kFallbackNameSpacesTable[] = "FallbackNameSpaces"; 689 const char kOnlineWhiteListsTable[] = "OnlineWhiteLists"; 690 const char kDeletableResponseIdsTable[] = "DeletableResponseIds"; 691 692 const struct { 693 const char* table_name; 694 const char* columns; 695 } kTables3[] = { 696 { kGroupsTable, 697 "(group_id INTEGER PRIMARY KEY," 698 " origin TEXT," 699 " manifest_url TEXT," 700 " creation_time INTEGER," 701 " last_access_time INTEGER)" }, 702 703 { kCachesTable, 704 "(cache_id INTEGER PRIMARY KEY," 705 " group_id INTEGER," 706 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1))," 707 " update_time INTEGER," 708 " cache_size INTEGER)" }, // intentionally not normalized 709 710 { kEntriesTable, 711 "(cache_id INTEGER," 712 " url TEXT," 713 " flags INTEGER," 714 " response_id INTEGER," 715 " response_size INTEGER)" }, 716 717 { kFallbackNameSpacesTable, 718 "(cache_id INTEGER," 719 " origin TEXT," // intentionally not normalized 720 " namespace_url TEXT," 721 " fallback_entry_url TEXT)" }, 722 723 { kOnlineWhiteListsTable, 724 "(cache_id INTEGER," 725 " namespace_url TEXT)" }, 726 727 { kDeletableResponseIdsTable, 728 "(response_id INTEGER NOT NULL)" }, 729 }; 730 731 const struct { 732 const char* index_name; 733 const char* table_name; 734 const char* columns; 735 bool unique; 736 } kIndexes3[] = { 737 { "GroupsOriginIndex", 738 kGroupsTable, 739 "(origin)", 740 false }, 741 742 { "GroupsManifestIndex", 743 kGroupsTable, 744 "(manifest_url)", 745 true }, 746 747 { "CachesGroupIndex", 748 kCachesTable, 749 "(group_id)", 750 false }, 751 752 { "EntriesCacheIndex", 753 kEntriesTable, 754 "(cache_id)", 755 false }, 756 757 { "EntriesCacheAndUrlIndex", 758 kEntriesTable, 759 "(cache_id, url)", 760 true }, 761 762 { "EntriesResponseIdIndex", 763 kEntriesTable, 764 "(response_id)", 765 true }, 766 767 { "FallbackNameSpacesCacheIndex", 768 kFallbackNameSpacesTable, 769 "(cache_id)", 770 false }, 771 772 { "FallbackNameSpacesOriginIndex", 773 kFallbackNameSpacesTable, 774 "(origin)", 775 false }, 776 777 { "FallbackNameSpacesCacheAndUrlIndex", 778 kFallbackNameSpacesTable, 779 "(cache_id, namespace_url)", 780 true }, 781 782 { "OnlineWhiteListCacheIndex", 783 kOnlineWhiteListsTable, 784 "(cache_id)", 785 false }, 786 787 { "DeletableResponsesIdIndex", 788 kDeletableResponseIdsTable, 789 "(response_id)", 790 true }, 791 }; 792 793 const int kTableCount3 = ARRAYSIZE_UNSAFE(kTables3); 794 const int kIndexCount3 = ARRAYSIZE_UNSAFE(kIndexes3); 795 796 sql::Connection connection; 797 EXPECT_TRUE(connection.Open(kDbFile)); 798 799 sql::Transaction transaction(&connection); 800 EXPECT_TRUE(transaction.Begin()); 801 802 sql::MetaTable meta_table; 803 EXPECT_TRUE(meta_table.Init(&connection, kVersion3, kVersion3)); 804 805 for (int i = 0; i < kTableCount3; ++i) { 806 std::string sql("CREATE TABLE "); 807 sql += kTables3[i].table_name; 808 sql += kTables3[i].columns; 809 EXPECT_TRUE(connection.Execute(sql.c_str())); 810 } 811 812 for (int i = 0; i < kIndexCount3; ++i) { 813 std::string sql; 814 if (kIndexes3[i].unique) 815 sql += "CREATE UNIQUE INDEX "; 816 else 817 sql += "CREATE INDEX "; 818 sql += kIndexes3[i].index_name; 819 sql += " ON "; 820 sql += kIndexes3[i].table_name; 821 sql += kIndexes3[i].columns; 822 EXPECT_TRUE(connection.Execute(sql.c_str())); 823 } 824 825 const char* kSql = 826 "INSERT INTO FallbackNameSpaces" 827 " (cache_id, origin, namespace_url, fallback_entry_url)" 828 " VALUES (?, ?, ?, ?)"; 829 830 sql::Statement statement; 831 statement.Assign(connection.GetUniqueStatement(kSql)); 832 EXPECT_TRUE(statement.is_valid()); 833 for (int i = 0; i < kNumNamespaces; ++i) { 834 GURL namespace_url( 835 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i))); 836 GURL target_url( 837 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i))); 838 statement.BindInt64(0, i); 839 statement.BindString(1, kMockOrigin.spec().c_str()); 840 statement.BindString(2, namespace_url.spec().c_str()); 841 statement.BindString(3, target_url.spec().c_str()); 842 ASSERT_TRUE(statement.Run()); 843 statement.Reset(true); 844 } 845 846 EXPECT_TRUE(transaction.Commit()); 847 } 848 849 // Open that database and verify that it got updated. 850 AppCacheDatabase db(kDbFile); 851 EXPECT_TRUE(db.LazyOpen(true)); 852 853 EXPECT_FALSE(db.db_->DoesTableExist("FallbackNameSpaces")); 854 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNamesSpacesCacheIndex")); 855 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNameSpacesOriginIndex")); 856 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNameSpacesCacheAndUrlIndex")); 857 858 EXPECT_TRUE(db.db_->DoesTableExist("Namespaces")); 859 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesCacheIndex")); 860 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesOriginIndex")); 861 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesCacheAndUrlIndex")); 862 EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "is_pattern")); 863 EXPECT_TRUE(db.db_->DoesColumnExist("OnlineWhiteLists", "is_pattern")); 864 865 EXPECT_EQ(5, db.meta_table_->GetVersionNumber()); 866 EXPECT_EQ(5, db.meta_table_->GetCompatibleVersionNumber()); 867 868 std::vector<AppCacheDatabase::NamespaceRecord> intercepts; 869 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks; 870 EXPECT_TRUE(db.FindNamespacesForOrigin(kMockOrigin, &intercepts, 871 &fallbacks)); 872 EXPECT_TRUE(intercepts.empty()); 873 EXPECT_EQ(kNumNamespaces, static_cast<int>(fallbacks.size())); 874 875 for (int i = 0; i < kNumNamespaces; ++i) { 876 GURL expected_namespace_url( 877 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i))); 878 GURL expected_target_url( 879 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i))); 880 881 EXPECT_EQ(i, fallbacks[i].cache_id); 882 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[i].namespace_.type); 883 EXPECT_EQ(kMockOrigin, fallbacks[i].origin); 884 EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_.namespace_url); 885 EXPECT_EQ(expected_target_url, fallbacks[i].namespace_.target_url); 886 EXPECT_FALSE(fallbacks[i].namespace_.is_pattern); 887 } 888 } 889 890 TEST(AppCacheDatabaseTest, UpgradeSchema4to5) { 891 // Real file on disk for this test. 892 base::ScopedTempDir temp_dir; 893 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 894 const base::FilePath kDbFile = temp_dir.path().AppendASCII("upgrade4.db"); 895 896 const GURL kMockOrigin("http://mockorigin/"); 897 const char kNamespaceUrlFormat[] = "namespace%d"; 898 const char kWhitelistUrlFormat[] = "whitelist%d"; 899 const char kTargetUrlFormat[] = "target%d"; 900 const int kNumNamespaces = 10; 901 const int kWhitelistCacheId = 1; 902 903 // Create a v4 schema based database containing some fallback records. 904 { 905 const int kVersion4 = 4; 906 const char kGroupsTable[] = "Groups"; 907 const char kCachesTable[] = "Caches"; 908 const char kEntriesTable[] = "Entries"; 909 const char kNamespacesTable[] = "Namespaces"; 910 const char kOnlineWhiteListsTable[] = "OnlineWhiteLists"; 911 const char kDeletableResponseIdsTable[] = "DeletableResponseIds"; 912 913 struct TableInfo { 914 const char* table_name; 915 const char* columns; 916 }; 917 918 struct IndexInfo { 919 const char* index_name; 920 const char* table_name; 921 const char* columns; 922 bool unique; 923 }; 924 925 const TableInfo kTables4[] = { 926 { kGroupsTable, 927 "(group_id INTEGER PRIMARY KEY," 928 " origin TEXT," 929 " manifest_url TEXT," 930 " creation_time INTEGER," 931 " last_access_time INTEGER)" }, 932 933 { kCachesTable, 934 "(cache_id INTEGER PRIMARY KEY," 935 " group_id INTEGER," 936 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1))," 937 " update_time INTEGER," 938 " cache_size INTEGER)" }, // intentionally not normalized 939 940 { kEntriesTable, 941 "(cache_id INTEGER," 942 " url TEXT," 943 " flags INTEGER," 944 " response_id INTEGER," 945 " response_size INTEGER)" }, 946 947 { kNamespacesTable, 948 "(cache_id INTEGER," 949 " origin TEXT," // intentionally not normalized 950 " type INTEGER," 951 " namespace_url TEXT," 952 " target_url TEXT)" }, 953 954 { kOnlineWhiteListsTable, 955 "(cache_id INTEGER," 956 " namespace_url TEXT)" }, 957 958 { kDeletableResponseIdsTable, 959 "(response_id INTEGER NOT NULL)" }, 960 }; 961 962 const IndexInfo kIndexes4[] = { 963 { "GroupsOriginIndex", 964 kGroupsTable, 965 "(origin)", 966 false }, 967 968 { "GroupsManifestIndex", 969 kGroupsTable, 970 "(manifest_url)", 971 true }, 972 973 { "CachesGroupIndex", 974 kCachesTable, 975 "(group_id)", 976 false }, 977 978 { "EntriesCacheIndex", 979 kEntriesTable, 980 "(cache_id)", 981 false }, 982 983 { "EntriesCacheAndUrlIndex", 984 kEntriesTable, 985 "(cache_id, url)", 986 true }, 987 988 { "EntriesResponseIdIndex", 989 kEntriesTable, 990 "(response_id)", 991 true }, 992 993 { "NamespacesCacheIndex", 994 kNamespacesTable, 995 "(cache_id)", 996 false }, 997 998 { "NamespacesOriginIndex", 999 kNamespacesTable, 1000 "(origin)", 1001 false }, 1002 1003 { "NamespacesCacheAndUrlIndex", 1004 kNamespacesTable, 1005 "(cache_id, namespace_url)", 1006 true }, 1007 1008 { "OnlineWhiteListCacheIndex", 1009 kOnlineWhiteListsTable, 1010 "(cache_id)", 1011 false }, 1012 1013 { "DeletableResponsesIdIndex", 1014 kDeletableResponseIdsTable, 1015 "(response_id)", 1016 true }, 1017 }; 1018 1019 const int kTableCount4 = ARRAYSIZE_UNSAFE(kTables4); 1020 const int kIndexCount4 = ARRAYSIZE_UNSAFE(kIndexes4); 1021 1022 sql::Connection connection; 1023 EXPECT_TRUE(connection.Open(kDbFile)); 1024 1025 sql::Transaction transaction(&connection); 1026 EXPECT_TRUE(transaction.Begin()); 1027 1028 sql::MetaTable meta_table; 1029 EXPECT_TRUE(meta_table.Init(&connection, kVersion4, kVersion4)); 1030 1031 for (int i = 0; i < kTableCount4; ++i) { 1032 std::string sql("CREATE TABLE "); 1033 sql += kTables4[i].table_name; 1034 sql += kTables4[i].columns; 1035 EXPECT_TRUE(connection.Execute(sql.c_str())); 1036 } 1037 1038 for (int i = 0; i < kIndexCount4; ++i) { 1039 std::string sql; 1040 if (kIndexes4[i].unique) 1041 sql += "CREATE UNIQUE INDEX "; 1042 else 1043 sql += "CREATE INDEX "; 1044 sql += kIndexes4[i].index_name; 1045 sql += " ON "; 1046 sql += kIndexes4[i].table_name; 1047 sql += kIndexes4[i].columns; 1048 EXPECT_TRUE(connection.Execute(sql.c_str())); 1049 } 1050 1051 const char* kNamespacesSql = 1052 "INSERT INTO Namespaces" 1053 " (cache_id, origin, type, namespace_url, target_url)" 1054 " VALUES (?, ?, ?, ?, ?)"; 1055 sql::Statement statement; 1056 statement.Assign(connection.GetUniqueStatement(kNamespacesSql)); 1057 EXPECT_TRUE(statement.is_valid()); 1058 for (int i = 0; i < kNumNamespaces; ++i) { 1059 GURL namespace_url( 1060 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i))); 1061 GURL target_url( 1062 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i))); 1063 statement.BindInt64(0, i); 1064 statement.BindString(1, kMockOrigin.spec().c_str()); 1065 statement.BindInt(2, FALLBACK_NAMESPACE); 1066 statement.BindString(3, namespace_url.spec().c_str()); 1067 statement.BindString(4, target_url.spec().c_str()); 1068 ASSERT_TRUE(statement.Run()); 1069 statement.Reset(true); 1070 } 1071 1072 const char* kWhitelistsSql = 1073 "INSERT INTO OnlineWhiteLists" 1074 " (cache_id, namespace_url)" 1075 " VALUES (?, ?)"; 1076 statement.Assign(connection.GetUniqueStatement(kWhitelistsSql)); 1077 EXPECT_TRUE(statement.is_valid()); 1078 for (int i = 0; i < kNumNamespaces; ++i) { 1079 GURL namespace_url( 1080 kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i))); 1081 statement.BindInt64(0, kWhitelistCacheId); 1082 statement.BindString(1, namespace_url.spec().c_str()); 1083 ASSERT_TRUE(statement.Run()); 1084 statement.Reset(true); 1085 } 1086 1087 EXPECT_TRUE(transaction.Commit()); 1088 } 1089 1090 // Open that database and verify that it got upgraded to v5. 1091 AppCacheDatabase db(kDbFile); 1092 EXPECT_TRUE(db.LazyOpen(true)); 1093 EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "is_pattern")); 1094 EXPECT_TRUE(db.db_->DoesColumnExist("OnlineWhiteLists", "is_pattern")); 1095 EXPECT_EQ(5, db.meta_table_->GetVersionNumber()); 1096 EXPECT_EQ(5, db.meta_table_->GetCompatibleVersionNumber()); 1097 1098 std::vector<AppCacheDatabase::NamespaceRecord> intercepts; 1099 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks; 1100 EXPECT_TRUE(db.FindNamespacesForOrigin(kMockOrigin, &intercepts, 1101 &fallbacks)); 1102 EXPECT_TRUE(intercepts.empty()); 1103 EXPECT_EQ(kNumNamespaces, static_cast<int>(fallbacks.size())); 1104 1105 std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists; 1106 EXPECT_TRUE(db.FindOnlineWhiteListForCache(kWhitelistCacheId, &whitelists)); 1107 EXPECT_EQ(kNumNamespaces, static_cast<int>(whitelists.size())); 1108 1109 for (int i = 0; i < kNumNamespaces; ++i) { 1110 GURL expected_namespace_url( 1111 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i))); 1112 GURL expected_target_url( 1113 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i))); 1114 GURL expected_whitelist_url( 1115 kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i))); 1116 1117 EXPECT_EQ(i, fallbacks[i].cache_id); 1118 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[i].namespace_.type); 1119 EXPECT_EQ(kMockOrigin, fallbacks[i].origin); 1120 EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_.namespace_url); 1121 EXPECT_EQ(expected_target_url, fallbacks[i].namespace_.target_url); 1122 EXPECT_FALSE(fallbacks[i].namespace_.is_pattern); 1123 EXPECT_EQ(expected_whitelist_url, whitelists[i].namespace_url); 1124 EXPECT_FALSE(whitelists[i].is_pattern); 1125 } 1126 } 1127 1128 } // namespace appcache 1129