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.
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"
22 const base::Time kZeroTime
;
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
));
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.
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
));
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());
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());
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
));
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));
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
;
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
));
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
));
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
);
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
);
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
);
249 EXPECT_TRUE(db
.DeleteEntriesForCache(2));
250 EXPECT_TRUE(db
.FindEntriesForCache(2, &found
));
251 EXPECT_TRUE(found
.empty());
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
));
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
));
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
));
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());
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));
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());
412 record
.manifest_url
= kManifest2
;
413 record
.origin
= kOrigin2
;
414 EXPECT_TRUE(db
.InsertGroup(&record
));
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.
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
));
477 record
.origin
= kFooOrigin
;
478 record
.namespace_
.namespace_url
= kFooNameSpace2
;
479 record
.namespace_
.target_url
= kFooFallbackEntry
;
480 EXPECT_TRUE(db
.InsertNamespace(&record
));
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
);
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
);
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));
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.
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
));
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
));
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
);
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));
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
));
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
);
589 record
.namespace_url
= kBarNameSpace1
;
590 EXPECT_TRUE(db
.InsertOnlineWhiteList(&record
));
592 EXPECT_TRUE(db
.FindOnlineWhiteListForCache(2, &records
));
593 EXPECT_EQ(1U, records
.size());
595 EXPECT_TRUE(db
.DeleteOnlineWhiteListForCache(1));
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());
615 EXPECT_TRUE(db
.DeleteDeletableResponseIds(ids
));
616 EXPECT_TRUE(db
.InsertDeletableResponseIds(ids
));
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.
634 EXPECT_FALSE(db
.InsertDeletableResponseIds(ids
));
637 for (int i
= 1; i
< 10; ++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
);
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.
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).
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
));
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.
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";
770 const char* table_name
;
774 "(group_id INTEGER PRIMARY KEY,"
776 " manifest_url TEXT,"
777 " creation_time INTEGER,"
778 " last_access_time INTEGER)" },
781 "(cache_id INTEGER PRIMARY KEY,"
783 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
784 " update_time INTEGER,"
785 " cache_size INTEGER)" }, // intentionally not normalized
791 " response_id INTEGER,"
792 " response_size INTEGER)" },
794 { kFallbackNameSpacesTable
,
796 " origin TEXT," // intentionally not normalized
797 " namespace_url TEXT,"
798 " fallback_entry_url TEXT)" },
800 { kOnlineWhiteListsTable
,
802 " namespace_url TEXT)" },
804 { kDeletableResponseIdsTable
,
805 "(response_id INTEGER NOT NULL)" },
809 const char* index_name
;
810 const char* table_name
;
814 { "GroupsOriginIndex",
819 { "GroupsManifestIndex",
824 { "CachesGroupIndex",
829 { "EntriesCacheIndex",
834 { "EntriesCacheAndUrlIndex",
839 { "EntriesResponseIdIndex",
844 { "FallbackNameSpacesCacheIndex",
845 kFallbackNameSpacesTable
,
849 { "FallbackNameSpacesOriginIndex",
850 kFallbackNameSpacesTable
,
854 { "FallbackNameSpacesCacheAndUrlIndex",
855 kFallbackNameSpacesTable
,
856 "(cache_id, namespace_url)",
859 { "OnlineWhiteListCacheIndex",
860 kOnlineWhiteListsTable
,
864 { "DeletableResponsesIdIndex",
865 kDeletableResponseIdsTable
,
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
) {
891 if (kIndexes3
[i
].unique
)
892 sql
+= "CREATE UNIQUE INDEX ";
894 sql
+= "CREATE INDEX ";
895 sql
+= kIndexes3
[i
].index_name
;
897 sql
+= kIndexes3
[i
].table_name
;
898 sql
+= kIndexes3
[i
].columns
;
899 EXPECT_TRUE(connection
.Execute(sql
.c_str()));
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
) {
912 kMockOrigin
.Resolve(base::StringPrintf(kNamespaceUrlFormat
, i
)));
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
,
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.
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";
995 const char* table_name
;
1000 const char* index_name
;
1001 const char* table_name
;
1002 const char* columns
;
1006 const TableInfo kTables4
[] = {
1008 "(group_id INTEGER PRIMARY KEY,"
1010 " manifest_url TEXT,"
1011 " creation_time INTEGER,"
1012 " last_access_time INTEGER)" },
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
1022 "(cache_id INTEGER,"
1025 " response_id INTEGER,"
1026 " response_size INTEGER)" },
1029 "(cache_id INTEGER,"
1030 " origin TEXT," // intentionally not normalized
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",
1049 { "GroupsManifestIndex",
1054 { "CachesGroupIndex",
1059 { "EntriesCacheIndex",
1064 { "EntriesCacheAndUrlIndex",
1069 { "EntriesResponseIdIndex",
1074 { "NamespacesCacheIndex",
1079 { "NamespacesOriginIndex",
1084 { "NamespacesCacheAndUrlIndex",
1086 "(cache_id, namespace_url)",
1089 { "OnlineWhiteListCacheIndex",
1090 kOnlineWhiteListsTable
,
1094 { "DeletableResponsesIdIndex",
1095 kDeletableResponseIdsTable
,
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
) {
1121 if (kIndexes4
[i
].unique
)
1122 sql
+= "CREATE UNIQUE INDEX ";
1124 sql
+= "CREATE INDEX ";
1125 sql
+= kIndexes4
[i
].index_name
;
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
) {
1141 kMockOrigin
.Resolve(base::StringPrintf(kNamespaceUrlFormat
, i
)));
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)"
1157 statement
.Assign(connection
.GetUniqueStatement(kWhitelistsSql
));
1158 EXPECT_TRUE(statement
.is_valid());
1159 for (int i
= 0; i
< kNumNamespaces
; ++i
) {
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
,
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