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 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
;
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 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
));
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
));
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 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.
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
));
369 record
.origin
= kFooOrigin
;
370 record
.namespace_
.namespace_url
= kFooNameSpace2
;
371 record
.namespace_
.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_
.namespace_url
);
380 EXPECT_EQ(kFooFallbackEntry
, fallbacks
[0].namespace_
.target_url
);
381 EXPECT_FALSE(fallbacks
[0].namespace_
.is_pattern
);
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
);
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));
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.
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
));
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
));
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
);
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));
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
));
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
);
481 record
.namespace_url
= kBarNameSpace1
;
482 EXPECT_TRUE(db
.InsertOnlineWhiteList(&record
));
484 EXPECT_TRUE(db
.FindOnlineWhiteListForCache(2, &records
));
485 EXPECT_EQ(1U, records
.size());
487 EXPECT_TRUE(db
.DeleteOnlineWhiteListForCache(1));
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());
505 EXPECT_TRUE(db
.DeleteDeletableResponseIds(ids
));
506 EXPECT_TRUE(db
.InsertDeletableResponseIds(ids
));
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.
524 EXPECT_FALSE(db
.InsertDeletableResponseIds(ids
));
527 for (int i
= 1; i
< 10; ++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
);
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.
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).
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
));
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";
657 const char* table_name
;
661 "(group_id INTEGER PRIMARY KEY,"
663 " manifest_url TEXT,"
664 " creation_time INTEGER,"
665 " last_access_time INTEGER)" },
668 "(cache_id INTEGER PRIMARY KEY,"
670 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
671 " update_time INTEGER,"
672 " cache_size INTEGER)" }, // intentionally not normalized
678 " response_id INTEGER,"
679 " response_size INTEGER)" },
681 { kFallbackNameSpacesTable
,
683 " origin TEXT," // intentionally not normalized
684 " namespace_url TEXT,"
685 " fallback_entry_url TEXT)" },
687 { kOnlineWhiteListsTable
,
689 " namespace_url TEXT)" },
691 { kDeletableResponseIdsTable
,
692 "(response_id INTEGER NOT NULL)" },
696 const char* index_name
;
697 const char* table_name
;
701 { "GroupsOriginIndex",
706 { "GroupsManifestIndex",
711 { "CachesGroupIndex",
716 { "EntriesCacheIndex",
721 { "EntriesCacheAndUrlIndex",
726 { "EntriesResponseIdIndex",
731 { "FallbackNameSpacesCacheIndex",
732 kFallbackNameSpacesTable
,
736 { "FallbackNameSpacesOriginIndex",
737 kFallbackNameSpacesTable
,
741 { "FallbackNameSpacesCacheAndUrlIndex",
742 kFallbackNameSpacesTable
,
743 "(cache_id, namespace_url)",
746 { "OnlineWhiteListCacheIndex",
747 kOnlineWhiteListsTable
,
751 { "DeletableResponsesIdIndex",
752 kDeletableResponseIdsTable
,
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
) {
778 if (kIndexes3
[i
].unique
)
779 sql
+= "CREATE UNIQUE INDEX ";
781 sql
+= "CREATE INDEX ";
782 sql
+= kIndexes3
[i
].index_name
;
784 sql
+= kIndexes3
[i
].table_name
;
785 sql
+= kIndexes3
[i
].columns
;
786 EXPECT_TRUE(connection
.Execute(sql
.c_str()));
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
) {
799 kMockOrigin
.Resolve(base::StringPrintf(kNamespaceUrlFormat
, i
)));
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
,
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";
878 const char* table_name
;
883 const char* index_name
;
884 const char* table_name
;
889 const TableInfo kTables4
[] = {
891 "(group_id INTEGER PRIMARY KEY,"
893 " manifest_url TEXT,"
894 " creation_time INTEGER,"
895 " last_access_time INTEGER)" },
898 "(cache_id INTEGER PRIMARY KEY,"
900 " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
901 " update_time INTEGER,"
902 " cache_size INTEGER)" }, // intentionally not normalized
908 " response_id INTEGER,"
909 " response_size INTEGER)" },
913 " origin TEXT," // intentionally not normalized
915 " namespace_url TEXT,"
916 " target_url TEXT)" },
918 { kOnlineWhiteListsTable
,
920 " namespace_url TEXT)" },
922 { kDeletableResponseIdsTable
,
923 "(response_id INTEGER NOT NULL)" },
926 const IndexInfo kIndexes4
[] = {
927 { "GroupsOriginIndex",
932 { "GroupsManifestIndex",
937 { "CachesGroupIndex",
942 { "EntriesCacheIndex",
947 { "EntriesCacheAndUrlIndex",
952 { "EntriesResponseIdIndex",
957 { "NamespacesCacheIndex",
962 { "NamespacesOriginIndex",
967 { "NamespacesCacheAndUrlIndex",
969 "(cache_id, namespace_url)",
972 { "OnlineWhiteListCacheIndex",
973 kOnlineWhiteListsTable
,
977 { "DeletableResponsesIdIndex",
978 kDeletableResponseIdsTable
,
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
) {
1004 if (kIndexes4
[i
].unique
)
1005 sql
+= "CREATE UNIQUE INDEX ";
1007 sql
+= "CREATE INDEX ";
1008 sql
+= kIndexes4
[i
].index_name
;
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
) {
1024 kMockOrigin
.Resolve(base::StringPrintf(kNamespaceUrlFormat
, i
)));
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)"
1040 statement
.Assign(connection
.GetUniqueStatement(kWhitelistsSql
));
1041 EXPECT_TRUE(statement
.is_valid());
1042 for (int i
= 0; i
< kNumNamespaces
; ++i
) {
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
,
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