Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / browser / appcache / appcache_database_unittest.cc
blob44a6c6ac24de6a323704c111fdbe31c272d0ed50
1 // Copyright 2014 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.
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 "content/browser/appcache/appcache_database.h"
10 #include "content/browser/appcache/appcache_entry.h"
11 #include "sql/connection.h"
12 #include "sql/meta_table.h"
13 #include "sql/statement.h"
14 #include "sql/test/scoped_error_ignorer.h"
15 #include "sql/test/test_helpers.h"
16 #include "sql/transaction.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/sqlite/sqlite3.h"
20 namespace {
22 const base::Time kZeroTime;
24 } // namespace
26 namespace content {
28 class AppCacheDatabaseTest {};
30 TEST(AppCacheDatabaseTest, LazyOpen) {
31 // Use an empty file path to use an in-memory sqlite database.
32 const base::FilePath kEmptyPath;
33 AppCacheDatabase db(kEmptyPath);
35 EXPECT_FALSE(db.LazyOpen(false));
36 EXPECT_TRUE(db.LazyOpen(true));
38 int64 group_id, cache_id, response_id, deleteable_response_rowid;
39 group_id = cache_id = response_id = deleteable_response_rowid = 0;
40 EXPECT_TRUE(db.FindLastStorageIds(&group_id, &cache_id, &response_id,
41 &deleteable_response_rowid));
42 EXPECT_EQ(0, group_id);
43 EXPECT_EQ(0, cache_id);
44 EXPECT_EQ(0, response_id);
45 EXPECT_EQ(0, deleteable_response_rowid);
47 std::set<GURL> origins;
48 EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
49 EXPECT_TRUE(origins.empty());
52 TEST(AppCacheDatabaseTest, ReCreate) {
53 // Real files on disk for this test.
54 base::ScopedTempDir temp_dir;
55 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
56 const base::FilePath kDbFile = temp_dir.path().AppendASCII("appcache.db");
57 const base::FilePath kNestedDir = temp_dir.path().AppendASCII("nested");
58 const base::FilePath kOtherFile = kNestedDir.AppendASCII("other_file");
59 EXPECT_TRUE(base::CreateDirectory(kNestedDir));
60 EXPECT_EQ(3, base::WriteFile(kOtherFile, "foo", 3));
62 AppCacheDatabase db(kDbFile);
63 EXPECT_FALSE(db.LazyOpen(false));
64 EXPECT_TRUE(db.LazyOpen(true));
66 EXPECT_TRUE(base::PathExists(kDbFile));
67 EXPECT_TRUE(base::DirectoryExists(kNestedDir));
68 EXPECT_TRUE(base::PathExists(kOtherFile));
70 EXPECT_TRUE(db.DeleteExistingAndCreateNewDatabase());
72 EXPECT_TRUE(base::PathExists(kDbFile));
73 EXPECT_FALSE(base::DirectoryExists(kNestedDir));
74 EXPECT_FALSE(base::PathExists(kOtherFile));
77 #ifdef NDEBUG
78 // Only run in release builds because sql::Connection and familiy
79 // crank up DLOG(FATAL)'ness and this test presents it with
80 // intentionally bad data which causes debug builds to exit instead
81 // of run to completion. In release builds, errors the are delivered
82 // to the consumer so we can test the error handling of the consumer.
83 // TODO: crbug/328576
84 TEST(AppCacheDatabaseTest, QuickIntegrityCheck) {
85 // Real files on disk for this test too, a corrupt database file.
86 base::ScopedTempDir temp_dir;
87 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
88 base::FilePath mock_dir = temp_dir.path().AppendASCII("mock");
89 ASSERT_TRUE(base::CreateDirectory(mock_dir));
91 const base::FilePath kDbFile = mock_dir.AppendASCII("appcache.db");
92 const base::FilePath kOtherFile = mock_dir.AppendASCII("other_file");
93 EXPECT_EQ(3, base::WriteFile(kOtherFile, "foo", 3));
95 // First create a valid db file.
97 AppCacheDatabase db(kDbFile);
98 EXPECT_TRUE(db.LazyOpen(true));
99 EXPECT_TRUE(base::PathExists(kOtherFile));
100 EXPECT_TRUE(base::PathExists(kDbFile));
103 // Break it.
104 ASSERT_TRUE(sql::test::CorruptSizeInHeader(kDbFile));
106 // Reopening will notice the corruption and delete/recreate the directory.
108 sql::ScopedErrorIgnorer ignore_errors;
109 ignore_errors.IgnoreError(SQLITE_CORRUPT);
110 AppCacheDatabase db(kDbFile);
111 EXPECT_TRUE(db.LazyOpen(true));
112 EXPECT_FALSE(base::PathExists(kOtherFile));
113 EXPECT_TRUE(base::PathExists(kDbFile));
114 EXPECT_TRUE(ignore_errors.CheckIgnoredErrors());
117 #endif // NDEBUG
119 TEST(AppCacheDatabaseTest, WasCorrutionDetected) {
120 // Real files on disk for this test too, a corrupt database file.
121 base::ScopedTempDir temp_dir;
122 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
123 const base::FilePath kDbFile = temp_dir.path().AppendASCII("appcache.db");
125 // First create a valid db file.
126 AppCacheDatabase db(kDbFile);
127 EXPECT_TRUE(db.LazyOpen(true));
128 EXPECT_TRUE(base::PathExists(kDbFile));
129 EXPECT_FALSE(db.was_corruption_detected());
131 // Break it.
132 ASSERT_TRUE(sql::test::CorruptSizeInHeader(kDbFile));
134 // See the the corruption is detected and reported.
136 sql::ScopedErrorIgnorer ignore_errors;
137 ignore_errors.IgnoreError(SQLITE_CORRUPT);
138 std::map<GURL, int64> usage_map;
139 EXPECT_FALSE(db.GetAllOriginUsage(&usage_map));
140 EXPECT_TRUE(db.was_corruption_detected());
141 EXPECT_TRUE(base::PathExists(kDbFile));
142 EXPECT_TRUE(ignore_errors.CheckIgnoredErrors());
146 TEST(AppCacheDatabaseTest, ExperimentalFlags) {
147 const char kExperimentFlagsKey[] = "ExperimentFlags";
148 std::string kInjectedFlags("exp1,exp2");
150 // Real files on disk for this test.
151 base::ScopedTempDir temp_dir;
152 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
153 const base::FilePath kDbFile = temp_dir.path().AppendASCII("appcache.db");
154 const base::FilePath kOtherFile = temp_dir.path().AppendASCII("other_file");
155 EXPECT_EQ(3, base::WriteFile(kOtherFile, "foo", 3));
156 EXPECT_TRUE(base::PathExists(kOtherFile));
158 // Inject a non empty flags value, and verify it got there.
160 AppCacheDatabase db(kDbFile);
161 EXPECT_TRUE(db.LazyOpen(true));
162 EXPECT_TRUE(db.meta_table_->SetValue(kExperimentFlagsKey, kInjectedFlags));
163 std::string flags;
164 EXPECT_TRUE(db.meta_table_->GetValue(kExperimentFlagsKey, &flags));
165 EXPECT_EQ(kInjectedFlags, flags);
168 // If flags don't match the expected value, empty string by default,
169 // the database should be recreated and other files should be cleared out.
171 AppCacheDatabase db(kDbFile);
172 EXPECT_TRUE(db.LazyOpen(false));
173 std::string flags;
174 EXPECT_TRUE(db.meta_table_->GetValue(kExperimentFlagsKey, &flags));
175 EXPECT_TRUE(flags.empty());
176 EXPECT_FALSE(base::PathExists(kOtherFile));
180 TEST(AppCacheDatabaseTest, EntryRecords) {
181 const base::FilePath kEmptyPath;
182 AppCacheDatabase db(kEmptyPath);
183 EXPECT_TRUE(db.LazyOpen(true));
185 sql::ScopedErrorIgnorer ignore_errors;
186 // TODO(shess): Suppressing SQLITE_CONSTRAINT because the code
187 // expects that and handles the resulting error. Consider revising
188 // the code to use INSERT OR IGNORE (which would not throw
189 // SQLITE_CONSTRAINT) and then check ChangeCount() to see if any
190 // changes were made.
191 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
193 AppCacheDatabase::EntryRecord entry;
195 entry.cache_id = 1;
196 entry.url = GURL("http://blah/1");
197 entry.flags = AppCacheEntry::MASTER;
198 entry.response_id = 1;
199 entry.response_size = 100;
200 EXPECT_TRUE(db.InsertEntry(&entry));
201 EXPECT_FALSE(db.InsertEntry(&entry));
203 entry.cache_id = 2;
204 entry.url = GURL("http://blah/2");
205 entry.flags = AppCacheEntry::EXPLICIT;
206 entry.response_id = 2;
207 entry.response_size = 200;
208 EXPECT_TRUE(db.InsertEntry(&entry));
210 entry.cache_id = 2;
211 entry.url = GURL("http://blah/3");
212 entry.flags = AppCacheEntry::MANIFEST;
213 entry.response_id = 3;
214 entry.response_size = 300;
215 EXPECT_TRUE(db.InsertEntry(&entry));
217 std::vector<AppCacheDatabase::EntryRecord> found;
219 EXPECT_TRUE(db.FindEntriesForCache(1, &found));
220 EXPECT_EQ(1U, found.size());
221 EXPECT_EQ(1, found[0].cache_id);
222 EXPECT_EQ(GURL("http://blah/1"), found[0].url);
223 EXPECT_EQ(AppCacheEntry::MASTER, found[0].flags);
224 EXPECT_EQ(1, found[0].response_id);
225 EXPECT_EQ(100, found[0].response_size);
226 found.clear();
228 EXPECT_TRUE(db.AddEntryFlags(GURL("http://blah/1"), 1,
229 AppCacheEntry::FOREIGN));
230 EXPECT_TRUE(db.FindEntriesForCache(1, &found));
231 EXPECT_EQ(1U, found.size());
232 EXPECT_EQ(AppCacheEntry::MASTER | AppCacheEntry::FOREIGN, found[0].flags);
233 found.clear();
235 EXPECT_TRUE(db.FindEntriesForCache(2, &found));
236 EXPECT_EQ(2U, found.size());
237 EXPECT_EQ(2, found[0].cache_id);
238 EXPECT_EQ(GURL("http://blah/2"), found[0].url);
239 EXPECT_EQ(AppCacheEntry::EXPLICIT, found[0].flags);
240 EXPECT_EQ(2, found[0].response_id);
241 EXPECT_EQ(200, found[0].response_size);
242 EXPECT_EQ(2, found[1].cache_id);
243 EXPECT_EQ(GURL("http://blah/3"), found[1].url);
244 EXPECT_EQ(AppCacheEntry::MANIFEST, found[1].flags);
245 EXPECT_EQ(3, found[1].response_id);
246 EXPECT_EQ(300, found[1].response_size);
247 found.clear();
249 EXPECT_TRUE(db.DeleteEntriesForCache(2));
250 EXPECT_TRUE(db.FindEntriesForCache(2, &found));
251 EXPECT_TRUE(found.empty());
252 found.clear();
254 EXPECT_TRUE(db.DeleteEntriesForCache(1));
255 EXPECT_FALSE(db.AddEntryFlags(GURL("http://blah/1"), 1,
256 AppCacheEntry::FOREIGN));
258 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
261 TEST(AppCacheDatabaseTest, CacheRecords) {
262 const base::FilePath kEmptyPath;
263 AppCacheDatabase db(kEmptyPath);
264 EXPECT_TRUE(db.LazyOpen(true));
266 sql::ScopedErrorIgnorer ignore_errors;
267 // TODO(shess): See EntryRecords test.
268 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
270 const AppCacheDatabase::CacheRecord kZeroRecord;
271 AppCacheDatabase::CacheRecord record;
272 EXPECT_FALSE(db.FindCache(1, &record));
274 record.cache_id = 1;
275 record.group_id = 1;
276 record.online_wildcard = true;
277 record.update_time = kZeroTime;
278 record.cache_size = 100;
279 EXPECT_TRUE(db.InsertCache(&record));
280 EXPECT_FALSE(db.InsertCache(&record));
282 record = kZeroRecord;
283 EXPECT_TRUE(db.FindCache(1, &record));
284 EXPECT_EQ(1, record.cache_id);
285 EXPECT_EQ(1, record.group_id);
286 EXPECT_TRUE(record.online_wildcard);
287 EXPECT_TRUE(kZeroTime == record.update_time);
288 EXPECT_EQ(100, record.cache_size);
290 record = kZeroRecord;
291 EXPECT_TRUE(db.FindCacheForGroup(1, &record));
292 EXPECT_EQ(1, record.cache_id);
293 EXPECT_EQ(1, record.group_id);
294 EXPECT_TRUE(record.online_wildcard);
295 EXPECT_TRUE(kZeroTime == record.update_time);
296 EXPECT_EQ(100, record.cache_size);
298 EXPECT_TRUE(db.DeleteCache(1));
299 EXPECT_FALSE(db.FindCache(1, &record));
300 EXPECT_FALSE(db.FindCacheForGroup(1, &record));
302 EXPECT_TRUE(db.DeleteCache(1));
304 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
307 TEST(AppCacheDatabaseTest, GroupRecords) {
308 const base::FilePath kEmptyPath;
309 AppCacheDatabase db(kEmptyPath);
310 EXPECT_TRUE(db.LazyOpen(true));
312 sql::ScopedErrorIgnorer ignore_errors;
313 // TODO(shess): See EntryRecords test.
314 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
316 const GURL kManifestUrl("http://blah/manifest");
317 const GURL kOrigin(kManifestUrl.GetOrigin());
318 const base::Time kLastAccessTime = base::Time::Now();
319 const base::Time kCreationTime =
320 kLastAccessTime - base::TimeDelta::FromDays(7);
322 const AppCacheDatabase::GroupRecord kZeroRecord;
323 AppCacheDatabase::GroupRecord record;
324 std::vector<AppCacheDatabase::GroupRecord> records;
326 // Behavior with an empty table
327 EXPECT_FALSE(db.FindGroup(1, &record));
328 EXPECT_FALSE(db.FindGroupForManifestUrl(kManifestUrl, &record));
329 EXPECT_TRUE(db.DeleteGroup(1));
330 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
331 EXPECT_TRUE(records.empty());
332 EXPECT_FALSE(db.FindGroupForCache(1, &record));
334 record.group_id = 1;
335 record.manifest_url = kManifestUrl;
336 record.origin = kOrigin;
337 record.last_access_time = kLastAccessTime;
338 record.creation_time = kCreationTime;
339 EXPECT_TRUE(db.InsertGroup(&record));
340 EXPECT_FALSE(db.InsertGroup(&record));
342 record.group_id = 2;
343 EXPECT_FALSE(db.InsertGroup(&record));
345 record = kZeroRecord;
346 EXPECT_TRUE(db.FindGroup(1, &record));
347 EXPECT_EQ(1, record.group_id);
348 EXPECT_EQ(kManifestUrl, record.manifest_url);
349 EXPECT_EQ(kOrigin, record.origin);
350 EXPECT_EQ(kCreationTime.ToInternalValue(),
351 record.creation_time.ToInternalValue());
352 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
353 record.last_access_time.ToInternalValue());
355 record = kZeroRecord;
356 EXPECT_TRUE(db.FindGroupForManifestUrl(kManifestUrl, &record));
357 EXPECT_EQ(1, record.group_id);
358 EXPECT_EQ(kManifestUrl, record.manifest_url);
359 EXPECT_EQ(kOrigin, record.origin);
360 EXPECT_EQ(kCreationTime.ToInternalValue(),
361 record.creation_time.ToInternalValue());
362 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
363 record.last_access_time.ToInternalValue());
365 record.group_id = 2;
366 record.manifest_url = kOrigin;
367 record.origin = kOrigin;
368 record.last_access_time = kLastAccessTime;
369 record.creation_time = kCreationTime;
370 EXPECT_TRUE(db.InsertGroup(&record));
372 record = kZeroRecord;
373 EXPECT_TRUE(db.FindGroupForManifestUrl(kOrigin, &record));
374 EXPECT_EQ(2, record.group_id);
375 EXPECT_EQ(kOrigin, record.manifest_url);
376 EXPECT_EQ(kOrigin, record.origin);
377 EXPECT_EQ(kCreationTime.ToInternalValue(),
378 record.creation_time.ToInternalValue());
379 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
380 record.last_access_time.ToInternalValue());
382 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
383 EXPECT_EQ(2U, records.size());
384 EXPECT_EQ(1, records[0].group_id);
385 EXPECT_EQ(kManifestUrl, records[0].manifest_url);
386 EXPECT_EQ(kOrigin, records[0].origin);
387 EXPECT_EQ(2, records[1].group_id);
388 EXPECT_EQ(kOrigin, records[1].manifest_url);
389 EXPECT_EQ(kOrigin, records[1].origin);
391 EXPECT_TRUE(db.DeleteGroup(1));
393 records.clear();
394 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
395 EXPECT_EQ(1U, records.size());
396 EXPECT_EQ(2, records[0].group_id);
397 EXPECT_EQ(kOrigin, records[0].manifest_url);
398 EXPECT_EQ(kOrigin, records[0].origin);
399 EXPECT_EQ(kCreationTime.ToInternalValue(),
400 record.creation_time.ToInternalValue());
401 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
402 record.last_access_time.ToInternalValue());
404 std::set<GURL> origins;
405 EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
406 EXPECT_EQ(1U, origins.size());
407 EXPECT_EQ(kOrigin, *(origins.begin()));
409 const GURL kManifest2("http://blah2/manifest");
410 const GURL kOrigin2(kManifest2.GetOrigin());
411 record.group_id = 1;
412 record.manifest_url = kManifest2;
413 record.origin = kOrigin2;
414 EXPECT_TRUE(db.InsertGroup(&record));
416 origins.clear();
417 EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
418 EXPECT_EQ(2U, origins.size());
419 EXPECT_TRUE(origins.end() != origins.find(kOrigin));
420 EXPECT_TRUE(origins.end() != origins.find(kOrigin2));
422 AppCacheDatabase::CacheRecord cache_record;
423 cache_record.cache_id = 1;
424 cache_record.group_id = 1;
425 cache_record.online_wildcard = true;
426 cache_record.update_time = kZeroTime;
427 EXPECT_TRUE(db.InsertCache(&cache_record));
429 record = kZeroRecord;
430 EXPECT_TRUE(db.FindGroupForCache(1, &record));
431 EXPECT_EQ(1, record.group_id);
432 EXPECT_EQ(kManifest2, record.manifest_url);
433 EXPECT_EQ(kOrigin2, record.origin);
435 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
438 TEST(AppCacheDatabaseTest, NamespaceRecords) {
439 const base::FilePath kEmptyPath;
440 AppCacheDatabase db(kEmptyPath);
441 EXPECT_TRUE(db.LazyOpen(true));
443 sql::ScopedErrorIgnorer ignore_errors;
444 // TODO(shess): See EntryRecords test.
445 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
447 const GURL kFooNameSpace1("http://foo/namespace1");
448 const GURL kFooNameSpace2("http://foo/namespace2");
449 const GURL kFooFallbackEntry("http://foo/entry");
450 const GURL kFooOrigin(kFooNameSpace1.GetOrigin());
451 const GURL kBarNameSpace1("http://bar/namespace1");
452 const GURL kBarNameSpace2("http://bar/namespace2");
453 const GURL kBarFallbackEntry("http://bar/entry");
454 const GURL kBarOrigin(kBarNameSpace1.GetOrigin());
456 const AppCacheDatabase::NamespaceRecord kZeroRecord;
457 AppCacheDatabase::NamespaceRecord record;
458 std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
459 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
461 // Behavior with an empty table
462 EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks));
463 EXPECT_TRUE(fallbacks.empty());
464 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
465 EXPECT_TRUE(fallbacks.empty());
466 EXPECT_TRUE(db.DeleteNamespacesForCache(1));
468 // Two records for two differenent caches in the Foo origin.
469 record.cache_id = 1;
470 record.origin = kFooOrigin;
471 record.namespace_.namespace_url = kFooNameSpace1;
472 record.namespace_.target_url = kFooFallbackEntry;
473 EXPECT_TRUE(db.InsertNamespace(&record));
474 EXPECT_FALSE(db.InsertNamespace(&record));
476 record.cache_id = 2;
477 record.origin = kFooOrigin;
478 record.namespace_.namespace_url = kFooNameSpace2;
479 record.namespace_.target_url = kFooFallbackEntry;
480 EXPECT_TRUE(db.InsertNamespace(&record));
482 fallbacks.clear();
483 EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks));
484 EXPECT_EQ(1U, fallbacks.size());
485 EXPECT_EQ(1, fallbacks[0].cache_id);
486 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
487 EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url);
488 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
489 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
491 fallbacks.clear();
492 EXPECT_TRUE(db.FindNamespacesForCache(2, &intercepts, &fallbacks));
493 EXPECT_EQ(1U, fallbacks.size());
494 EXPECT_EQ(2, fallbacks[0].cache_id);
495 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
496 EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url);
497 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
498 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
500 fallbacks.clear();
501 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
502 EXPECT_EQ(2U, fallbacks.size());
503 EXPECT_EQ(1, fallbacks[0].cache_id);
504 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
505 EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url);
506 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
507 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
508 EXPECT_EQ(2, fallbacks[1].cache_id);
509 EXPECT_EQ(kFooOrigin, fallbacks[1].origin);
510 EXPECT_EQ(kFooNameSpace2, fallbacks[1].namespace_.namespace_url);
511 EXPECT_EQ(kFooFallbackEntry, fallbacks[1].namespace_.target_url);
512 EXPECT_FALSE(fallbacks[1].namespace_.is_pattern);
514 EXPECT_TRUE(db.DeleteNamespacesForCache(1));
515 fallbacks.clear();
516 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
517 EXPECT_EQ(1U, fallbacks.size());
518 EXPECT_EQ(2, fallbacks[0].cache_id);
519 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
520 EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url);
521 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
522 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
524 // Two more records for the same cache in the Bar origin.
525 record.cache_id = 3;
526 record.origin = kBarOrigin;
527 record.namespace_.namespace_url = kBarNameSpace1;
528 record.namespace_.target_url = kBarFallbackEntry;
529 record.namespace_.is_pattern = true;
530 EXPECT_TRUE(db.InsertNamespace(&record));
532 record.cache_id = 3;
533 record.origin = kBarOrigin;
534 record.namespace_.namespace_url = kBarNameSpace2;
535 record.namespace_.target_url = kBarFallbackEntry;
536 record.namespace_.is_pattern = true;
537 EXPECT_TRUE(db.InsertNamespace(&record));
539 fallbacks.clear();
540 EXPECT_TRUE(db.FindNamespacesForCache(3, &intercepts, &fallbacks));
541 EXPECT_EQ(2U, fallbacks.size());
542 EXPECT_TRUE(fallbacks[0].namespace_.is_pattern);
543 EXPECT_TRUE(fallbacks[1].namespace_.is_pattern);
545 fallbacks.clear();
546 EXPECT_TRUE(db.FindNamespacesForOrigin(kBarOrigin, &intercepts, &fallbacks));
547 EXPECT_EQ(2U, fallbacks.size());
548 EXPECT_TRUE(fallbacks[0].namespace_.is_pattern);
549 EXPECT_TRUE(fallbacks[1].namespace_.is_pattern);
551 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
554 TEST(AppCacheDatabaseTest, OnlineWhiteListRecords) {
555 const base::FilePath kEmptyPath;
556 AppCacheDatabase db(kEmptyPath);
557 EXPECT_TRUE(db.LazyOpen(true));
559 const GURL kFooNameSpace1("http://foo/namespace1");
560 const GURL kFooNameSpace2("http://foo/namespace2");
561 const GURL kBarNameSpace1("http://bar/namespace1");
563 const AppCacheDatabase::OnlineWhiteListRecord kZeroRecord;
564 AppCacheDatabase::OnlineWhiteListRecord record;
565 std::vector<AppCacheDatabase::OnlineWhiteListRecord> records;
567 // Behavior with an empty table
568 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records));
569 EXPECT_TRUE(records.empty());
570 EXPECT_TRUE(db.DeleteOnlineWhiteListForCache(1));
572 record.cache_id = 1;
573 record.namespace_url = kFooNameSpace1;
574 EXPECT_TRUE(db.InsertOnlineWhiteList(&record));
575 record.namespace_url = kFooNameSpace2;
576 record.is_pattern = true;
577 EXPECT_TRUE(db.InsertOnlineWhiteList(&record));
578 records.clear();
579 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records));
580 EXPECT_EQ(2U, records.size());
581 EXPECT_EQ(1, records[0].cache_id);
582 EXPECT_EQ(kFooNameSpace1, records[0].namespace_url);
583 EXPECT_FALSE(records[0].is_pattern);
584 EXPECT_EQ(1, records[1].cache_id);
585 EXPECT_EQ(kFooNameSpace2, records[1].namespace_url);
586 EXPECT_TRUE(records[1].is_pattern);
588 record.cache_id = 2;
589 record.namespace_url = kBarNameSpace1;
590 EXPECT_TRUE(db.InsertOnlineWhiteList(&record));
591 records.clear();
592 EXPECT_TRUE(db.FindOnlineWhiteListForCache(2, &records));
593 EXPECT_EQ(1U, records.size());
595 EXPECT_TRUE(db.DeleteOnlineWhiteListForCache(1));
596 records.clear();
597 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records));
598 EXPECT_TRUE(records.empty());
601 TEST(AppCacheDatabaseTest, DeletableResponseIds) {
602 const base::FilePath kEmptyPath;
603 AppCacheDatabase db(kEmptyPath);
604 EXPECT_TRUE(db.LazyOpen(true));
606 sql::ScopedErrorIgnorer ignore_errors;
607 // TODO(shess): See EntryRecords test.
608 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
610 std::vector<int64> ids;
612 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
613 EXPECT_TRUE(ids.empty());
614 ids.push_back(0);
615 EXPECT_TRUE(db.DeleteDeletableResponseIds(ids));
616 EXPECT_TRUE(db.InsertDeletableResponseIds(ids));
618 ids.clear();
619 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
620 EXPECT_EQ(1U, ids.size());
621 EXPECT_EQ(0, ids[0]);
623 int64 unused, deleteable_response_rowid;
624 unused = deleteable_response_rowid = 0;
625 EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused,
626 &deleteable_response_rowid));
627 EXPECT_EQ(1, deleteable_response_rowid);
630 // Expected to fail due to the duplicate id, 0 is already in the table.
631 ids.clear();
632 ids.push_back(0);
633 ids.push_back(1);
634 EXPECT_FALSE(db.InsertDeletableResponseIds(ids));
636 ids.clear();
637 for (int i = 1; i < 10; ++i)
638 ids.push_back(i);
639 EXPECT_TRUE(db.InsertDeletableResponseIds(ids));
640 EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused,
641 &deleteable_response_rowid));
642 EXPECT_EQ(10, deleteable_response_rowid);
644 ids.clear();
645 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
646 EXPECT_EQ(10U, ids.size());
647 for (int i = 0; i < 10; ++i)
648 EXPECT_EQ(i, ids[i]);
650 // Ensure the limit is respected.
651 ids.clear();
652 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 5));
653 EXPECT_EQ(5U, ids.size());
654 for (int i = 0; i < static_cast<int>(ids.size()); ++i)
655 EXPECT_EQ(i, ids[i]);
657 // Ensure the max_rowid is respected (the first rowid is 1).
658 ids.clear();
659 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, 5, 100));
660 EXPECT_EQ(5U, ids.size());
661 for (int i = 0; i < static_cast<int>(ids.size()); ++i)
662 EXPECT_EQ(i, ids[i]);
664 // Ensure that we can delete from the table.
665 EXPECT_TRUE(db.DeleteDeletableResponseIds(ids));
666 ids.clear();
667 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
668 EXPECT_EQ(5U, ids.size());
669 for (int i = 0; i < static_cast<int>(ids.size()); ++i)
670 EXPECT_EQ(i + 5, ids[i]);
672 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
675 TEST(AppCacheDatabaseTest, OriginUsage) {
676 const GURL kManifestUrl("http://blah/manifest");
677 const GURL kManifestUrl2("http://blah/manifest2");
678 const GURL kOrigin(kManifestUrl.GetOrigin());
679 const GURL kOtherOriginManifestUrl("http://other/manifest");
680 const GURL kOtherOrigin(kOtherOriginManifestUrl.GetOrigin());
682 const base::FilePath kEmptyPath;
683 AppCacheDatabase db(kEmptyPath);
684 EXPECT_TRUE(db.LazyOpen(true));
686 std::vector<AppCacheDatabase::CacheRecord> cache_records;
687 EXPECT_EQ(0, db.GetOriginUsage(kOrigin));
688 EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records));
689 EXPECT_TRUE(cache_records.empty());
691 AppCacheDatabase::GroupRecord group_record;
692 group_record.group_id = 1;
693 group_record.manifest_url = kManifestUrl;
694 group_record.origin = kOrigin;
695 EXPECT_TRUE(db.InsertGroup(&group_record));
696 AppCacheDatabase::CacheRecord cache_record;
697 cache_record.cache_id = 1;
698 cache_record.group_id = 1;
699 cache_record.online_wildcard = true;
700 cache_record.update_time = kZeroTime;
701 cache_record.cache_size = 100;
702 EXPECT_TRUE(db.InsertCache(&cache_record));
704 EXPECT_EQ(100, db.GetOriginUsage(kOrigin));
706 group_record.group_id = 2;
707 group_record.manifest_url = kManifestUrl2;
708 group_record.origin = kOrigin;
709 EXPECT_TRUE(db.InsertGroup(&group_record));
710 cache_record.cache_id = 2;
711 cache_record.group_id = 2;
712 cache_record.online_wildcard = true;
713 cache_record.update_time = kZeroTime;
714 cache_record.cache_size = 1000;
715 EXPECT_TRUE(db.InsertCache(&cache_record));
717 EXPECT_EQ(1100, db.GetOriginUsage(kOrigin));
719 group_record.group_id = 3;
720 group_record.manifest_url = kOtherOriginManifestUrl;
721 group_record.origin = kOtherOrigin;
722 EXPECT_TRUE(db.InsertGroup(&group_record));
723 cache_record.cache_id = 3;
724 cache_record.group_id = 3;
725 cache_record.online_wildcard = true;
726 cache_record.update_time = kZeroTime;
727 cache_record.cache_size = 5000;
728 EXPECT_TRUE(db.InsertCache(&cache_record));
730 EXPECT_EQ(5000, db.GetOriginUsage(kOtherOrigin));
732 EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records));
733 EXPECT_EQ(2U, cache_records.size());
734 cache_records.clear();
735 EXPECT_TRUE(db.FindCachesForOrigin(kOtherOrigin, &cache_records));
736 EXPECT_EQ(1U, cache_records.size());
738 std::map<GURL, int64> usage_map;
739 EXPECT_TRUE(db.GetAllOriginUsage(&usage_map));
740 EXPECT_EQ(2U, usage_map.size());
741 EXPECT_EQ(1100, usage_map[kOrigin]);
742 EXPECT_EQ(5000, usage_map[kOtherOrigin]);
745 #if defined(APPCACHE_USE_SIMPLE_CACHE)
746 // There is no such upgrade path in this case.
747 #else
748 TEST(AppCacheDatabaseTest, UpgradeSchema3to5) {
749 // Real file on disk for this test.
750 base::ScopedTempDir temp_dir;
751 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
752 const base::FilePath kDbFile = temp_dir.path().AppendASCII("upgrade3.db");
754 const GURL kMockOrigin("http://mockorigin/");
755 const char kNamespaceUrlFormat[] = "namespace%d";
756 const char kTargetUrlFormat[] = "target%d";
757 const int kNumNamespaces = 10;
759 // Create a v3 schema based database containing some fallback records.
761 const int kVersion3 = 3;
762 const char kGroupsTable[] = "Groups";
763 const char kCachesTable[] = "Caches";
764 const char kEntriesTable[] = "Entries";
765 const char kFallbackNameSpacesTable[] = "FallbackNameSpaces";
766 const char kOnlineWhiteListsTable[] = "OnlineWhiteLists";
767 const char kDeletableResponseIdsTable[] = "DeletableResponseIds";
769 const struct {
770 const char* table_name;
771 const char* columns;
772 } kTables3[] = {
773 { kGroupsTable,
774 "(group_id INTEGER PRIMARY KEY,"
775 " origin TEXT,"
776 " manifest_url TEXT,"
777 " creation_time INTEGER,"
778 " last_access_time INTEGER)" },
780 { kCachesTable,
781 "(cache_id INTEGER PRIMARY KEY,"
782 " group_id INTEGER,"
783 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
784 " update_time INTEGER,"
785 " cache_size INTEGER)" }, // intentionally not normalized
787 { kEntriesTable,
788 "(cache_id INTEGER,"
789 " url TEXT,"
790 " flags INTEGER,"
791 " response_id INTEGER,"
792 " response_size INTEGER)" },
794 { kFallbackNameSpacesTable,
795 "(cache_id INTEGER,"
796 " origin TEXT," // intentionally not normalized
797 " namespace_url TEXT,"
798 " fallback_entry_url TEXT)" },
800 { kOnlineWhiteListsTable,
801 "(cache_id INTEGER,"
802 " namespace_url TEXT)" },
804 { kDeletableResponseIdsTable,
805 "(response_id INTEGER NOT NULL)" },
808 const struct {
809 const char* index_name;
810 const char* table_name;
811 const char* columns;
812 bool unique;
813 } kIndexes3[] = {
814 { "GroupsOriginIndex",
815 kGroupsTable,
816 "(origin)",
817 false },
819 { "GroupsManifestIndex",
820 kGroupsTable,
821 "(manifest_url)",
822 true },
824 { "CachesGroupIndex",
825 kCachesTable,
826 "(group_id)",
827 false },
829 { "EntriesCacheIndex",
830 kEntriesTable,
831 "(cache_id)",
832 false },
834 { "EntriesCacheAndUrlIndex",
835 kEntriesTable,
836 "(cache_id, url)",
837 true },
839 { "EntriesResponseIdIndex",
840 kEntriesTable,
841 "(response_id)",
842 true },
844 { "FallbackNameSpacesCacheIndex",
845 kFallbackNameSpacesTable,
846 "(cache_id)",
847 false },
849 { "FallbackNameSpacesOriginIndex",
850 kFallbackNameSpacesTable,
851 "(origin)",
852 false },
854 { "FallbackNameSpacesCacheAndUrlIndex",
855 kFallbackNameSpacesTable,
856 "(cache_id, namespace_url)",
857 true },
859 { "OnlineWhiteListCacheIndex",
860 kOnlineWhiteListsTable,
861 "(cache_id)",
862 false },
864 { "DeletableResponsesIdIndex",
865 kDeletableResponseIdsTable,
866 "(response_id)",
867 true },
870 const int kTableCount3 = ARRAYSIZE_UNSAFE(kTables3);
871 const int kIndexCount3 = ARRAYSIZE_UNSAFE(kIndexes3);
873 sql::Connection connection;
874 EXPECT_TRUE(connection.Open(kDbFile));
876 sql::Transaction transaction(&connection);
877 EXPECT_TRUE(transaction.Begin());
879 sql::MetaTable meta_table;
880 EXPECT_TRUE(meta_table.Init(&connection, kVersion3, kVersion3));
882 for (int i = 0; i < kTableCount3; ++i) {
883 std::string sql("CREATE TABLE ");
884 sql += kTables3[i].table_name;
885 sql += kTables3[i].columns;
886 EXPECT_TRUE(connection.Execute(sql.c_str()));
889 for (int i = 0; i < kIndexCount3; ++i) {
890 std::string sql;
891 if (kIndexes3[i].unique)
892 sql += "CREATE UNIQUE INDEX ";
893 else
894 sql += "CREATE INDEX ";
895 sql += kIndexes3[i].index_name;
896 sql += " ON ";
897 sql += kIndexes3[i].table_name;
898 sql += kIndexes3[i].columns;
899 EXPECT_TRUE(connection.Execute(sql.c_str()));
902 const char* kSql =
903 "INSERT INTO FallbackNameSpaces"
904 " (cache_id, origin, namespace_url, fallback_entry_url)"
905 " VALUES (?, ?, ?, ?)";
907 sql::Statement statement;
908 statement.Assign(connection.GetUniqueStatement(kSql));
909 EXPECT_TRUE(statement.is_valid());
910 for (int i = 0; i < kNumNamespaces; ++i) {
911 GURL namespace_url(
912 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
913 GURL target_url(
914 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
915 statement.BindInt64(0, i);
916 statement.BindString(1, kMockOrigin.spec().c_str());
917 statement.BindString(2, namespace_url.spec().c_str());
918 statement.BindString(3, target_url.spec().c_str());
919 ASSERT_TRUE(statement.Run());
920 statement.Reset(true);
923 EXPECT_TRUE(transaction.Commit());
926 // Open that database and verify that it got updated.
927 AppCacheDatabase db(kDbFile);
928 EXPECT_TRUE(db.LazyOpen(true));
930 EXPECT_FALSE(db.db_->DoesTableExist("FallbackNameSpaces"));
931 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNamesSpacesCacheIndex"));
932 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNameSpacesOriginIndex"));
933 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNameSpacesCacheAndUrlIndex"));
935 EXPECT_TRUE(db.db_->DoesTableExist("Namespaces"));
936 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesCacheIndex"));
937 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesOriginIndex"));
938 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesCacheAndUrlIndex"));
939 EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "is_pattern"));
940 EXPECT_TRUE(db.db_->DoesColumnExist("OnlineWhiteLists", "is_pattern"));
942 EXPECT_EQ(5, db.meta_table_->GetVersionNumber());
943 EXPECT_EQ(5, db.meta_table_->GetCompatibleVersionNumber());
945 std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
946 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
947 EXPECT_TRUE(db.FindNamespacesForOrigin(kMockOrigin, &intercepts,
948 &fallbacks));
949 EXPECT_TRUE(intercepts.empty());
950 EXPECT_EQ(kNumNamespaces, static_cast<int>(fallbacks.size()));
952 for (int i = 0; i < kNumNamespaces; ++i) {
953 GURL expected_namespace_url(
954 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
955 GURL expected_target_url(
956 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
958 EXPECT_EQ(i, fallbacks[i].cache_id);
959 EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[i].namespace_.type);
960 EXPECT_EQ(kMockOrigin, fallbacks[i].origin);
961 EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_.namespace_url);
962 EXPECT_EQ(expected_target_url, fallbacks[i].namespace_.target_url);
963 EXPECT_FALSE(fallbacks[i].namespace_.is_pattern);
966 #endif // !APPCACHE_USE_SIMPLE_CACHE
968 #if defined(APPCACHE_USE_SIMPLE_CACHE)
969 // There is no such upgrade path in this case.
970 #else
971 TEST(AppCacheDatabaseTest, UpgradeSchema4to5) {
972 // Real file on disk for this test.
973 base::ScopedTempDir temp_dir;
974 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
975 const base::FilePath kDbFile = temp_dir.path().AppendASCII("upgrade4.db");
977 const GURL kMockOrigin("http://mockorigin/");
978 const char kNamespaceUrlFormat[] = "namespace%d";
979 const char kWhitelistUrlFormat[] = "whitelist%d";
980 const char kTargetUrlFormat[] = "target%d";
981 const int kNumNamespaces = 10;
982 const int kWhitelistCacheId = 1;
984 // Create a v4 schema based database containing some fallback records.
986 const int kVersion4 = 4;
987 const char kGroupsTable[] = "Groups";
988 const char kCachesTable[] = "Caches";
989 const char kEntriesTable[] = "Entries";
990 const char kNamespacesTable[] = "Namespaces";
991 const char kOnlineWhiteListsTable[] = "OnlineWhiteLists";
992 const char kDeletableResponseIdsTable[] = "DeletableResponseIds";
994 struct TableInfo {
995 const char* table_name;
996 const char* columns;
999 struct IndexInfo {
1000 const char* index_name;
1001 const char* table_name;
1002 const char* columns;
1003 bool unique;
1006 const TableInfo kTables4[] = {
1007 { kGroupsTable,
1008 "(group_id INTEGER PRIMARY KEY,"
1009 " origin TEXT,"
1010 " manifest_url TEXT,"
1011 " creation_time INTEGER,"
1012 " last_access_time INTEGER)" },
1014 { kCachesTable,
1015 "(cache_id INTEGER PRIMARY KEY,"
1016 " group_id INTEGER,"
1017 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
1018 " update_time INTEGER,"
1019 " cache_size INTEGER)" }, // intentionally not normalized
1021 { kEntriesTable,
1022 "(cache_id INTEGER,"
1023 " url TEXT,"
1024 " flags INTEGER,"
1025 " response_id INTEGER,"
1026 " response_size INTEGER)" },
1028 { kNamespacesTable,
1029 "(cache_id INTEGER,"
1030 " origin TEXT," // intentionally not normalized
1031 " type INTEGER,"
1032 " namespace_url TEXT,"
1033 " target_url TEXT)" },
1035 { kOnlineWhiteListsTable,
1036 "(cache_id INTEGER,"
1037 " namespace_url TEXT)" },
1039 { kDeletableResponseIdsTable,
1040 "(response_id INTEGER NOT NULL)" },
1043 const IndexInfo kIndexes4[] = {
1044 { "GroupsOriginIndex",
1045 kGroupsTable,
1046 "(origin)",
1047 false },
1049 { "GroupsManifestIndex",
1050 kGroupsTable,
1051 "(manifest_url)",
1052 true },
1054 { "CachesGroupIndex",
1055 kCachesTable,
1056 "(group_id)",
1057 false },
1059 { "EntriesCacheIndex",
1060 kEntriesTable,
1061 "(cache_id)",
1062 false },
1064 { "EntriesCacheAndUrlIndex",
1065 kEntriesTable,
1066 "(cache_id, url)",
1067 true },
1069 { "EntriesResponseIdIndex",
1070 kEntriesTable,
1071 "(response_id)",
1072 true },
1074 { "NamespacesCacheIndex",
1075 kNamespacesTable,
1076 "(cache_id)",
1077 false },
1079 { "NamespacesOriginIndex",
1080 kNamespacesTable,
1081 "(origin)",
1082 false },
1084 { "NamespacesCacheAndUrlIndex",
1085 kNamespacesTable,
1086 "(cache_id, namespace_url)",
1087 true },
1089 { "OnlineWhiteListCacheIndex",
1090 kOnlineWhiteListsTable,
1091 "(cache_id)",
1092 false },
1094 { "DeletableResponsesIdIndex",
1095 kDeletableResponseIdsTable,
1096 "(response_id)",
1097 true },
1100 const int kTableCount4 = ARRAYSIZE_UNSAFE(kTables4);
1101 const int kIndexCount4 = ARRAYSIZE_UNSAFE(kIndexes4);
1103 sql::Connection connection;
1104 EXPECT_TRUE(connection.Open(kDbFile));
1106 sql::Transaction transaction(&connection);
1107 EXPECT_TRUE(transaction.Begin());
1109 sql::MetaTable meta_table;
1110 EXPECT_TRUE(meta_table.Init(&connection, kVersion4, kVersion4));
1112 for (int i = 0; i < kTableCount4; ++i) {
1113 std::string sql("CREATE TABLE ");
1114 sql += kTables4[i].table_name;
1115 sql += kTables4[i].columns;
1116 EXPECT_TRUE(connection.Execute(sql.c_str()));
1119 for (int i = 0; i < kIndexCount4; ++i) {
1120 std::string sql;
1121 if (kIndexes4[i].unique)
1122 sql += "CREATE UNIQUE INDEX ";
1123 else
1124 sql += "CREATE INDEX ";
1125 sql += kIndexes4[i].index_name;
1126 sql += " ON ";
1127 sql += kIndexes4[i].table_name;
1128 sql += kIndexes4[i].columns;
1129 EXPECT_TRUE(connection.Execute(sql.c_str()));
1132 const char* kNamespacesSql =
1133 "INSERT INTO Namespaces"
1134 " (cache_id, origin, type, namespace_url, target_url)"
1135 " VALUES (?, ?, ?, ?, ?)";
1136 sql::Statement statement;
1137 statement.Assign(connection.GetUniqueStatement(kNamespacesSql));
1138 EXPECT_TRUE(statement.is_valid());
1139 for (int i = 0; i < kNumNamespaces; ++i) {
1140 GURL namespace_url(
1141 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
1142 GURL target_url(
1143 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
1144 statement.BindInt64(0, i);
1145 statement.BindString(1, kMockOrigin.spec().c_str());
1146 statement.BindInt(2, APPCACHE_FALLBACK_NAMESPACE);
1147 statement.BindString(3, namespace_url.spec().c_str());
1148 statement.BindString(4, target_url.spec().c_str());
1149 ASSERT_TRUE(statement.Run());
1150 statement.Reset(true);
1153 const char* kWhitelistsSql =
1154 "INSERT INTO OnlineWhiteLists"
1155 " (cache_id, namespace_url)"
1156 " VALUES (?, ?)";
1157 statement.Assign(connection.GetUniqueStatement(kWhitelistsSql));
1158 EXPECT_TRUE(statement.is_valid());
1159 for (int i = 0; i < kNumNamespaces; ++i) {
1160 GURL namespace_url(
1161 kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i)));
1162 statement.BindInt64(0, kWhitelistCacheId);
1163 statement.BindString(1, namespace_url.spec().c_str());
1164 ASSERT_TRUE(statement.Run());
1165 statement.Reset(true);
1168 EXPECT_TRUE(transaction.Commit());
1171 // Open that database and verify that it got upgraded to v5.
1172 AppCacheDatabase db(kDbFile);
1173 EXPECT_TRUE(db.LazyOpen(true));
1174 EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "is_pattern"));
1175 EXPECT_TRUE(db.db_->DoesColumnExist("OnlineWhiteLists", "is_pattern"));
1176 EXPECT_EQ(5, db.meta_table_->GetVersionNumber());
1177 EXPECT_EQ(5, db.meta_table_->GetCompatibleVersionNumber());
1179 std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
1180 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
1181 EXPECT_TRUE(db.FindNamespacesForOrigin(kMockOrigin, &intercepts,
1182 &fallbacks));
1183 EXPECT_TRUE(intercepts.empty());
1184 EXPECT_EQ(kNumNamespaces, static_cast<int>(fallbacks.size()));
1186 std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
1187 EXPECT_TRUE(db.FindOnlineWhiteListForCache(kWhitelistCacheId, &whitelists));
1188 EXPECT_EQ(kNumNamespaces, static_cast<int>(whitelists.size()));
1190 for (int i = 0; i < kNumNamespaces; ++i) {
1191 GURL expected_namespace_url(
1192 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
1193 GURL expected_target_url(
1194 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
1195 GURL expected_whitelist_url(
1196 kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i)));
1198 EXPECT_EQ(i, fallbacks[i].cache_id);
1199 EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[i].namespace_.type);
1200 EXPECT_EQ(kMockOrigin, fallbacks[i].origin);
1201 EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_.namespace_url);
1202 EXPECT_EQ(expected_target_url, fallbacks[i].namespace_.target_url);
1203 EXPECT_FALSE(fallbacks[i].namespace_.is_pattern);
1204 EXPECT_EQ(expected_whitelist_url, whitelists[i].namespace_url);
1205 EXPECT_FALSE(whitelists[i].is_pattern);
1208 #endif // !APPCACHE_USE_SIMPLE_CACHE
1210 } // namespace content