Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / webkit / appcache / appcache_database_unittest.cc
blob96627c71063820405685d991075ebac45d8dccfa
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.
5 #include "testing/gtest/include/gtest/gtest.h"
7 #include "base/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/stringprintf.h"
10 #include "sql/connection.h"
11 #include "sql/meta_table.h"
12 #include "sql/statement.h"
13 #include "sql/transaction.h"
14 #include "webkit/appcache/appcache_database.h"
15 #include "webkit/appcache/appcache_entry.h"
17 namespace {
19 const base::Time kZeroTime;
21 class TestErrorDelegate : public sql::ErrorDelegate {
22 public:
23 TestErrorDelegate() {}
24 virtual ~TestErrorDelegate() {}
26 virtual int OnError(int error,
27 sql::Connection* connection,
28 sql::Statement* stmt) OVERRIDE {
29 return error;
32 private:
33 DISALLOW_COPY_AND_ASSIGN(TestErrorDelegate);
36 } // namespace
38 namespace appcache {
40 class AppCacheDatabaseTest {};
42 TEST(AppCacheDatabaseTest, LazyOpen) {
43 // Use an empty file path to use an in-memory sqlite database.
44 const base::FilePath kEmptyPath;
45 AppCacheDatabase db(kEmptyPath);
47 EXPECT_FALSE(db.LazyOpen(false));
48 EXPECT_TRUE(db.LazyOpen(true));
50 int64 group_id, cache_id, response_id, deleteable_response_rowid;
51 group_id = cache_id = response_id = deleteable_response_rowid = 0;
52 EXPECT_TRUE(db.FindLastStorageIds(&group_id, &cache_id, &response_id,
53 &deleteable_response_rowid));
54 EXPECT_EQ(0, group_id);
55 EXPECT_EQ(0, cache_id);
56 EXPECT_EQ(0, response_id);
57 EXPECT_EQ(0, deleteable_response_rowid);
59 std::set<GURL> origins;
60 EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
61 EXPECT_TRUE(origins.empty());
64 TEST(AppCacheDatabaseTest, ReCreate) {
65 // Real files on disk for this test.
66 base::ScopedTempDir temp_dir;
67 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
68 const base::FilePath kDbFile = temp_dir.path().AppendASCII("appcache.db");
69 const base::FilePath kNestedDir = temp_dir.path().AppendASCII("nested");
70 const base::FilePath kOtherFile = kNestedDir.AppendASCII("other_file");
71 EXPECT_TRUE(file_util::CreateDirectory(kNestedDir));
72 EXPECT_EQ(3, file_util::WriteFile(kOtherFile, "foo", 3));
74 AppCacheDatabase db(kDbFile);
75 EXPECT_FALSE(db.LazyOpen(false));
76 EXPECT_TRUE(db.LazyOpen(true));
78 EXPECT_TRUE(file_util::PathExists(kDbFile));
79 EXPECT_TRUE(file_util::DirectoryExists(kNestedDir));
80 EXPECT_TRUE(file_util::PathExists(kOtherFile));
82 EXPECT_TRUE(db.DeleteExistingAndCreateNewDatabase());
84 EXPECT_TRUE(file_util::PathExists(kDbFile));
85 EXPECT_FALSE(file_util::DirectoryExists(kNestedDir));
86 EXPECT_FALSE(file_util::PathExists(kOtherFile));
89 TEST(AppCacheDatabaseTest, EntryRecords) {
90 const base::FilePath kEmptyPath;
91 AppCacheDatabase db(kEmptyPath);
92 EXPECT_TRUE(db.LazyOpen(true));
94 // Set an error delegate that will make all operations return false on error.
95 db.db_->set_error_delegate(new TestErrorDelegate());
97 AppCacheDatabase::EntryRecord entry;
99 entry.cache_id = 1;
100 entry.url = GURL("http://blah/1");
101 entry.flags = AppCacheEntry::MASTER;
102 entry.response_id = 1;
103 entry.response_size = 100;
104 EXPECT_TRUE(db.InsertEntry(&entry));
105 EXPECT_FALSE(db.InsertEntry(&entry));
107 entry.cache_id = 2;
108 entry.url = GURL("http://blah/2");
109 entry.flags = AppCacheEntry::EXPLICIT;
110 entry.response_id = 2;
111 entry.response_size = 200;
112 EXPECT_TRUE(db.InsertEntry(&entry));
114 entry.cache_id = 2;
115 entry.url = GURL("http://blah/3");
116 entry.flags = AppCacheEntry::MANIFEST;
117 entry.response_id = 3;
118 entry.response_size = 300;
119 EXPECT_TRUE(db.InsertEntry(&entry));
121 std::vector<AppCacheDatabase::EntryRecord> found;
123 EXPECT_TRUE(db.FindEntriesForCache(1, &found));
124 EXPECT_EQ(1U, found.size());
125 EXPECT_EQ(1, found[0].cache_id);
126 EXPECT_EQ(GURL("http://blah/1"), found[0].url);
127 EXPECT_EQ(AppCacheEntry::MASTER, found[0].flags);
128 EXPECT_EQ(1, found[0].response_id);
129 EXPECT_EQ(100, found[0].response_size);
130 found.clear();
132 EXPECT_TRUE(db.AddEntryFlags(GURL("http://blah/1"), 1,
133 AppCacheEntry::FOREIGN));
134 EXPECT_TRUE(db.FindEntriesForCache(1, &found));
135 EXPECT_EQ(1U, found.size());
136 EXPECT_EQ(AppCacheEntry::MASTER | AppCacheEntry::FOREIGN, found[0].flags);
137 found.clear();
139 EXPECT_TRUE(db.FindEntriesForCache(2, &found));
140 EXPECT_EQ(2U, found.size());
141 EXPECT_EQ(2, found[0].cache_id);
142 EXPECT_EQ(GURL("http://blah/2"), found[0].url);
143 EXPECT_EQ(AppCacheEntry::EXPLICIT, found[0].flags);
144 EXPECT_EQ(2, found[0].response_id);
145 EXPECT_EQ(200, found[0].response_size);
146 EXPECT_EQ(2, found[1].cache_id);
147 EXPECT_EQ(GURL("http://blah/3"), found[1].url);
148 EXPECT_EQ(AppCacheEntry::MANIFEST, found[1].flags);
149 EXPECT_EQ(3, found[1].response_id);
150 EXPECT_EQ(300, found[1].response_size);
151 found.clear();
153 EXPECT_TRUE(db.DeleteEntriesForCache(2));
154 EXPECT_TRUE(db.FindEntriesForCache(2, &found));
155 EXPECT_TRUE(found.empty());
156 found.clear();
158 EXPECT_TRUE(db.DeleteEntriesForCache(1));
159 EXPECT_FALSE(db.AddEntryFlags(GURL("http://blah/1"), 1,
160 AppCacheEntry::FOREIGN));
163 TEST(AppCacheDatabaseTest, CacheRecords) {
164 const base::FilePath kEmptyPath;
165 AppCacheDatabase db(kEmptyPath);
166 EXPECT_TRUE(db.LazyOpen(true));
168 db.db_->set_error_delegate(new TestErrorDelegate());
170 const AppCacheDatabase::CacheRecord kZeroRecord;
171 AppCacheDatabase::CacheRecord record;
172 EXPECT_FALSE(db.FindCache(1, &record));
174 record.cache_id = 1;
175 record.group_id = 1;
176 record.online_wildcard = true;
177 record.update_time = kZeroTime;
178 record.cache_size = 100;
179 EXPECT_TRUE(db.InsertCache(&record));
180 EXPECT_FALSE(db.InsertCache(&record));
182 record = kZeroRecord;
183 EXPECT_TRUE(db.FindCache(1, &record));
184 EXPECT_EQ(1, record.cache_id);
185 EXPECT_EQ(1, record.group_id);
186 EXPECT_TRUE(record.online_wildcard);
187 EXPECT_TRUE(kZeroTime == record.update_time);
188 EXPECT_EQ(100, record.cache_size);
190 record = kZeroRecord;
191 EXPECT_TRUE(db.FindCacheForGroup(1, &record));
192 EXPECT_EQ(1, record.cache_id);
193 EXPECT_EQ(1, record.group_id);
194 EXPECT_TRUE(record.online_wildcard);
195 EXPECT_TRUE(kZeroTime == record.update_time);
196 EXPECT_EQ(100, record.cache_size);
198 EXPECT_TRUE(db.DeleteCache(1));
199 EXPECT_FALSE(db.FindCache(1, &record));
200 EXPECT_FALSE(db.FindCacheForGroup(1, &record));
202 EXPECT_TRUE(db.DeleteCache(1));
205 TEST(AppCacheDatabaseTest, GroupRecords) {
206 const base::FilePath kEmptyPath;
207 AppCacheDatabase db(kEmptyPath);
208 EXPECT_TRUE(db.LazyOpen(true));
210 db.db_->set_error_delegate(new TestErrorDelegate());
212 const GURL kManifestUrl("http://blah/manifest");
213 const GURL kOrigin(kManifestUrl.GetOrigin());
214 const base::Time kLastAccessTime = base::Time::Now();
215 const base::Time kCreationTime =
216 kLastAccessTime - base::TimeDelta::FromDays(7);
218 const AppCacheDatabase::GroupRecord kZeroRecord;
219 AppCacheDatabase::GroupRecord record;
220 std::vector<AppCacheDatabase::GroupRecord> records;
222 // Behavior with an empty table
223 EXPECT_FALSE(db.FindGroup(1, &record));
224 EXPECT_FALSE(db.FindGroupForManifestUrl(kManifestUrl, &record));
225 EXPECT_TRUE(db.DeleteGroup(1));
226 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
227 EXPECT_TRUE(records.empty());
228 EXPECT_FALSE(db.FindGroupForCache(1, &record));
230 record.group_id = 1;
231 record.manifest_url = kManifestUrl;
232 record.origin = kOrigin;
233 record.last_access_time = kLastAccessTime;
234 record.creation_time = kCreationTime;
235 EXPECT_TRUE(db.InsertGroup(&record));
236 EXPECT_FALSE(db.InsertGroup(&record));
238 record.group_id = 2;
239 EXPECT_FALSE(db.InsertGroup(&record));
241 record = kZeroRecord;
242 EXPECT_TRUE(db.FindGroup(1, &record));
243 EXPECT_EQ(1, record.group_id);
244 EXPECT_EQ(kManifestUrl, record.manifest_url);
245 EXPECT_EQ(kOrigin, record.origin);
246 EXPECT_EQ(kCreationTime.ToInternalValue(),
247 record.creation_time.ToInternalValue());
248 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
249 record.last_access_time.ToInternalValue());
251 record = kZeroRecord;
252 EXPECT_TRUE(db.FindGroupForManifestUrl(kManifestUrl, &record));
253 EXPECT_EQ(1, record.group_id);
254 EXPECT_EQ(kManifestUrl, record.manifest_url);
255 EXPECT_EQ(kOrigin, record.origin);
256 EXPECT_EQ(kCreationTime.ToInternalValue(),
257 record.creation_time.ToInternalValue());
258 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
259 record.last_access_time.ToInternalValue());
261 record.group_id = 2;
262 record.manifest_url = kOrigin;
263 record.origin = kOrigin;
264 record.last_access_time = kLastAccessTime;
265 record.creation_time = kCreationTime;
266 EXPECT_TRUE(db.InsertGroup(&record));
268 record = kZeroRecord;
269 EXPECT_TRUE(db.FindGroupForManifestUrl(kOrigin, &record));
270 EXPECT_EQ(2, record.group_id);
271 EXPECT_EQ(kOrigin, record.manifest_url);
272 EXPECT_EQ(kOrigin, record.origin);
273 EXPECT_EQ(kCreationTime.ToInternalValue(),
274 record.creation_time.ToInternalValue());
275 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
276 record.last_access_time.ToInternalValue());
278 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
279 EXPECT_EQ(2U, records.size());
280 EXPECT_EQ(1, records[0].group_id);
281 EXPECT_EQ(kManifestUrl, records[0].manifest_url);
282 EXPECT_EQ(kOrigin, records[0].origin);
283 EXPECT_EQ(2, records[1].group_id);
284 EXPECT_EQ(kOrigin, records[1].manifest_url);
285 EXPECT_EQ(kOrigin, records[1].origin);
287 EXPECT_TRUE(db.DeleteGroup(1));
289 records.clear();
290 EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
291 EXPECT_EQ(1U, records.size());
292 EXPECT_EQ(2, records[0].group_id);
293 EXPECT_EQ(kOrigin, records[0].manifest_url);
294 EXPECT_EQ(kOrigin, records[0].origin);
295 EXPECT_EQ(kCreationTime.ToInternalValue(),
296 record.creation_time.ToInternalValue());
297 EXPECT_EQ(kLastAccessTime.ToInternalValue(),
298 record.last_access_time.ToInternalValue());
300 std::set<GURL> origins;
301 EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
302 EXPECT_EQ(1U, origins.size());
303 EXPECT_EQ(kOrigin, *(origins.begin()));
305 const GURL kManifest2("http://blah2/manifest");
306 const GURL kOrigin2(kManifest2.GetOrigin());
307 record.group_id = 1;
308 record.manifest_url = kManifest2;
309 record.origin = kOrigin2;
310 EXPECT_TRUE(db.InsertGroup(&record));
312 origins.clear();
313 EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
314 EXPECT_EQ(2U, origins.size());
315 EXPECT_TRUE(origins.end() != origins.find(kOrigin));
316 EXPECT_TRUE(origins.end() != origins.find(kOrigin2));
318 AppCacheDatabase::CacheRecord cache_record;
319 cache_record.cache_id = 1;
320 cache_record.group_id = 1;
321 cache_record.online_wildcard = true;
322 cache_record.update_time = kZeroTime;
323 EXPECT_TRUE(db.InsertCache(&cache_record));
325 record = kZeroRecord;
326 EXPECT_TRUE(db.FindGroupForCache(1, &record));
327 EXPECT_EQ(1, record.group_id);
328 EXPECT_EQ(kManifest2, record.manifest_url);
329 EXPECT_EQ(kOrigin2, record.origin);
332 TEST(AppCacheDatabaseTest, NamespaceRecords) {
333 const base::FilePath kEmptyPath;
334 AppCacheDatabase db(kEmptyPath);
335 EXPECT_TRUE(db.LazyOpen(true));
337 db.db_->set_error_delegate(new TestErrorDelegate());
339 const GURL kFooNameSpace1("http://foo/namespace1");
340 const GURL kFooNameSpace2("http://foo/namespace2");
341 const GURL kFooFallbackEntry("http://foo/entry");
342 const GURL kFooOrigin(kFooNameSpace1.GetOrigin());
343 const GURL kBarNameSpace1("http://bar/namespace1");
344 const GURL kBarNameSpace2("http://bar/namespace2");
345 const GURL kBarFallbackEntry("http://bar/entry");
346 const GURL kBarOrigin(kBarNameSpace1.GetOrigin());
348 const AppCacheDatabase::NamespaceRecord kZeroRecord;
349 AppCacheDatabase::NamespaceRecord record;
350 std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
351 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
353 // Behavior with an empty table
354 EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks));
355 EXPECT_TRUE(fallbacks.empty());
356 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
357 EXPECT_TRUE(fallbacks.empty());
358 EXPECT_TRUE(db.DeleteNamespacesForCache(1));
360 // Two records for two differenent caches in the Foo origin.
361 record.cache_id = 1;
362 record.origin = kFooOrigin;
363 record.namespace_.namespace_url = kFooNameSpace1;
364 record.namespace_.target_url = kFooFallbackEntry;
365 EXPECT_TRUE(db.InsertNamespace(&record));
366 EXPECT_FALSE(db.InsertNamespace(&record));
368 record.cache_id = 2;
369 record.origin = kFooOrigin;
370 record.namespace_.namespace_url = kFooNameSpace2;
371 record.namespace_.target_url = kFooFallbackEntry;
372 EXPECT_TRUE(db.InsertNamespace(&record));
374 fallbacks.clear();
375 EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks));
376 EXPECT_EQ(1U, fallbacks.size());
377 EXPECT_EQ(1, fallbacks[0].cache_id);
378 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
379 EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url);
380 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
381 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
383 fallbacks.clear();
384 EXPECT_TRUE(db.FindNamespacesForCache(2, &intercepts, &fallbacks));
385 EXPECT_EQ(1U, fallbacks.size());
386 EXPECT_EQ(2, fallbacks[0].cache_id);
387 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
388 EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url);
389 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
390 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
392 fallbacks.clear();
393 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
394 EXPECT_EQ(2U, fallbacks.size());
395 EXPECT_EQ(1, fallbacks[0].cache_id);
396 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
397 EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url);
398 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
399 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
400 EXPECT_EQ(2, fallbacks[1].cache_id);
401 EXPECT_EQ(kFooOrigin, fallbacks[1].origin);
402 EXPECT_EQ(kFooNameSpace2, fallbacks[1].namespace_.namespace_url);
403 EXPECT_EQ(kFooFallbackEntry, fallbacks[1].namespace_.target_url);
404 EXPECT_FALSE(fallbacks[1].namespace_.is_pattern);
406 EXPECT_TRUE(db.DeleteNamespacesForCache(1));
407 fallbacks.clear();
408 EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
409 EXPECT_EQ(1U, fallbacks.size());
410 EXPECT_EQ(2, fallbacks[0].cache_id);
411 EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
412 EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url);
413 EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
414 EXPECT_FALSE(fallbacks[0].namespace_.is_pattern);
416 // Two more records for the same cache in the Bar origin.
417 record.cache_id = 3;
418 record.origin = kBarOrigin;
419 record.namespace_.namespace_url = kBarNameSpace1;
420 record.namespace_.target_url = kBarFallbackEntry;
421 record.namespace_.is_pattern = true;
422 EXPECT_TRUE(db.InsertNamespace(&record));
424 record.cache_id = 3;
425 record.origin = kBarOrigin;
426 record.namespace_.namespace_url = kBarNameSpace2;
427 record.namespace_.target_url = kBarFallbackEntry;
428 record.namespace_.is_pattern = true;
429 EXPECT_TRUE(db.InsertNamespace(&record));
431 fallbacks.clear();
432 EXPECT_TRUE(db.FindNamespacesForCache(3, &intercepts, &fallbacks));
433 EXPECT_EQ(2U, fallbacks.size());
434 EXPECT_TRUE(fallbacks[0].namespace_.is_pattern);
435 EXPECT_TRUE(fallbacks[1].namespace_.is_pattern);
437 fallbacks.clear();
438 EXPECT_TRUE(db.FindNamespacesForOrigin(kBarOrigin, &intercepts, &fallbacks));
439 EXPECT_EQ(2U, fallbacks.size());
440 EXPECT_TRUE(fallbacks[0].namespace_.is_pattern);
441 EXPECT_TRUE(fallbacks[1].namespace_.is_pattern);
444 TEST(AppCacheDatabaseTest, OnlineWhiteListRecords) {
445 const base::FilePath kEmptyPath;
446 AppCacheDatabase db(kEmptyPath);
447 EXPECT_TRUE(db.LazyOpen(true));
449 db.db_->set_error_delegate(new TestErrorDelegate());
451 const GURL kFooNameSpace1("http://foo/namespace1");
452 const GURL kFooNameSpace2("http://foo/namespace2");
453 const GURL kBarNameSpace1("http://bar/namespace1");
455 const AppCacheDatabase::OnlineWhiteListRecord kZeroRecord;
456 AppCacheDatabase::OnlineWhiteListRecord record;
457 std::vector<AppCacheDatabase::OnlineWhiteListRecord> records;
459 // Behavior with an empty table
460 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records));
461 EXPECT_TRUE(records.empty());
462 EXPECT_TRUE(db.DeleteOnlineWhiteListForCache(1));
464 record.cache_id = 1;
465 record.namespace_url = kFooNameSpace1;
466 EXPECT_TRUE(db.InsertOnlineWhiteList(&record));
467 record.namespace_url = kFooNameSpace2;
468 record.is_pattern = true;
469 EXPECT_TRUE(db.InsertOnlineWhiteList(&record));
470 records.clear();
471 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records));
472 EXPECT_EQ(2U, records.size());
473 EXPECT_EQ(1, records[0].cache_id);
474 EXPECT_EQ(kFooNameSpace1, records[0].namespace_url);
475 EXPECT_FALSE(records[0].is_pattern);
476 EXPECT_EQ(1, records[1].cache_id);
477 EXPECT_EQ(kFooNameSpace2, records[1].namespace_url);
478 EXPECT_TRUE(records[1].is_pattern);
480 record.cache_id = 2;
481 record.namespace_url = kBarNameSpace1;
482 EXPECT_TRUE(db.InsertOnlineWhiteList(&record));
483 records.clear();
484 EXPECT_TRUE(db.FindOnlineWhiteListForCache(2, &records));
485 EXPECT_EQ(1U, records.size());
487 EXPECT_TRUE(db.DeleteOnlineWhiteListForCache(1));
488 records.clear();
489 EXPECT_TRUE(db.FindOnlineWhiteListForCache(1, &records));
490 EXPECT_TRUE(records.empty());
493 TEST(AppCacheDatabaseTest, DeletableResponseIds) {
494 const base::FilePath kEmptyPath;
495 AppCacheDatabase db(kEmptyPath);
496 EXPECT_TRUE(db.LazyOpen(true));
498 db.db_->set_error_delegate(new TestErrorDelegate());
500 std::vector<int64> ids;
502 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
503 EXPECT_TRUE(ids.empty());
504 ids.push_back(0);
505 EXPECT_TRUE(db.DeleteDeletableResponseIds(ids));
506 EXPECT_TRUE(db.InsertDeletableResponseIds(ids));
508 ids.clear();
509 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
510 EXPECT_EQ(1U, ids.size());
511 EXPECT_EQ(0, ids[0]);
513 int64 unused, deleteable_response_rowid;
514 unused = deleteable_response_rowid = 0;
515 EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused,
516 &deleteable_response_rowid));
517 EXPECT_EQ(1, deleteable_response_rowid);
520 // Expected to fail due to the duplicate id, 0 is already in the table.
521 ids.clear();
522 ids.push_back(0);
523 ids.push_back(1);
524 EXPECT_FALSE(db.InsertDeletableResponseIds(ids));
526 ids.clear();
527 for (int i = 1; i < 10; ++i)
528 ids.push_back(i);
529 EXPECT_TRUE(db.InsertDeletableResponseIds(ids));
530 EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused,
531 &deleteable_response_rowid));
532 EXPECT_EQ(10, deleteable_response_rowid);
534 ids.clear();
535 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
536 EXPECT_EQ(10U, ids.size());
537 for (int i = 0; i < 10; ++i)
538 EXPECT_EQ(i, ids[i]);
540 // Ensure the limit is respected.
541 ids.clear();
542 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 5));
543 EXPECT_EQ(5U, ids.size());
544 for (int i = 0; i < static_cast<int>(ids.size()); ++i)
545 EXPECT_EQ(i, ids[i]);
547 // Ensure the max_rowid is respected (the first rowid is 1).
548 ids.clear();
549 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, 5, 100));
550 EXPECT_EQ(5U, ids.size());
551 for (int i = 0; i < static_cast<int>(ids.size()); ++i)
552 EXPECT_EQ(i, ids[i]);
554 // Ensure that we can delete from the table.
555 EXPECT_TRUE(db.DeleteDeletableResponseIds(ids));
556 ids.clear();
557 EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
558 EXPECT_EQ(5U, ids.size());
559 for (int i = 0; i < static_cast<int>(ids.size()); ++i)
560 EXPECT_EQ(i + 5, ids[i]);
563 TEST(AppCacheDatabaseTest, OriginUsage) {
564 const GURL kManifestUrl("http://blah/manifest");
565 const GURL kManifestUrl2("http://blah/manifest2");
566 const GURL kOrigin(kManifestUrl.GetOrigin());
567 const GURL kOtherOriginManifestUrl("http://other/manifest");
568 const GURL kOtherOrigin(kOtherOriginManifestUrl.GetOrigin());
570 const base::FilePath kEmptyPath;
571 AppCacheDatabase db(kEmptyPath);
572 EXPECT_TRUE(db.LazyOpen(true));
574 db.db_->set_error_delegate(new TestErrorDelegate());
576 std::vector<AppCacheDatabase::CacheRecord> cache_records;
577 EXPECT_EQ(0, db.GetOriginUsage(kOrigin));
578 EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records));
579 EXPECT_TRUE(cache_records.empty());
581 AppCacheDatabase::GroupRecord group_record;
582 group_record.group_id = 1;
583 group_record.manifest_url = kManifestUrl;
584 group_record.origin = kOrigin;
585 EXPECT_TRUE(db.InsertGroup(&group_record));
586 AppCacheDatabase::CacheRecord cache_record;
587 cache_record.cache_id = 1;
588 cache_record.group_id = 1;
589 cache_record.online_wildcard = true;
590 cache_record.update_time = kZeroTime;
591 cache_record.cache_size = 100;
592 EXPECT_TRUE(db.InsertCache(&cache_record));
594 EXPECT_EQ(100, db.GetOriginUsage(kOrigin));
596 group_record.group_id = 2;
597 group_record.manifest_url = kManifestUrl2;
598 group_record.origin = kOrigin;
599 EXPECT_TRUE(db.InsertGroup(&group_record));
600 cache_record.cache_id = 2;
601 cache_record.group_id = 2;
602 cache_record.online_wildcard = true;
603 cache_record.update_time = kZeroTime;
604 cache_record.cache_size = 1000;
605 EXPECT_TRUE(db.InsertCache(&cache_record));
607 EXPECT_EQ(1100, db.GetOriginUsage(kOrigin));
609 group_record.group_id = 3;
610 group_record.manifest_url = kOtherOriginManifestUrl;
611 group_record.origin = kOtherOrigin;
612 EXPECT_TRUE(db.InsertGroup(&group_record));
613 cache_record.cache_id = 3;
614 cache_record.group_id = 3;
615 cache_record.online_wildcard = true;
616 cache_record.update_time = kZeroTime;
617 cache_record.cache_size = 5000;
618 EXPECT_TRUE(db.InsertCache(&cache_record));
620 EXPECT_EQ(5000, db.GetOriginUsage(kOtherOrigin));
622 EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records));
623 EXPECT_EQ(2U, cache_records.size());
624 cache_records.clear();
625 EXPECT_TRUE(db.FindCachesForOrigin(kOtherOrigin, &cache_records));
626 EXPECT_EQ(1U, cache_records.size());
628 std::map<GURL, int64> usage_map;
629 EXPECT_TRUE(db.GetAllOriginUsage(&usage_map));
630 EXPECT_EQ(2U, usage_map.size());
631 EXPECT_EQ(1100, usage_map[kOrigin]);
632 EXPECT_EQ(5000, usage_map[kOtherOrigin]);
635 TEST(AppCacheDatabaseTest, UpgradeSchema3to5) {
636 // Real file on disk for this test.
637 base::ScopedTempDir temp_dir;
638 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
639 const base::FilePath kDbFile = temp_dir.path().AppendASCII("upgrade3.db");
641 const GURL kMockOrigin("http://mockorigin/");
642 const char kNamespaceUrlFormat[] = "namespace%d";
643 const char kTargetUrlFormat[] = "target%d";
644 const int kNumNamespaces = 10;
646 // Create a v3 schema based database containing some fallback records.
648 const int kVersion3 = 3;
649 const char kGroupsTable[] = "Groups";
650 const char kCachesTable[] = "Caches";
651 const char kEntriesTable[] = "Entries";
652 const char kFallbackNameSpacesTable[] = "FallbackNameSpaces";
653 const char kOnlineWhiteListsTable[] = "OnlineWhiteLists";
654 const char kDeletableResponseIdsTable[] = "DeletableResponseIds";
656 const struct {
657 const char* table_name;
658 const char* columns;
659 } kTables3[] = {
660 { kGroupsTable,
661 "(group_id INTEGER PRIMARY KEY,"
662 " origin TEXT,"
663 " manifest_url TEXT,"
664 " creation_time INTEGER,"
665 " last_access_time INTEGER)" },
667 { kCachesTable,
668 "(cache_id INTEGER PRIMARY KEY,"
669 " group_id INTEGER,"
670 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
671 " update_time INTEGER,"
672 " cache_size INTEGER)" }, // intentionally not normalized
674 { kEntriesTable,
675 "(cache_id INTEGER,"
676 " url TEXT,"
677 " flags INTEGER,"
678 " response_id INTEGER,"
679 " response_size INTEGER)" },
681 { kFallbackNameSpacesTable,
682 "(cache_id INTEGER,"
683 " origin TEXT," // intentionally not normalized
684 " namespace_url TEXT,"
685 " fallback_entry_url TEXT)" },
687 { kOnlineWhiteListsTable,
688 "(cache_id INTEGER,"
689 " namespace_url TEXT)" },
691 { kDeletableResponseIdsTable,
692 "(response_id INTEGER NOT NULL)" },
695 const struct {
696 const char* index_name;
697 const char* table_name;
698 const char* columns;
699 bool unique;
700 } kIndexes3[] = {
701 { "GroupsOriginIndex",
702 kGroupsTable,
703 "(origin)",
704 false },
706 { "GroupsManifestIndex",
707 kGroupsTable,
708 "(manifest_url)",
709 true },
711 { "CachesGroupIndex",
712 kCachesTable,
713 "(group_id)",
714 false },
716 { "EntriesCacheIndex",
717 kEntriesTable,
718 "(cache_id)",
719 false },
721 { "EntriesCacheAndUrlIndex",
722 kEntriesTable,
723 "(cache_id, url)",
724 true },
726 { "EntriesResponseIdIndex",
727 kEntriesTable,
728 "(response_id)",
729 true },
731 { "FallbackNameSpacesCacheIndex",
732 kFallbackNameSpacesTable,
733 "(cache_id)",
734 false },
736 { "FallbackNameSpacesOriginIndex",
737 kFallbackNameSpacesTable,
738 "(origin)",
739 false },
741 { "FallbackNameSpacesCacheAndUrlIndex",
742 kFallbackNameSpacesTable,
743 "(cache_id, namespace_url)",
744 true },
746 { "OnlineWhiteListCacheIndex",
747 kOnlineWhiteListsTable,
748 "(cache_id)",
749 false },
751 { "DeletableResponsesIdIndex",
752 kDeletableResponseIdsTable,
753 "(response_id)",
754 true },
757 const int kTableCount3 = ARRAYSIZE_UNSAFE(kTables3);
758 const int kIndexCount3 = ARRAYSIZE_UNSAFE(kIndexes3);
760 sql::Connection connection;
761 EXPECT_TRUE(connection.Open(kDbFile));
763 sql::Transaction transaction(&connection);
764 EXPECT_TRUE(transaction.Begin());
766 sql::MetaTable meta_table;
767 EXPECT_TRUE(meta_table.Init(&connection, kVersion3, kVersion3));
769 for (int i = 0; i < kTableCount3; ++i) {
770 std::string sql("CREATE TABLE ");
771 sql += kTables3[i].table_name;
772 sql += kTables3[i].columns;
773 EXPECT_TRUE(connection.Execute(sql.c_str()));
776 for (int i = 0; i < kIndexCount3; ++i) {
777 std::string sql;
778 if (kIndexes3[i].unique)
779 sql += "CREATE UNIQUE INDEX ";
780 else
781 sql += "CREATE INDEX ";
782 sql += kIndexes3[i].index_name;
783 sql += " ON ";
784 sql += kIndexes3[i].table_name;
785 sql += kIndexes3[i].columns;
786 EXPECT_TRUE(connection.Execute(sql.c_str()));
789 const char* kSql =
790 "INSERT INTO FallbackNameSpaces"
791 " (cache_id, origin, namespace_url, fallback_entry_url)"
792 " VALUES (?, ?, ?, ?)";
794 sql::Statement statement;
795 statement.Assign(connection.GetUniqueStatement(kSql));
796 EXPECT_TRUE(statement.is_valid());
797 for (int i = 0; i < kNumNamespaces; ++i) {
798 GURL namespace_url(
799 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
800 GURL target_url(
801 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
802 statement.BindInt64(0, i);
803 statement.BindString(1, kMockOrigin.spec().c_str());
804 statement.BindString(2, namespace_url.spec().c_str());
805 statement.BindString(3, target_url.spec().c_str());
806 ASSERT_TRUE(statement.Run());
807 statement.Reset(true);
810 EXPECT_TRUE(transaction.Commit());
813 // Open that database and verify that it got updated.
814 AppCacheDatabase db(kDbFile);
815 EXPECT_TRUE(db.LazyOpen(true));
817 EXPECT_FALSE(db.db_->DoesTableExist("FallbackNameSpaces"));
818 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNamesSpacesCacheIndex"));
819 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNameSpacesOriginIndex"));
820 EXPECT_FALSE(db.db_->DoesIndexExist("FallbackNameSpacesCacheAndUrlIndex"));
822 EXPECT_TRUE(db.db_->DoesTableExist("Namespaces"));
823 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesCacheIndex"));
824 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesOriginIndex"));
825 EXPECT_TRUE(db.db_->DoesIndexExist("NamespacesCacheAndUrlIndex"));
826 EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "is_pattern"));
827 EXPECT_TRUE(db.db_->DoesColumnExist("OnlineWhiteLists", "is_pattern"));
829 EXPECT_EQ(5, db.meta_table_->GetVersionNumber());
830 EXPECT_EQ(5, db.meta_table_->GetCompatibleVersionNumber());
832 std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
833 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
834 EXPECT_TRUE(db.FindNamespacesForOrigin(kMockOrigin, &intercepts,
835 &fallbacks));
836 EXPECT_TRUE(intercepts.empty());
837 EXPECT_EQ(kNumNamespaces, static_cast<int>(fallbacks.size()));
839 for (int i = 0; i < kNumNamespaces; ++i) {
840 GURL expected_namespace_url(
841 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
842 GURL expected_target_url(
843 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
845 EXPECT_EQ(i, fallbacks[i].cache_id);
846 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[i].namespace_.type);
847 EXPECT_EQ(kMockOrigin, fallbacks[i].origin);
848 EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_.namespace_url);
849 EXPECT_EQ(expected_target_url, fallbacks[i].namespace_.target_url);
850 EXPECT_FALSE(fallbacks[i].namespace_.is_pattern);
854 TEST(AppCacheDatabaseTest, UpgradeSchema4to5) {
855 // Real file on disk for this test.
856 base::ScopedTempDir temp_dir;
857 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
858 const base::FilePath kDbFile = temp_dir.path().AppendASCII("upgrade4.db");
860 const GURL kMockOrigin("http://mockorigin/");
861 const char kNamespaceUrlFormat[] = "namespace%d";
862 const char kWhitelistUrlFormat[] = "whitelist%d";
863 const char kTargetUrlFormat[] = "target%d";
864 const int kNumNamespaces = 10;
865 const int kWhitelistCacheId = 1;
867 // Create a v4 schema based database containing some fallback records.
869 const int kVersion4 = 4;
870 const char kGroupsTable[] = "Groups";
871 const char kCachesTable[] = "Caches";
872 const char kEntriesTable[] = "Entries";
873 const char kNamespacesTable[] = "Namespaces";
874 const char kOnlineWhiteListsTable[] = "OnlineWhiteLists";
875 const char kDeletableResponseIdsTable[] = "DeletableResponseIds";
877 struct TableInfo {
878 const char* table_name;
879 const char* columns;
882 struct IndexInfo {
883 const char* index_name;
884 const char* table_name;
885 const char* columns;
886 bool unique;
889 const TableInfo kTables4[] = {
890 { kGroupsTable,
891 "(group_id INTEGER PRIMARY KEY,"
892 " origin TEXT,"
893 " manifest_url TEXT,"
894 " creation_time INTEGER,"
895 " last_access_time INTEGER)" },
897 { kCachesTable,
898 "(cache_id INTEGER PRIMARY KEY,"
899 " group_id INTEGER,"
900 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
901 " update_time INTEGER,"
902 " cache_size INTEGER)" }, // intentionally not normalized
904 { kEntriesTable,
905 "(cache_id INTEGER,"
906 " url TEXT,"
907 " flags INTEGER,"
908 " response_id INTEGER,"
909 " response_size INTEGER)" },
911 { kNamespacesTable,
912 "(cache_id INTEGER,"
913 " origin TEXT," // intentionally not normalized
914 " type INTEGER,"
915 " namespace_url TEXT,"
916 " target_url TEXT)" },
918 { kOnlineWhiteListsTable,
919 "(cache_id INTEGER,"
920 " namespace_url TEXT)" },
922 { kDeletableResponseIdsTable,
923 "(response_id INTEGER NOT NULL)" },
926 const IndexInfo kIndexes4[] = {
927 { "GroupsOriginIndex",
928 kGroupsTable,
929 "(origin)",
930 false },
932 { "GroupsManifestIndex",
933 kGroupsTable,
934 "(manifest_url)",
935 true },
937 { "CachesGroupIndex",
938 kCachesTable,
939 "(group_id)",
940 false },
942 { "EntriesCacheIndex",
943 kEntriesTable,
944 "(cache_id)",
945 false },
947 { "EntriesCacheAndUrlIndex",
948 kEntriesTable,
949 "(cache_id, url)",
950 true },
952 { "EntriesResponseIdIndex",
953 kEntriesTable,
954 "(response_id)",
955 true },
957 { "NamespacesCacheIndex",
958 kNamespacesTable,
959 "(cache_id)",
960 false },
962 { "NamespacesOriginIndex",
963 kNamespacesTable,
964 "(origin)",
965 false },
967 { "NamespacesCacheAndUrlIndex",
968 kNamespacesTable,
969 "(cache_id, namespace_url)",
970 true },
972 { "OnlineWhiteListCacheIndex",
973 kOnlineWhiteListsTable,
974 "(cache_id)",
975 false },
977 { "DeletableResponsesIdIndex",
978 kDeletableResponseIdsTable,
979 "(response_id)",
980 true },
983 const int kTableCount4 = ARRAYSIZE_UNSAFE(kTables4);
984 const int kIndexCount4 = ARRAYSIZE_UNSAFE(kIndexes4);
986 sql::Connection connection;
987 EXPECT_TRUE(connection.Open(kDbFile));
989 sql::Transaction transaction(&connection);
990 EXPECT_TRUE(transaction.Begin());
992 sql::MetaTable meta_table;
993 EXPECT_TRUE(meta_table.Init(&connection, kVersion4, kVersion4));
995 for (int i = 0; i < kTableCount4; ++i) {
996 std::string sql("CREATE TABLE ");
997 sql += kTables4[i].table_name;
998 sql += kTables4[i].columns;
999 EXPECT_TRUE(connection.Execute(sql.c_str()));
1002 for (int i = 0; i < kIndexCount4; ++i) {
1003 std::string sql;
1004 if (kIndexes4[i].unique)
1005 sql += "CREATE UNIQUE INDEX ";
1006 else
1007 sql += "CREATE INDEX ";
1008 sql += kIndexes4[i].index_name;
1009 sql += " ON ";
1010 sql += kIndexes4[i].table_name;
1011 sql += kIndexes4[i].columns;
1012 EXPECT_TRUE(connection.Execute(sql.c_str()));
1015 const char* kNamespacesSql =
1016 "INSERT INTO Namespaces"
1017 " (cache_id, origin, type, namespace_url, target_url)"
1018 " VALUES (?, ?, ?, ?, ?)";
1019 sql::Statement statement;
1020 statement.Assign(connection.GetUniqueStatement(kNamespacesSql));
1021 EXPECT_TRUE(statement.is_valid());
1022 for (int i = 0; i < kNumNamespaces; ++i) {
1023 GURL namespace_url(
1024 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
1025 GURL target_url(
1026 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
1027 statement.BindInt64(0, i);
1028 statement.BindString(1, kMockOrigin.spec().c_str());
1029 statement.BindInt(2, FALLBACK_NAMESPACE);
1030 statement.BindString(3, namespace_url.spec().c_str());
1031 statement.BindString(4, target_url.spec().c_str());
1032 ASSERT_TRUE(statement.Run());
1033 statement.Reset(true);
1036 const char* kWhitelistsSql =
1037 "INSERT INTO OnlineWhiteLists"
1038 " (cache_id, namespace_url)"
1039 " VALUES (?, ?)";
1040 statement.Assign(connection.GetUniqueStatement(kWhitelistsSql));
1041 EXPECT_TRUE(statement.is_valid());
1042 for (int i = 0; i < kNumNamespaces; ++i) {
1043 GURL namespace_url(
1044 kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i)));
1045 statement.BindInt64(0, kWhitelistCacheId);
1046 statement.BindString(1, namespace_url.spec().c_str());
1047 ASSERT_TRUE(statement.Run());
1048 statement.Reset(true);
1051 EXPECT_TRUE(transaction.Commit());
1054 // Open that database and verify that it got upgraded to v5.
1055 AppCacheDatabase db(kDbFile);
1056 EXPECT_TRUE(db.LazyOpen(true));
1057 EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "is_pattern"));
1058 EXPECT_TRUE(db.db_->DoesColumnExist("OnlineWhiteLists", "is_pattern"));
1059 EXPECT_EQ(5, db.meta_table_->GetVersionNumber());
1060 EXPECT_EQ(5, db.meta_table_->GetCompatibleVersionNumber());
1062 std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
1063 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
1064 EXPECT_TRUE(db.FindNamespacesForOrigin(kMockOrigin, &intercepts,
1065 &fallbacks));
1066 EXPECT_TRUE(intercepts.empty());
1067 EXPECT_EQ(kNumNamespaces, static_cast<int>(fallbacks.size()));
1069 std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
1070 EXPECT_TRUE(db.FindOnlineWhiteListForCache(kWhitelistCacheId, &whitelists));
1071 EXPECT_EQ(kNumNamespaces, static_cast<int>(whitelists.size()));
1073 for (int i = 0; i < kNumNamespaces; ++i) {
1074 GURL expected_namespace_url(
1075 kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
1076 GURL expected_target_url(
1077 kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
1078 GURL expected_whitelist_url(
1079 kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i)));
1081 EXPECT_EQ(i, fallbacks[i].cache_id);
1082 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[i].namespace_.type);
1083 EXPECT_EQ(kMockOrigin, fallbacks[i].origin);
1084 EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_.namespace_url);
1085 EXPECT_EQ(expected_target_url, fallbacks[i].namespace_.target_url);
1086 EXPECT_FALSE(fallbacks[i].namespace_.is_pattern);
1087 EXPECT_EQ(expected_whitelist_url, whitelists[i].namespace_url);
1088 EXPECT_FALSE(whitelists[i].is_pattern);
1092 } // namespace appcache