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.
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/test/test_helpers.h"
14 #include "sql/transaction.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/sqlite/sqlite3.h"
17 #include "webkit/browser/appcache/appcache_database.h"
18 #include "webkit/browser/appcache/appcache_entry.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, file_util::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, file_util::WriteFile(kOtherFile, "foo", 3));
95 // First create a valid db file.
96 AppCacheDatabase db(kDbFile);
97 EXPECT_TRUE(db.LazyOpen(true));
98 EXPECT_TRUE(base::PathExists(kOtherFile));
99 EXPECT_TRUE(base::PathExists(kDbFile));
100 db.CloseConnection();
103 ASSERT_TRUE(sql::test::CorruptSizeInHeader(kDbFile));
105 // Reopening will notice the corruption and delete/recreate the directory.
107 sql::ScopedErrorIgnorer ignore_errors;
108 ignore_errors.IgnoreError(SQLITE_CORRUPT);
109 EXPECT_TRUE(db.LazyOpen(true));
110 EXPECT_FALSE(base::PathExists(kOtherFile));
111 EXPECT_TRUE(base::PathExists(kDbFile));
112 EXPECT_TRUE(ignore_errors.CheckIgnoredErrors());
117 TEST(AppCacheDatabaseTest, WasCorrutionDetected) {
118 // Real files on disk for this test too, a corrupt database file.
119 base::ScopedTempDir temp_dir;
120 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
121 const base::FilePath kDbFile = temp_dir.path().AppendASCII("appcache.db");
123 // First create a valid db file.
124 AppCacheDatabase db(kDbFile);
125 EXPECT_TRUE(db.LazyOpen(true));
126 EXPECT_TRUE(base::PathExists(kDbFile));
127 EXPECT_FALSE(db.was_corruption_detected());
130 ASSERT_TRUE(sql::test::CorruptSizeInHeader(kDbFile));
132 // See the the corruption is detected and reported.
134 sql::ScopedErrorIgnorer ignore_errors;
135 ignore_errors.IgnoreError(SQLITE_CORRUPT);
136 std::map<GURL, int64> usage_map;
137 EXPECT_FALSE(db.GetAllOriginUsage(&usage_map));
138 EXPECT_TRUE(db.was_corruption_detected());
139 EXPECT_TRUE(base::PathExists(kDbFile));
140 EXPECT_TRUE(ignore_errors.CheckIgnoredErrors());
144 TEST(AppCacheDatabaseTest, ExperimentalFlags) {
145 const char kExperimentFlagsKey[] = "ExperimentFlags";
146 std::string kInjectedFlags("exp1,exp2");
148 // Real files on disk for this test.
149 base::ScopedTempDir temp_dir;
150 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
151 const base::FilePath kDbFile = temp_dir.path().AppendASCII("appcache.db");
152 const base::FilePath kOtherFile = temp_dir.path().AppendASCII("other_file");
153 EXPECT_EQ(3, file_util::WriteFile(kOtherFile, "foo", 3));
154 EXPECT_TRUE(base::PathExists(kOtherFile));
156 AppCacheDatabase db(kDbFile);
157 EXPECT_TRUE(db.LazyOpen(true));
159 // Inject a non empty flags value, and verify it got there.
160 EXPECT_TRUE(db.meta_table_->SetValue(kExperimentFlagsKey, kInjectedFlags));
162 EXPECT_TRUE(db.meta_table_->GetValue(kExperimentFlagsKey, &flags));
163 EXPECT_EQ(kInjectedFlags, flags);
164 db.CloseConnection();
166 // If flags don't match the expected value, empty string by default,
167 // the database should be recreated and other files should be cleared out.
168 EXPECT_TRUE(db.LazyOpen(false));
169 EXPECT_TRUE(db.meta_table_->GetValue(kExperimentFlagsKey, &flags));
170 EXPECT_TRUE(flags.empty());
171 EXPECT_FALSE(base::PathExists(kOtherFile));
174 TEST(AppCacheDatabaseTest, EntryRecords) {
175 const base::FilePath kEmptyPath;
176 AppCacheDatabase db(kEmptyPath);
177 EXPECT_TRUE(db.LazyOpen(true));
179 sql::ScopedErrorIgnorer ignore_errors;
180 // TODO(shess): Suppressing SQLITE_CONSTRAINT because the code
181 // expects that and handles the resulting error. Consider revising
182 // the code to use INSERT OR IGNORE (which would not throw
183 // SQLITE_CONSTRAINT) and then check ChangeCount() to see if any
184 // changes were made.
185 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
187 AppCacheDatabase::EntryRecord entry;
190 entry.url = GURL("http://blah/1");
191 entry.flags = AppCacheEntry::MASTER;
192 entry.response_id = 1;
193 entry.response_size = 100;
194 EXPECT_TRUE(db.InsertEntry(&entry));
195 EXPECT_FALSE(db.InsertEntry(&entry));
198 entry.url = GURL("http://blah/2");
199 entry.flags = AppCacheEntry::EXPLICIT;
200 entry.response_id = 2;
201 entry.response_size = 200;
202 EXPECT_TRUE(db.InsertEntry(&entry));
205 entry.url = GURL("http://blah/3");
206 entry.flags = AppCacheEntry::MANIFEST;
207 entry.response_id = 3;
208 entry.response_size = 300;
209 EXPECT_TRUE(db.InsertEntry(&entry));
211 std::vector<AppCacheDatabase::EntryRecord> found;
213 EXPECT_TRUE(db.FindEntriesForCache(1, &found));
214 EXPECT_EQ(1U, found.size());
215 EXPECT_EQ(1, found[0].cache_id);
216 EXPECT_EQ(GURL("http://blah/1"), found[0].url);
217 EXPECT_EQ(AppCacheEntry::MASTER, found[0].flags);
218 EXPECT_EQ(1, found[0].response_id);
219 EXPECT_EQ(100, found[0].response_size);
222 EXPECT_TRUE(db.AddEntryFlags(GURL("http://blah/1"), 1,
223 AppCacheEntry::FOREIGN));
224 EXPECT_TRUE(db.FindEntriesForCache(1, &found));
225 EXPECT_EQ(1U, found.size());
226 EXPECT_EQ(AppCacheEntry::MASTER | AppCacheEntry::FOREIGN, found[0].flags);
229 EXPECT_TRUE(db.FindEntriesForCache(2, &found));
230 EXPECT_EQ(2U, found.size());
231 EXPECT_EQ(2, found[0].cache_id);
232 EXPECT_EQ(GURL("http://blah/2"), found[0].url);
233 EXPECT_EQ(AppCacheEntry::EXPLICIT, found[0].flags);
234 EXPECT_EQ(2, found[0].response_id);
235 EXPECT_EQ(200, found[0].response_size);
236 EXPECT_EQ(2, found[1].cache_id);
237 EXPECT_EQ(GURL("http://blah/3"), found[1].url);
238 EXPECT_EQ(AppCacheEntry::MANIFEST, found[1].flags);
239 EXPECT_EQ(3, found[1].response_id);
240 EXPECT_EQ(300, found[1].response_size);
243 EXPECT_TRUE(db.DeleteEntriesForCache(2));
244 EXPECT_TRUE(db.FindEntriesForCache(2, &found));
245 EXPECT_TRUE(found.empty());
248 EXPECT_TRUE(db.DeleteEntriesForCache(1));
249 EXPECT_FALSE(db.AddEntryFlags(GURL("http://blah/1"), 1,
250 AppCacheEntry::FOREIGN));
252 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
255 TEST(AppCacheDatabaseTest, CacheRecords) {
256 const base::FilePath kEmptyPath;
257 AppCacheDatabase db(kEmptyPath);
258 EXPECT_TRUE(db.LazyOpen(true));
260 sql::ScopedErrorIgnorer ignore_errors;
261 // TODO(shess): See EntryRecords test.
262 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
264 const AppCacheDatabase::CacheRecord kZeroRecord;
265 AppCacheDatabase::CacheRecord record;
266 EXPECT_FALSE(db.FindCache(1, &record));
270 record.online_wildcard = true;
271 record.update_time = kZeroTime;
272 record.cache_size = 100;
273 EXPECT_TRUE(db.InsertCache(&record));
274 EXPECT_FALSE(db.InsertCache(&record));
276 record = kZeroRecord;
277 EXPECT_TRUE(db.FindCache(1, &record));
278 EXPECT_EQ(1, record.cache_id);
279 EXPECT_EQ(1, record.group_id);
280 EXPECT_TRUE(record.online_wildcard);
281 EXPECT_TRUE(kZeroTime == record.update_time);
282 EXPECT_EQ(100, record.cache_size);
284 record = kZeroRecord;
285 EXPECT_TRUE(db.FindCacheForGroup(1, &record));
286 EXPECT_EQ(1, record.cache_id);
287 EXPECT_EQ(1, record.group_id);
288 EXPECT_TRUE(record.online_wildcard);
289 EXPECT_TRUE(kZeroTime == record.update_time);
290 EXPECT_EQ(100, record.cache_size);
292 EXPECT_TRUE(db.DeleteCache(1));
293 EXPECT_FALSE(db.FindCache(1, &record));
294 EXPECT_FALSE(db.FindCacheForGroup(1, &record));
296 EXPECT_TRUE(db.DeleteCache(1));
298 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
301 TEST(AppCacheDatabaseTest, GroupRecords) {
302 const base::FilePath kEmptyPath;
303 AppCacheDatabase db(kEmptyPath);
304 EXPECT_TRUE(db.LazyOpen(true));
306 sql::ScopedErrorIgnorer ignore_errors;
307 // TODO(shess): See EntryRecords test.
308 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
310 const GURL kManifestUrl("http://blah/manifest");
311 const GURL kOrigin(kManifestUrl.GetOrigin());
312 const base::Time kLastAccessTime = base::Time::Now();
313 const base::Time kCreationTime =
314 kLastAccessTime - base::TimeDelta::FromDays(7);
316 const AppCacheDatabase::GroupRecord kZeroRecord;
317 AppCacheDatabase::GroupRecord record;
318 std::vector<AppCacheDatabase::GroupRecord> records;
320 // Behavior with an empty table
321 EXPECT_FALSE(db.FindGroup(1, &record));
322 EXPECT_FALSE(db.FindGroupForManifestUrl(kManifestUrl, &record));
323 EXPECT_TRUE(db.DeleteGroup(1));
324 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
325 EXPECT_TRUE(records.empty());
326 EXPECT_FALSE(db.FindGroupForCache(1, &record));
329 record.manifest_url = kManifestUrl;
330 record.origin = kOrigin;
331 record.last_access_time = kLastAccessTime;
332 record.creation_time = kCreationTime;
333 EXPECT_TRUE(db.InsertGroup(&record));
334 EXPECT_FALSE(db.InsertGroup(&record));
337 EXPECT_FALSE(db.InsertGroup(&record));
339 record = kZeroRecord;
340 EXPECT_TRUE(db.FindGroup(1, &record));
341 EXPECT_EQ(1, record.group_id);
342 EXPECT_EQ(kManifestUrl, record.manifest_url);
343 EXPECT_EQ(kOrigin, record.origin);
344 EXPECT_EQ(kCreationTime.ToInternalValue(),
345 record.creation_time.ToInternalValue());
346 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
347 record.last_access_time.ToInternalValue());
349 record = kZeroRecord;
350 EXPECT_TRUE(db.FindGroupForManifestUrl(kManifestUrl, &record));
351 EXPECT_EQ(1, record.group_id);
352 EXPECT_EQ(kManifestUrl, record.manifest_url);
353 EXPECT_EQ(kOrigin, record.origin);
354 EXPECT_EQ(kCreationTime.ToInternalValue(),
355 record.creation_time.ToInternalValue());
356 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
357 record.last_access_time.ToInternalValue());
360 record.manifest_url = kOrigin;
361 record.origin = kOrigin;
362 record.last_access_time = kLastAccessTime;
363 record.creation_time = kCreationTime;
364 EXPECT_TRUE(db.InsertGroup(&record));
366 record = kZeroRecord;
367 EXPECT_TRUE(db.FindGroupForManifestUrl(kOrigin, &record));
368 EXPECT_EQ(2, record.group_id);
369 EXPECT_EQ(kOrigin, record.manifest_url);
370 EXPECT_EQ(kOrigin, record.origin);
371 EXPECT_EQ(kCreationTime.ToInternalValue(),
372 record.creation_time.ToInternalValue());
373 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
374 record.last_access_time.ToInternalValue());
376 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
377 EXPECT_EQ(2U, records.size());
378 EXPECT_EQ(1, records[0].group_id);
379 EXPECT_EQ(kManifestUrl, records[0].manifest_url);
380 EXPECT_EQ(kOrigin, records[0].origin);
381 EXPECT_EQ(2, records[1].group_id);
382 EXPECT_EQ(kOrigin, records[1].manifest_url);
383 EXPECT_EQ(kOrigin, records[1].origin);
385 EXPECT_TRUE(db.DeleteGroup(1));
388 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
389 EXPECT_EQ(1U, records.size());
390 EXPECT_EQ(2, records[0].group_id);
391 EXPECT_EQ(kOrigin, records[0].manifest_url);
392 EXPECT_EQ(kOrigin, records[0].origin);
393 EXPECT_EQ(kCreationTime.ToInternalValue(),
394 record.creation_time.ToInternalValue());
395 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
396 record.last_access_time.ToInternalValue());
398 std::set<GURL> origins;
399 EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
400 EXPECT_EQ(1U, origins.size());
401 EXPECT_EQ(kOrigin, *(origins.begin()));
403 const GURL kManifest2("http://blah2/manifest");
404 const GURL kOrigin2(kManifest2.GetOrigin());
406 record.manifest_url = kManifest2;
407 record.origin = kOrigin2;
408 EXPECT_TRUE(db.InsertGroup(&record));
411 EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
412 EXPECT_EQ(2U, origins.size());
413 EXPECT_TRUE(origins.end() != origins.find(kOrigin));
414 EXPECT_TRUE(origins.end() != origins.find(kOrigin2));
416 AppCacheDatabase::CacheRecord cache_record;
417 cache_record.cache_id = 1;
418 cache_record.group_id = 1;
419 cache_record.online_wildcard = true;
420 cache_record.update_time = kZeroTime;
421 EXPECT_TRUE(db.InsertCache(&cache_record));
423 record = kZeroRecord;
424 EXPECT_TRUE(db.FindGroupForCache(1, &record));
425 EXPECT_EQ(1, record.group_id);
426 EXPECT_EQ(kManifest2, record.manifest_url);
427 EXPECT_EQ(kOrigin2, record.origin);
429 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
432 TEST(AppCacheDatabaseTest, NamespaceRecords) {
433 const base::FilePath kEmptyPath;
434 AppCacheDatabase db(kEmptyPath);
435 EXPECT_TRUE(db.LazyOpen(true));
437 sql::ScopedErrorIgnorer ignore_errors;
438 // TODO(shess): See EntryRecords test.
439 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
441 const GURL kFooNameSpace1("http://foo/namespace1");
442 const GURL kFooNameSpace2("http://foo/namespace2");
443 const GURL kFooFallbackEntry("http://foo/entry");
444 const GURL kFooOrigin(kFooNameSpace1.GetOrigin());
445 const GURL kBarNameSpace1("http://bar/namespace1");
446 const GURL kBarNameSpace2("http://bar/namespace2");
447 const GURL kBarFallbackEntry("http://bar/entry");
448 const GURL kBarOrigin(kBarNameSpace1.GetOrigin());
450 const AppCacheDatabase::NamespaceRecord kZeroRecord;
451 AppCacheDatabase::NamespaceRecord record;
452 std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
453 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
455 // Behavior with an empty table
456 EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks));
457 EXPECT_TRUE(fallbacks.empty());
458 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
459 EXPECT_TRUE(fallbacks.empty());
460 EXPECT_TRUE(db.DeleteNamespacesForCache(1));
462 // Two records for two differenent caches in the Foo origin.
464 record.origin = kFooOrigin;
465 record.namespace_.namespace_url = kFooNameSpace1;
466 record.namespace_.target_url = kFooFallbackEntry;
467 EXPECT_TRUE(db.InsertNamespace(&record));
468 EXPECT_FALSE(db.InsertNamespace(&record));
471 record.origin = kFooOrigin;
472 record.namespace_.namespace_url = kFooNameSpace2;
473 record.namespace_.target_url = kFooFallbackEntry;
474 EXPECT_TRUE(db.InsertNamespace(&record));
477 EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks));
478 EXPECT_EQ(1U, fallbacks.size());
479 EXPECT_EQ(1, fallbacks[0].cache_id);
480 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
481 EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url);
482 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
483 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
486 EXPECT_TRUE(db.FindNamespacesForCache(2, &intercepts, &fallbacks));
487 EXPECT_EQ(1U, fallbacks.size());
488 EXPECT_EQ(2, fallbacks[0].cache_id);
489 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
490 EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url);
491 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
492 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
495 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
496 EXPECT_EQ(2U, fallbacks.size());
497 EXPECT_EQ(1, fallbacks[0].cache_id);
498 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
499 EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url);
500 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
501 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
502 EXPECT_EQ(2, fallbacks[1].cache_id);
503 EXPECT_EQ(kFooOrigin, fallbacks[1].origin);
504 EXPECT_EQ(kFooNameSpace2, fallbacks[1].namespace_.namespace_url);
505 EXPECT_EQ(kFooFallbackEntry, fallbacks[1].namespace_.target_url);
506 EXPECT_FALSE(fallbacks[1].namespace_.is_pattern);
508 EXPECT_TRUE(db.DeleteNamespacesForCache(1));
510 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
511 EXPECT_EQ(1U, fallbacks.size());
512 EXPECT_EQ(2, fallbacks[0].cache_id);
513 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
514 EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url);
515 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
516 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
518 // Two more records for the same cache in the Bar origin.
520 record.origin = kBarOrigin;
521 record.namespace_.namespace_url = kBarNameSpace1;
522 record.namespace_.target_url = kBarFallbackEntry;
523 record.namespace_.is_pattern = true;
524 EXPECT_TRUE(db.InsertNamespace(&record));
527 record.origin = kBarOrigin;
528 record.namespace_.namespace_url = kBarNameSpace2;
529 record.namespace_.target_url = kBarFallbackEntry;
530 record.namespace_.is_pattern = true;
531 EXPECT_TRUE(db.InsertNamespace(&record));
534 EXPECT_TRUE(db.FindNamespacesForCache(3, &intercepts, &fallbacks));
535 EXPECT_EQ(2U, fallbacks.size());
536 EXPECT_TRUE(fallbacks[0].namespace_.is_pattern);
537 EXPECT_TRUE(fallbacks[1].namespace_.is_pattern);
540 EXPECT_TRUE(db.FindNamespacesForOrigin(kBarOrigin, &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 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
548 TEST(AppCacheDatabaseTest, OnlineWhiteListRecords) {
549 const base::FilePath kEmptyPath;
550 AppCacheDatabase db(kEmptyPath);
551 EXPECT_TRUE(db.LazyOpen(true));
553 const GURL kFooNameSpace1("http://foo/namespace1");
554 const GURL kFooNameSpace2("http://foo/namespace2");
555 const GURL kBarNameSpace1("http://bar/namespace1");
557 const AppCacheDatabase::OnlineWhiteListRecord kZeroRecord;
558 AppCacheDatabase::OnlineWhiteListRecord record;
559 std::vector<AppCacheDatabase::OnlineWhiteListRecord> records;
561 // Behavior with an empty table
562 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records));
563 EXPECT_TRUE(records.empty());
564 EXPECT_TRUE(db.DeleteOnlineWhiteListForCache(1));
567 record.namespace_url = kFooNameSpace1;
568 EXPECT_TRUE(db.InsertOnlineWhiteList(&record));
569 record.namespace_url = kFooNameSpace2;
570 record.is_pattern = true;
571 EXPECT_TRUE(db.InsertOnlineWhiteList(&record));
573 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records));
574 EXPECT_EQ(2U, records.size());
575 EXPECT_EQ(1, records[0].cache_id);
576 EXPECT_EQ(kFooNameSpace1, records[0].namespace_url);
577 EXPECT_FALSE(records[0].is_pattern);
578 EXPECT_EQ(1, records[1].cache_id);
579 EXPECT_EQ(kFooNameSpace2, records[1].namespace_url);
580 EXPECT_TRUE(records[1].is_pattern);
583 record.namespace_url = kBarNameSpace1;
584 EXPECT_TRUE(db.InsertOnlineWhiteList(&record));
586 EXPECT_TRUE(db.FindOnlineWhiteListForCache(2, &records));
587 EXPECT_EQ(1U, records.size());
589 EXPECT_TRUE(db.DeleteOnlineWhiteListForCache(1));
591 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records));
592 EXPECT_TRUE(records.empty());
595 TEST(AppCacheDatabaseTest, DeletableResponseIds) {
596 const base::FilePath kEmptyPath;
597 AppCacheDatabase db(kEmptyPath);
598 EXPECT_TRUE(db.LazyOpen(true));
600 sql::ScopedErrorIgnorer ignore_errors;
601 // TODO(shess): See EntryRecords test.
602 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
604 std::vector<int64> ids;
606 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
607 EXPECT_TRUE(ids.empty());
609 EXPECT_TRUE(db.DeleteDeletableResponseIds(ids));
610 EXPECT_TRUE(db.InsertDeletableResponseIds(ids));
613 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
614 EXPECT_EQ(1U, ids.size());
615 EXPECT_EQ(0, ids[0]);
617 int64 unused, deleteable_response_rowid;
618 unused = deleteable_response_rowid = 0;
619 EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused,
620 &deleteable_response_rowid));
621 EXPECT_EQ(1, deleteable_response_rowid);
624 // Expected to fail due to the duplicate id, 0 is already in the table.
628 EXPECT_FALSE(db.InsertDeletableResponseIds(ids));
631 for (int i = 1; i < 10; ++i)
633 EXPECT_TRUE(db.InsertDeletableResponseIds(ids));
634 EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused,
635 &deleteable_response_rowid));
636 EXPECT_EQ(10, deleteable_response_rowid);
639 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
640 EXPECT_EQ(10U, ids.size());
641 for (int i = 0; i < 10; ++i)
642 EXPECT_EQ(i, ids[i]);
644 // Ensure the limit is respected.
646 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 5));
647 EXPECT_EQ(5U, ids.size());
648 for (int i = 0; i < static_cast<int>(ids.size()); ++i)
649 EXPECT_EQ(i, ids[i]);
651 // Ensure the max_rowid is respected (the first rowid is 1).
653 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, 5, 100));
654 EXPECT_EQ(5U, ids.size());
655 for (int i = 0; i < static_cast<int>(ids.size()); ++i)
656 EXPECT_EQ(i, ids[i]);
658 // Ensure that we can delete from the table.
659 EXPECT_TRUE(db.DeleteDeletableResponseIds(ids));
661 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
662 EXPECT_EQ(5U, ids.size());
663 for (int i = 0; i < static_cast<int>(ids.size()); ++i)
664 EXPECT_EQ(i + 5, ids[i]);
666 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
669 TEST(AppCacheDatabaseTest, OriginUsage) {
670 const GURL kManifestUrl("http://blah/manifest");
671 const GURL kManifestUrl2("http://blah/manifest2");
672 const GURL kOrigin(kManifestUrl.GetOrigin());
673 const GURL kOtherOriginManifestUrl("http://other/manifest");
674 const GURL kOtherOrigin(kOtherOriginManifestUrl.GetOrigin());
676 const base::FilePath kEmptyPath;
677 AppCacheDatabase db(kEmptyPath);
678 EXPECT_TRUE(db.LazyOpen(true));
680 std::vector<AppCacheDatabase::CacheRecord> cache_records;
681 EXPECT_EQ(0, db.GetOriginUsage(kOrigin));
682 EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records));
683 EXPECT_TRUE(cache_records.empty());
685 AppCacheDatabase::GroupRecord group_record;
686 group_record.group_id = 1;
687 group_record.manifest_url = kManifestUrl;
688 group_record.origin = kOrigin;
689 EXPECT_TRUE(db.InsertGroup(&group_record));
690 AppCacheDatabase::CacheRecord cache_record;
691 cache_record.cache_id = 1;
692 cache_record.group_id = 1;
693 cache_record.online_wildcard = true;
694 cache_record.update_time = kZeroTime;
695 cache_record.cache_size = 100;
696 EXPECT_TRUE(db.InsertCache(&cache_record));
698 EXPECT_EQ(100, db.GetOriginUsage(kOrigin));
700 group_record.group_id = 2;
701 group_record.manifest_url = kManifestUrl2;
702 group_record.origin = kOrigin;
703 EXPECT_TRUE(db.InsertGroup(&group_record));
704 cache_record.cache_id = 2;
705 cache_record.group_id = 2;
706 cache_record.online_wildcard = true;
707 cache_record.update_time = kZeroTime;
708 cache_record.cache_size = 1000;
709 EXPECT_TRUE(db.InsertCache(&cache_record));
711 EXPECT_EQ(1100, db.GetOriginUsage(kOrigin));
713 group_record.group_id = 3;
714 group_record.manifest_url = kOtherOriginManifestUrl;
715 group_record.origin = kOtherOrigin;
716 EXPECT_TRUE(db.InsertGroup(&group_record));
717 cache_record.cache_id = 3;
718 cache_record.group_id = 3;
719 cache_record.online_wildcard = true;
720 cache_record.update_time = kZeroTime;
721 cache_record.cache_size = 5000;
722 EXPECT_TRUE(db.InsertCache(&cache_record));
724 EXPECT_EQ(5000, db.GetOriginUsage(kOtherOrigin));
726 EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records));
727 EXPECT_EQ(2U, cache_records.size());
728 cache_records.clear();
729 EXPECT_TRUE(db.FindCachesForOrigin(kOtherOrigin, &cache_records));
730 EXPECT_EQ(1U, cache_records.size());
732 std::map<GURL, int64> usage_map;
733 EXPECT_TRUE(db.GetAllOriginUsage(&usage_map));
734 EXPECT_EQ(2U, usage_map.size());
735 EXPECT_EQ(1100, usage_map[kOrigin]);
736 EXPECT_EQ(5000, usage_map[kOtherOrigin]);
739 #if defined(APPCACHE_USE_SIMPLE_CACHE)
740 // There is no such upgrade path in this case.
742 TEST(AppCacheDatabaseTest, UpgradeSchema3to5) {
743 // Real file on disk for this test.
744 base::ScopedTempDir temp_dir;
745 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
746 const base::FilePath kDbFile = temp_dir.path().AppendASCII("upgrade3.db");
748 const GURL kMockOrigin("http://mockorigin/");
749 const char kNamespaceUrlFormat[] = "namespace%d";
750 const char kTargetUrlFormat[] = "target%d";
751 const int kNumNamespaces = 10;
753 // Create a v3 schema based database containing some fallback records.
755 const int kVersion3 = 3;
756 const char kGroupsTable[] = "Groups";
757 const char kCachesTable[] = "Caches";
758 const char kEntriesTable[] = "Entries";
759 const char kFallbackNameSpacesTable[] = "FallbackNameSpaces";
760 const char kOnlineWhiteListsTable[] = "OnlineWhiteLists";
761 const char kDeletableResponseIdsTable[] = "DeletableResponseIds";
764 const char* table_name;
768 "(group_id INTEGER PRIMARY KEY,"
770 " manifest_url TEXT,"
771 " creation_time INTEGER,"
772 " last_access_time INTEGER)" },
775 "(cache_id INTEGER PRIMARY KEY,"
777 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
778 " update_time INTEGER,"
779 " cache_size INTEGER)" }, // intentionally not normalized
785 " response_id INTEGER,"
786 " response_size INTEGER)" },
788 { kFallbackNameSpacesTable,
790 " origin TEXT," // intentionally not normalized
791 " namespace_url TEXT,"
792 " fallback_entry_url TEXT)" },
794 { kOnlineWhiteListsTable,
796 " namespace_url TEXT)" },
798 { kDeletableResponseIdsTable,
799 "(response_id INTEGER NOT NULL)" },
803 const char* index_name;
804 const char* table_name;
808 { "GroupsOriginIndex",
813 { "GroupsManifestIndex",
818 { "CachesGroupIndex",
823 { "EntriesCacheIndex",
828 { "EntriesCacheAndUrlIndex",
833 { "EntriesResponseIdIndex",
838 { "FallbackNameSpacesCacheIndex",
839 kFallbackNameSpacesTable,
843 { "FallbackNameSpacesOriginIndex",
844 kFallbackNameSpacesTable,
848 { "FallbackNameSpacesCacheAndUrlIndex",
849 kFallbackNameSpacesTable,
850 "(cache_id, namespace_url)",
853 { "OnlineWhiteListCacheIndex",
854 kOnlineWhiteListsTable,
858 { "DeletableResponsesIdIndex",
859 kDeletableResponseIdsTable,
864 const int kTableCount3 = ARRAYSIZE_UNSAFE(kTables3);
865 const int kIndexCount3 = ARRAYSIZE_UNSAFE(kIndexes3);
867 sql::Connection connection;
868 EXPECT_TRUE(connection.Open(kDbFile));
870 sql::Transaction transaction(&connection);
871 EXPECT_TRUE(transaction.Begin());
873 sql::MetaTable meta_table;
874 EXPECT_TRUE(meta_table.Init(&connection, kVersion3, kVersion3));
876 for (int i = 0; i < kTableCount3; ++i) {
877 std::string sql("CREATE TABLE ");
878 sql += kTables3[i].table_name;
879 sql += kTables3[i].columns;
880 EXPECT_TRUE(connection.Execute(sql.c_str()));
883 for (int i = 0; i < kIndexCount3; ++i) {
885 if (kIndexes3[i].unique)
886 sql += "CREATE UNIQUE INDEX ";
888 sql += "CREATE INDEX ";
889 sql += kIndexes3[i].index_name;
891 sql += kIndexes3[i].table_name;
892 sql += kIndexes3[i].columns;
893 EXPECT_TRUE(connection.Execute(sql.c_str()));
897 "INSERT INTO FallbackNameSpaces"
898 " (cache_id, origin, namespace_url, fallback_entry_url)"
899 " VALUES (?, ?, ?, ?)";
901 sql::Statement statement;
902 statement.Assign(connection.GetUniqueStatement(kSql));
903 EXPECT_TRUE(statement.is_valid());
904 for (int i = 0; i < kNumNamespaces; ++i) {
906 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
908 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
909 statement.BindInt64(0, i);
910 statement.BindString(1, kMockOrigin.spec().c_str());
911 statement.BindString(2, namespace_url.spec().c_str());
912 statement.BindString(3, target_url.spec().c_str());
913 ASSERT_TRUE(statement.Run());
914 statement.Reset(true);
917 EXPECT_TRUE(transaction.Commit());
920 // Open that database and verify that it got updated.
921 AppCacheDatabase db(kDbFile);
922 EXPECT_TRUE(db.LazyOpen(true));
924 EXPECT_FALSE(db.db_->DoesTableExist("FallbackNameSpaces"));
925 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNamesSpacesCacheIndex"));
926 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNameSpacesOriginIndex"));
927 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNameSpacesCacheAndUrlIndex"));
929 EXPECT_TRUE(db.db_->DoesTableExist("Namespaces"));
930 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesCacheIndex"));
931 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesOriginIndex"));
932 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesCacheAndUrlIndex"));
933 EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "is_pattern"));
934 EXPECT_TRUE(db.db_->DoesColumnExist("OnlineWhiteLists", "is_pattern"));
936 EXPECT_EQ(5, db.meta_table_->GetVersionNumber());
937 EXPECT_EQ(5, db.meta_table_->GetCompatibleVersionNumber());
939 std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
940 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
941 EXPECT_TRUE(db.FindNamespacesForOrigin(kMockOrigin, &intercepts,
943 EXPECT_TRUE(intercepts.empty());
944 EXPECT_EQ(kNumNamespaces, static_cast<int>(fallbacks.size()));
946 for (int i = 0; i < kNumNamespaces; ++i) {
947 GURL expected_namespace_url(
948 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
949 GURL expected_target_url(
950 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
952 EXPECT_EQ(i, fallbacks[i].cache_id);
953 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[i].namespace_.type);
954 EXPECT_EQ(kMockOrigin, fallbacks[i].origin);
955 EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_.namespace_url);
956 EXPECT_EQ(expected_target_url, fallbacks[i].namespace_.target_url);
957 EXPECT_FALSE(fallbacks[i].namespace_.is_pattern);
960 #endif // !APPCACHE_USE_SIMPLE_CACHE
962 #if defined(APPCACHE_USE_SIMPLE_CACHE)
963 // There is no such upgrade path in this case.
965 TEST(AppCacheDatabaseTest, UpgradeSchema4to5) {
966 // Real file on disk for this test.
967 base::ScopedTempDir temp_dir;
968 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
969 const base::FilePath kDbFile = temp_dir.path().AppendASCII("upgrade4.db");
971 const GURL kMockOrigin("http://mockorigin/");
972 const char kNamespaceUrlFormat[] = "namespace%d";
973 const char kWhitelistUrlFormat[] = "whitelist%d";
974 const char kTargetUrlFormat[] = "target%d";
975 const int kNumNamespaces = 10;
976 const int kWhitelistCacheId = 1;
978 // Create a v4 schema based database containing some fallback records.
980 const int kVersion4 = 4;
981 const char kGroupsTable[] = "Groups";
982 const char kCachesTable[] = "Caches";
983 const char kEntriesTable[] = "Entries";
984 const char kNamespacesTable[] = "Namespaces";
985 const char kOnlineWhiteListsTable[] = "OnlineWhiteLists";
986 const char kDeletableResponseIdsTable[] = "DeletableResponseIds";
989 const char* table_name;
994 const char* index_name;
995 const char* table_name;
1000 const TableInfo kTables4[] = {
1002 "(group_id INTEGER PRIMARY KEY,"
1004 " manifest_url TEXT,"
1005 " creation_time INTEGER,"
1006 " last_access_time INTEGER)" },
1009 "(cache_id INTEGER PRIMARY KEY,"
1010 " group_id INTEGER,"
1011 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
1012 " update_time INTEGER,"
1013 " cache_size INTEGER)" }, // intentionally not normalized
1016 "(cache_id INTEGER,"
1019 " response_id INTEGER,"
1020 " response_size INTEGER)" },
1023 "(cache_id INTEGER,"
1024 " origin TEXT," // intentionally not normalized
1026 " namespace_url TEXT,"
1027 " target_url TEXT)" },
1029 { kOnlineWhiteListsTable,
1030 "(cache_id INTEGER,"
1031 " namespace_url TEXT)" },
1033 { kDeletableResponseIdsTable,
1034 "(response_id INTEGER NOT NULL)" },
1037 const IndexInfo kIndexes4[] = {
1038 { "GroupsOriginIndex",
1043 { "GroupsManifestIndex",
1048 { "CachesGroupIndex",
1053 { "EntriesCacheIndex",
1058 { "EntriesCacheAndUrlIndex",
1063 { "EntriesResponseIdIndex",
1068 { "NamespacesCacheIndex",
1073 { "NamespacesOriginIndex",
1078 { "NamespacesCacheAndUrlIndex",
1080 "(cache_id, namespace_url)",
1083 { "OnlineWhiteListCacheIndex",
1084 kOnlineWhiteListsTable,
1088 { "DeletableResponsesIdIndex",
1089 kDeletableResponseIdsTable,
1094 const int kTableCount4 = ARRAYSIZE_UNSAFE(kTables4);
1095 const int kIndexCount4 = ARRAYSIZE_UNSAFE(kIndexes4);
1097 sql::Connection connection;
1098 EXPECT_TRUE(connection.Open(kDbFile));
1100 sql::Transaction transaction(&connection);
1101 EXPECT_TRUE(transaction.Begin());
1103 sql::MetaTable meta_table;
1104 EXPECT_TRUE(meta_table.Init(&connection, kVersion4, kVersion4));
1106 for (int i = 0; i < kTableCount4; ++i) {
1107 std::string sql("CREATE TABLE ");
1108 sql += kTables4[i].table_name;
1109 sql += kTables4[i].columns;
1110 EXPECT_TRUE(connection.Execute(sql.c_str()));
1113 for (int i = 0; i < kIndexCount4; ++i) {
1115 if (kIndexes4[i].unique)
1116 sql += "CREATE UNIQUE INDEX ";
1118 sql += "CREATE INDEX ";
1119 sql += kIndexes4[i].index_name;
1121 sql += kIndexes4[i].table_name;
1122 sql += kIndexes4[i].columns;
1123 EXPECT_TRUE(connection.Execute(sql.c_str()));
1126 const char* kNamespacesSql =
1127 "INSERT INTO Namespaces"
1128 " (cache_id, origin, type, namespace_url, target_url)"
1129 " VALUES (?, ?, ?, ?, ?)";
1130 sql::Statement statement;
1131 statement.Assign(connection.GetUniqueStatement(kNamespacesSql));
1132 EXPECT_TRUE(statement.is_valid());
1133 for (int i = 0; i < kNumNamespaces; ++i) {
1135 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
1137 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
1138 statement.BindInt64(0, i);
1139 statement.BindString(1, kMockOrigin.spec().c_str());
1140 statement.BindInt(2, FALLBACK_NAMESPACE);
1141 statement.BindString(3, namespace_url.spec().c_str());
1142 statement.BindString(4, target_url.spec().c_str());
1143 ASSERT_TRUE(statement.Run());
1144 statement.Reset(true);
1147 const char* kWhitelistsSql =
1148 "INSERT INTO OnlineWhiteLists"
1149 " (cache_id, namespace_url)"
1151 statement.Assign(connection.GetUniqueStatement(kWhitelistsSql));
1152 EXPECT_TRUE(statement.is_valid());
1153 for (int i = 0; i < kNumNamespaces; ++i) {
1155 kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i)));
1156 statement.BindInt64(0, kWhitelistCacheId);
1157 statement.BindString(1, namespace_url.spec().c_str());
1158 ASSERT_TRUE(statement.Run());
1159 statement.Reset(true);
1162 EXPECT_TRUE(transaction.Commit());
1165 // Open that database and verify that it got upgraded to v5.
1166 AppCacheDatabase db(kDbFile);
1167 EXPECT_TRUE(db.LazyOpen(true));
1168 EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "is_pattern"));
1169 EXPECT_TRUE(db.db_->DoesColumnExist("OnlineWhiteLists", "is_pattern"));
1170 EXPECT_EQ(5, db.meta_table_->GetVersionNumber());
1171 EXPECT_EQ(5, db.meta_table_->GetCompatibleVersionNumber());
1173 std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
1174 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
1175 EXPECT_TRUE(db.FindNamespacesForOrigin(kMockOrigin, &intercepts,
1177 EXPECT_TRUE(intercepts.empty());
1178 EXPECT_EQ(kNumNamespaces, static_cast<int>(fallbacks.size()));
1180 std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
1181 EXPECT_TRUE(db.FindOnlineWhiteListForCache(kWhitelistCacheId, &whitelists));
1182 EXPECT_EQ(kNumNamespaces, static_cast<int>(whitelists.size()));
1184 for (int i = 0; i < kNumNamespaces; ++i) {
1185 GURL expected_namespace_url(
1186 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
1187 GURL expected_target_url(
1188 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
1189 GURL expected_whitelist_url(
1190 kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i)));
1192 EXPECT_EQ(i, fallbacks[i].cache_id);
1193 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[i].namespace_.type);
1194 EXPECT_EQ(kMockOrigin, fallbacks[i].origin);
1195 EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_.namespace_url);
1196 EXPECT_EQ(expected_target_url, fallbacks[i].namespace_.target_url);
1197 EXPECT_FALSE(fallbacks[i].namespace_.is_pattern);
1198 EXPECT_EQ(expected_whitelist_url, whitelists[i].namespace_url);
1199 EXPECT_FALSE(whitelists[i].is_pattern);
1202 #endif // !APPCACHE_USE_SIMPLE_CACHE
1204 } // namespace appcache