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"
19 const base::Time kZeroTime
;
21 class TestErrorDelegate
: public sql::ErrorDelegate
{
23 TestErrorDelegate() {}
24 virtual ~TestErrorDelegate() {}
26 virtual int OnError(int error
,
27 sql::Connection
* connection
,
28 sql::Statement
* stmt
) OVERRIDE
{
33 DISALLOW_COPY_AND_ASSIGN(TestErrorDelegate
);
40 class AppCacheDatabaseTest
{};
42 TEST(AppCacheDatabaseTest
, LazyOpen
) {
43 // Use an empty file path to use an in-memory sqlite database.
44 const 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 FilePath kDbFile
= temp_dir
.path().AppendASCII("appcache.db");
69 const FilePath kNestedDir
= temp_dir
.path().AppendASCII("nested");
70 const 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 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
;
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
));
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
));
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
);
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
);
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
);
153 EXPECT_TRUE(db
.DeleteEntriesForCache(2));
154 EXPECT_TRUE(db
.FindEntriesForCache(2, &found
));
155 EXPECT_TRUE(found
.empty());
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 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
));
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 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
));
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
));
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());
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));
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());
308 record
.manifest_url
= kManifest2
;
309 record
.origin
= kOrigin2
;
310 EXPECT_TRUE(db
.InsertGroup(&record
));
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 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.
362 record
.origin
= kFooOrigin
;
363 record
.namespace_url
= kFooNameSpace1
;
364 record
.target_url
= kFooFallbackEntry
;
365 EXPECT_TRUE(db
.InsertNamespace(&record
));
366 EXPECT_FALSE(db
.InsertNamespace(&record
));
369 record
.origin
= kFooOrigin
;
370 record
.namespace_url
= kFooNameSpace2
;
371 record
.target_url
= kFooFallbackEntry
;
372 EXPECT_TRUE(db
.InsertNamespace(&record
));
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_url
);
380 EXPECT_EQ(kFooFallbackEntry
, fallbacks
[0].target_url
);
383 EXPECT_TRUE(db
.FindNamespacesForCache(2, &intercepts
, &fallbacks
));
384 EXPECT_EQ(1U, fallbacks
.size());
385 EXPECT_EQ(2, fallbacks
[0].cache_id
);
386 EXPECT_EQ(kFooOrigin
, fallbacks
[0].origin
);
387 EXPECT_EQ(kFooNameSpace2
, fallbacks
[0].namespace_url
);
388 EXPECT_EQ(kFooFallbackEntry
, fallbacks
[0].target_url
);
391 EXPECT_TRUE(db
.FindNamespacesForOrigin(kFooOrigin
, &intercepts
, &fallbacks
));
392 EXPECT_EQ(2U, fallbacks
.size());
393 EXPECT_EQ(1, fallbacks
[0].cache_id
);
394 EXPECT_EQ(kFooOrigin
, fallbacks
[0].origin
);
395 EXPECT_EQ(kFooNameSpace1
, fallbacks
[0].namespace_url
);
396 EXPECT_EQ(kFooFallbackEntry
, fallbacks
[0].target_url
);
397 EXPECT_EQ(2, fallbacks
[1].cache_id
);
398 EXPECT_EQ(kFooOrigin
, fallbacks
[1].origin
);
399 EXPECT_EQ(kFooNameSpace2
, fallbacks
[1].namespace_url
);
400 EXPECT_EQ(kFooFallbackEntry
, fallbacks
[1].target_url
);
402 EXPECT_TRUE(db
.DeleteNamespacesForCache(1));
404 EXPECT_TRUE(db
.FindNamespacesForOrigin(kFooOrigin
, &intercepts
, &fallbacks
));
405 EXPECT_EQ(1U, fallbacks
.size());
406 EXPECT_EQ(2, fallbacks
[0].cache_id
);
407 EXPECT_EQ(kFooOrigin
, fallbacks
[0].origin
);
408 EXPECT_EQ(kFooNameSpace2
, fallbacks
[0].namespace_url
);
409 EXPECT_EQ(kFooFallbackEntry
, fallbacks
[0].target_url
);
411 // Two more records for the same cache in the Bar origin.
413 record
.origin
= kBarOrigin
;
414 record
.namespace_url
= kBarNameSpace1
;
415 record
.target_url
= kBarFallbackEntry
;
416 EXPECT_TRUE(db
.InsertNamespace(&record
));
419 record
.origin
= kBarOrigin
;
420 record
.namespace_url
= kBarNameSpace2
;
421 record
.target_url
= kBarFallbackEntry
;
422 EXPECT_TRUE(db
.InsertNamespace(&record
));
425 EXPECT_TRUE(db
.FindNamespacesForCache(3, &intercepts
, &fallbacks
));
426 EXPECT_EQ(2U, fallbacks
.size());
428 EXPECT_TRUE(db
.FindNamespacesForOrigin(kBarOrigin
, &intercepts
, &fallbacks
));
429 EXPECT_EQ(2U, fallbacks
.size());
432 TEST(AppCacheDatabaseTest
, OnlineWhiteListRecords
) {
433 const FilePath kEmptyPath
;
434 AppCacheDatabase
db(kEmptyPath
);
435 EXPECT_TRUE(db
.LazyOpen(true));
437 db
.db_
->set_error_delegate(new TestErrorDelegate());
439 const GURL
kFooNameSpace1("http://foo/namespace1");
440 const GURL
kFooNameSpace2("http://foo/namespace2");
441 const GURL
kBarNameSpace1("http://bar/namespace1");
443 const AppCacheDatabase::OnlineWhiteListRecord kZeroRecord
;
444 AppCacheDatabase::OnlineWhiteListRecord record
;
445 std::vector
<AppCacheDatabase::OnlineWhiteListRecord
> records
;
447 // Behavior with an empty table
448 EXPECT_TRUE(db
.FindOnlineWhiteListForCache(1, &records
));
449 EXPECT_TRUE(records
.empty());
450 EXPECT_TRUE(db
.DeleteOnlineWhiteListForCache(1));
453 record
.namespace_url
= kFooNameSpace1
;
454 EXPECT_TRUE(db
.InsertOnlineWhiteList(&record
));
455 record
.namespace_url
= kFooNameSpace2
;
456 EXPECT_TRUE(db
.InsertOnlineWhiteList(&record
));
458 EXPECT_TRUE(db
.FindOnlineWhiteListForCache(1, &records
));
459 EXPECT_EQ(2U, records
.size());
460 EXPECT_EQ(1, records
[0].cache_id
);
461 EXPECT_EQ(kFooNameSpace1
, records
[0].namespace_url
);
462 EXPECT_EQ(1, records
[1].cache_id
);
463 EXPECT_EQ(kFooNameSpace2
, records
[1].namespace_url
);
466 record
.namespace_url
= kBarNameSpace1
;
467 EXPECT_TRUE(db
.InsertOnlineWhiteList(&record
));
469 EXPECT_TRUE(db
.FindOnlineWhiteListForCache(2, &records
));
470 EXPECT_EQ(1U, records
.size());
472 EXPECT_TRUE(db
.DeleteOnlineWhiteListForCache(1));
474 EXPECT_TRUE(db
.FindOnlineWhiteListForCache(1, &records
));
475 EXPECT_TRUE(records
.empty());
478 TEST(AppCacheDatabaseTest
, DeletableResponseIds
) {
479 const FilePath kEmptyPath
;
480 AppCacheDatabase
db(kEmptyPath
);
481 EXPECT_TRUE(db
.LazyOpen(true));
483 db
.db_
->set_error_delegate(new TestErrorDelegate());
485 std::vector
<int64
> ids
;
487 EXPECT_TRUE(db
.GetDeletableResponseIds(&ids
, kint64max
, 100));
488 EXPECT_TRUE(ids
.empty());
490 EXPECT_TRUE(db
.DeleteDeletableResponseIds(ids
));
491 EXPECT_TRUE(db
.InsertDeletableResponseIds(ids
));
494 EXPECT_TRUE(db
.GetDeletableResponseIds(&ids
, kint64max
, 100));
495 EXPECT_EQ(1U, ids
.size());
496 EXPECT_EQ(0, ids
[0]);
498 int64 unused
, deleteable_response_rowid
;
499 unused
= deleteable_response_rowid
= 0;
500 EXPECT_TRUE(db
.FindLastStorageIds(&unused
, &unused
, &unused
,
501 &deleteable_response_rowid
));
502 EXPECT_EQ(1, deleteable_response_rowid
);
505 // Expected to fail due to the duplicate id, 0 is already in the table.
509 EXPECT_FALSE(db
.InsertDeletableResponseIds(ids
));
512 for (int i
= 1; i
< 10; ++i
)
514 EXPECT_TRUE(db
.InsertDeletableResponseIds(ids
));
515 EXPECT_TRUE(db
.FindLastStorageIds(&unused
, &unused
, &unused
,
516 &deleteable_response_rowid
));
517 EXPECT_EQ(10, deleteable_response_rowid
);
520 EXPECT_TRUE(db
.GetDeletableResponseIds(&ids
, kint64max
, 100));
521 EXPECT_EQ(10U, ids
.size());
522 for (int i
= 0; i
< 10; ++i
)
523 EXPECT_EQ(i
, ids
[i
]);
525 // Ensure the limit is respected.
527 EXPECT_TRUE(db
.GetDeletableResponseIds(&ids
, kint64max
, 5));
528 EXPECT_EQ(5U, ids
.size());
529 for (int i
= 0; i
< static_cast<int>(ids
.size()); ++i
)
530 EXPECT_EQ(i
, ids
[i
]);
532 // Ensure the max_rowid is respected (the first rowid is 1).
534 EXPECT_TRUE(db
.GetDeletableResponseIds(&ids
, 5, 100));
535 EXPECT_EQ(5U, ids
.size());
536 for (int i
= 0; i
< static_cast<int>(ids
.size()); ++i
)
537 EXPECT_EQ(i
, ids
[i
]);
539 // Ensure that we can delete from the table.
540 EXPECT_TRUE(db
.DeleteDeletableResponseIds(ids
));
542 EXPECT_TRUE(db
.GetDeletableResponseIds(&ids
, kint64max
, 100));
543 EXPECT_EQ(5U, ids
.size());
544 for (int i
= 0; i
< static_cast<int>(ids
.size()); ++i
)
545 EXPECT_EQ(i
+ 5, ids
[i
]);
548 TEST(AppCacheDatabaseTest
, OriginUsage
) {
549 const GURL
kManifestUrl("http://blah/manifest");
550 const GURL
kManifestUrl2("http://blah/manifest2");
551 const GURL
kOrigin(kManifestUrl
.GetOrigin());
552 const GURL
kOtherOriginManifestUrl("http://other/manifest");
553 const GURL
kOtherOrigin(kOtherOriginManifestUrl
.GetOrigin());
555 const FilePath kEmptyPath
;
556 AppCacheDatabase
db(kEmptyPath
);
557 EXPECT_TRUE(db
.LazyOpen(true));
559 db
.db_
->set_error_delegate(new TestErrorDelegate());
561 std::vector
<AppCacheDatabase::CacheRecord
> cache_records
;
562 EXPECT_EQ(0, db
.GetOriginUsage(kOrigin
));
563 EXPECT_TRUE(db
.FindCachesForOrigin(kOrigin
, &cache_records
));
564 EXPECT_TRUE(cache_records
.empty());
566 AppCacheDatabase::GroupRecord group_record
;
567 group_record
.group_id
= 1;
568 group_record
.manifest_url
= kManifestUrl
;
569 group_record
.origin
= kOrigin
;
570 EXPECT_TRUE(db
.InsertGroup(&group_record
));
571 AppCacheDatabase::CacheRecord cache_record
;
572 cache_record
.cache_id
= 1;
573 cache_record
.group_id
= 1;
574 cache_record
.online_wildcard
= true;
575 cache_record
.update_time
= kZeroTime
;
576 cache_record
.cache_size
= 100;
577 EXPECT_TRUE(db
.InsertCache(&cache_record
));
579 EXPECT_EQ(100, db
.GetOriginUsage(kOrigin
));
581 group_record
.group_id
= 2;
582 group_record
.manifest_url
= kManifestUrl2
;
583 group_record
.origin
= kOrigin
;
584 EXPECT_TRUE(db
.InsertGroup(&group_record
));
585 cache_record
.cache_id
= 2;
586 cache_record
.group_id
= 2;
587 cache_record
.online_wildcard
= true;
588 cache_record
.update_time
= kZeroTime
;
589 cache_record
.cache_size
= 1000;
590 EXPECT_TRUE(db
.InsertCache(&cache_record
));
592 EXPECT_EQ(1100, db
.GetOriginUsage(kOrigin
));
594 group_record
.group_id
= 3;
595 group_record
.manifest_url
= kOtherOriginManifestUrl
;
596 group_record
.origin
= kOtherOrigin
;
597 EXPECT_TRUE(db
.InsertGroup(&group_record
));
598 cache_record
.cache_id
= 3;
599 cache_record
.group_id
= 3;
600 cache_record
.online_wildcard
= true;
601 cache_record
.update_time
= kZeroTime
;
602 cache_record
.cache_size
= 5000;
603 EXPECT_TRUE(db
.InsertCache(&cache_record
));
605 EXPECT_EQ(5000, db
.GetOriginUsage(kOtherOrigin
));
607 EXPECT_TRUE(db
.FindCachesForOrigin(kOrigin
, &cache_records
));
608 EXPECT_EQ(2U, cache_records
.size());
609 cache_records
.clear();
610 EXPECT_TRUE(db
.FindCachesForOrigin(kOtherOrigin
, &cache_records
));
611 EXPECT_EQ(1U, cache_records
.size());
613 std::map
<GURL
, int64
> usage_map
;
614 EXPECT_TRUE(db
.GetAllOriginUsage(&usage_map
));
615 EXPECT_EQ(2U, usage_map
.size());
616 EXPECT_EQ(1100, usage_map
[kOrigin
]);
617 EXPECT_EQ(5000, usage_map
[kOtherOrigin
]);
620 TEST(AppCacheDatabaseTest
, UpgradeSchema3to4
) {
621 // Real file on disk for this test.
622 base::ScopedTempDir temp_dir
;
623 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
624 const FilePath kDbFile
= temp_dir
.path().AppendASCII("upgrade.db");
626 const GURL
kMockOrigin("http://mockorigin/");
627 const char kNamespaceUrlFormat
[] = "namespace%d";
628 const char kTargetUrlFormat
[] = "target%d";
629 const int kNumNamespaces
= 10;
631 // Create a v3 schema based database containing some fallback records.
633 const int kVersion3
= 3;
634 const char kGroupsTable
[] = "Groups";
635 const char kCachesTable
[] = "Caches";
636 const char kEntriesTable
[] = "Entries";
637 const char kFallbackNameSpacesTable
[] = "FallbackNameSpaces";
638 const char kOnlineWhiteListsTable
[] = "OnlineWhiteLists";
639 const char kDeletableResponseIdsTable
[] = "DeletableResponseIds";
642 const char* table_name
;
646 "(group_id INTEGER PRIMARY KEY,"
648 " manifest_url TEXT,"
649 " creation_time INTEGER,"
650 " last_access_time INTEGER)" },
653 "(cache_id INTEGER PRIMARY KEY,"
655 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
656 " update_time INTEGER,"
657 " cache_size INTEGER)" }, // intentionally not normalized
663 " response_id INTEGER,"
664 " response_size INTEGER)" },
666 { kFallbackNameSpacesTable
,
668 " origin TEXT," // intentionally not normalized
669 " namespace_url TEXT,"
670 " fallback_entry_url TEXT)" },
672 { kOnlineWhiteListsTable
,
674 " namespace_url TEXT)" },
676 { kDeletableResponseIdsTable
,
677 "(response_id INTEGER NOT NULL)" },
681 const char* index_name
;
682 const char* table_name
;
686 { "GroupsOriginIndex",
691 { "GroupsManifestIndex",
696 { "CachesGroupIndex",
701 { "EntriesCacheIndex",
706 { "EntriesCacheAndUrlIndex",
711 { "EntriesResponseIdIndex",
716 { "FallbackNameSpacesCacheIndex",
717 kFallbackNameSpacesTable
,
721 { "FallbackNameSpacesOriginIndex",
722 kFallbackNameSpacesTable
,
726 { "FallbackNameSpacesCacheAndUrlIndex",
727 kFallbackNameSpacesTable
,
728 "(cache_id, namespace_url)",
731 { "OnlineWhiteListCacheIndex",
732 kOnlineWhiteListsTable
,
736 { "DeletableResponsesIdIndex",
737 kDeletableResponseIdsTable
,
742 const int kTableCount3
= ARRAYSIZE_UNSAFE(kTables3
);
743 const int kIndexCount3
= ARRAYSIZE_UNSAFE(kIndexes3
);
745 sql::Connection connection
;
746 EXPECT_TRUE(connection
.Open(kDbFile
));
748 sql::Transaction
transaction(&connection
);
749 EXPECT_TRUE(transaction
.Begin());
751 sql::MetaTable meta_table
;
752 EXPECT_TRUE(meta_table
.Init(&connection
, kVersion3
, kVersion3
));
754 for (int i
= 0; i
< kTableCount3
; ++i
) {
755 std::string
sql("CREATE TABLE ");
756 sql
+= kTables3
[i
].table_name
;
757 sql
+= kTables3
[i
].columns
;
758 EXPECT_TRUE(connection
.Execute(sql
.c_str()));
761 for (int i
= 0; i
< kIndexCount3
; ++i
) {
763 if (kIndexes3
[i
].unique
)
764 sql
+= "CREATE UNIQUE INDEX ";
766 sql
+= "CREATE INDEX ";
767 sql
+= kIndexes3
[i
].index_name
;
769 sql
+= kIndexes3
[i
].table_name
;
770 sql
+= kIndexes3
[i
].columns
;
771 EXPECT_TRUE(connection
.Execute(sql
.c_str()));
775 "INSERT INTO FallbackNameSpaces"
776 " (cache_id, origin, namespace_url, fallback_entry_url)"
777 " VALUES (?, ?, ?, ?)";
779 sql::Statement statement
;
780 statement
.Assign(connection
.GetUniqueStatement(kSql
));
781 EXPECT_TRUE(statement
.is_valid());
782 for (int i
= 0; i
< kNumNamespaces
; ++i
) {
784 kMockOrigin
.Resolve(base::StringPrintf(kNamespaceUrlFormat
, i
)));
786 kMockOrigin
.Resolve(base::StringPrintf(kTargetUrlFormat
, i
)));
787 statement
.BindInt64(0, i
);
788 statement
.BindString(1, kMockOrigin
.spec().c_str());
789 statement
.BindString(2, namespace_url
.spec().c_str());
790 statement
.BindString(3, target_url
.spec().c_str());
791 ASSERT_TRUE(statement
.Run());
792 statement
.Reset(true);
795 EXPECT_TRUE(transaction
.Commit());
798 // Open that database and verify that it got updated.
799 AppCacheDatabase
db(kDbFile
);
800 EXPECT_TRUE(db
.LazyOpen(true));
802 EXPECT_FALSE(db
.db_
->DoesTableExist("FallbackNameSpaces"));
803 EXPECT_FALSE(db
.db_
->DoesIndexExist("FallbackNamesSpacesCacheIndex"));
804 EXPECT_FALSE(db
.db_
->DoesIndexExist("FallbackNameSpacesOriginIndex"));
805 EXPECT_FALSE(db
.db_
->DoesIndexExist("FallbackNameSpacesCacheAndUrlIndex"));
807 EXPECT_TRUE(db
.db_
->DoesTableExist("Namespaces"));
808 EXPECT_TRUE(db
.db_
->DoesIndexExist("NamespacesCacheIndex"));
809 EXPECT_TRUE(db
.db_
->DoesIndexExist("NamespacesOriginIndex"));
810 EXPECT_TRUE(db
.db_
->DoesIndexExist("NamespacesCacheAndUrlIndex"));
812 EXPECT_EQ(4, db
.meta_table_
->GetVersionNumber());
813 EXPECT_EQ(4, db
.meta_table_
->GetCompatibleVersionNumber());
815 std::vector
<AppCacheDatabase::NamespaceRecord
> intercepts
;
816 std::vector
<AppCacheDatabase::NamespaceRecord
> fallbacks
;
817 EXPECT_TRUE(db
.FindNamespacesForOrigin(kMockOrigin
, &intercepts
,
819 EXPECT_TRUE(intercepts
.empty());
820 EXPECT_EQ(kNumNamespaces
, static_cast<int>(fallbacks
.size()));
822 for (int i
= 0; i
< kNumNamespaces
; ++i
) {
823 GURL
expected_namespace_url(
824 kMockOrigin
.Resolve(base::StringPrintf(kNamespaceUrlFormat
, i
)));
825 GURL
expected_target_url(
826 kMockOrigin
.Resolve(base::StringPrintf(kTargetUrlFormat
, i
)));
828 EXPECT_EQ(i
, fallbacks
[i
].cache_id
);
829 EXPECT_EQ(FALLBACK_NAMESPACE
, fallbacks
[i
].type
);
830 EXPECT_EQ(kMockOrigin
, fallbacks
[i
].origin
);
831 EXPECT_EQ(expected_namespace_url
, fallbacks
[i
].namespace_url
);
832 EXPECT_EQ(expected_target_url
, fallbacks
[i
].target_url
);
836 } // namespace appcache