1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/service_worker/service_worker_database.h"
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/stl_util.h"
12 #include "content/browser/service_worker/service_worker_database.pb.h"
13 #include "content/common/service_worker/service_worker_types.h"
14 #include "testing/gtest/include/gtest/gtest.h"
20 typedef ServiceWorkerDatabase::RegistrationData RegistrationData
;
21 typedef ServiceWorkerDatabase::ResourceRecord Resource
;
28 AvailableIds() : reg_id(-1), res_id(-1), ver_id(-1) {}
32 GURL
URL(const GURL
& origin
, const std::string
& path
) {
33 EXPECT_TRUE(origin
.is_valid());
34 EXPECT_EQ(origin
, origin
.GetOrigin());
35 GURL
out(origin
.spec() + path
);
36 EXPECT_TRUE(out
.is_valid());
40 Resource
CreateResource(int64 resource_id
, const GURL
& url
, uint64 size_bytes
) {
41 EXPECT_TRUE(url
.is_valid());
42 return Resource(resource_id
, url
, size_bytes
);
45 ServiceWorkerDatabase
* CreateDatabase(const base::FilePath
& path
) {
46 return new ServiceWorkerDatabase(path
);
49 ServiceWorkerDatabase
* CreateDatabaseInMemory() {
50 return new ServiceWorkerDatabase(base::FilePath());
53 void VerifyRegistrationData(const RegistrationData
& expected
,
54 const RegistrationData
& actual
) {
55 EXPECT_EQ(expected
.registration_id
, actual
.registration_id
);
56 EXPECT_EQ(expected
.scope
, actual
.scope
);
57 EXPECT_EQ(expected
.script
, actual
.script
);
58 EXPECT_EQ(expected
.version_id
, actual
.version_id
);
59 EXPECT_EQ(expected
.is_active
, actual
.is_active
);
60 EXPECT_EQ(expected
.has_fetch_handler
, actual
.has_fetch_handler
);
61 EXPECT_EQ(expected
.last_update_check
, actual
.last_update_check
);
62 EXPECT_EQ(expected
.resources_total_size_bytes
,
63 actual
.resources_total_size_bytes
);
66 void VerifyResourceRecords(const std::vector
<Resource
>& expected
,
67 const std::vector
<Resource
>& actual
) {
68 ASSERT_EQ(expected
.size(), actual
.size());
69 for (size_t i
= 0; i
< expected
.size(); ++i
) {
70 EXPECT_EQ(expected
[i
].resource_id
, actual
[i
].resource_id
);
71 EXPECT_EQ(expected
[i
].url
, actual
[i
].url
);
72 EXPECT_EQ(expected
[i
].size_bytes
, actual
[i
].size_bytes
);
78 TEST(ServiceWorkerDatabaseTest
, OpenDatabase
) {
79 base::ScopedTempDir database_dir
;
80 ASSERT_TRUE(database_dir
.CreateUniqueTempDir());
81 scoped_ptr
<ServiceWorkerDatabase
> database(
82 CreateDatabase(database_dir
.path()));
84 // Should be false because the database does not exist at the path.
85 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND
,
86 database
->LazyOpen(false));
88 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->LazyOpen(true));
90 database
.reset(CreateDatabase(database_dir
.path()));
91 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->LazyOpen(false));
94 TEST(ServiceWorkerDatabaseTest
, OpenDatabase_InMemory
) {
95 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
97 // Should be false because the database does not exist in memory.
98 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND
,
99 database
->LazyOpen(false));
101 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->LazyOpen(true));
102 database
.reset(CreateDatabaseInMemory());
104 // Should be false because the database is not persistent.
105 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND
,
106 database
->LazyOpen(false));
109 TEST(ServiceWorkerDatabaseTest
, DatabaseVersion
) {
110 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
111 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->LazyOpen(true));
113 // Opening a new database does not write anything, so its schema version
115 int64 db_version
= -1;
116 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
117 database
->ReadDatabaseVersion(&db_version
));
118 EXPECT_EQ(0u, db_version
);
120 // First writing triggers database initialization and bumps the schema
122 std::vector
<ServiceWorkerDatabase::ResourceRecord
> resources
;
123 ServiceWorkerDatabase::RegistrationData deleted_version
;
124 std::vector
<int64
> newly_purgeable_resources
;
125 ServiceWorkerDatabase::RegistrationData data
;
126 ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK
,
127 database
->WriteRegistration(
128 data
, resources
, &deleted_version
, &newly_purgeable_resources
));
130 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
131 database
->ReadDatabaseVersion(&db_version
));
132 EXPECT_LT(0, db_version
);
135 TEST(ServiceWorkerDatabaseTest
, GetNextAvailableIds
) {
136 base::ScopedTempDir database_dir
;
137 ASSERT_TRUE(database_dir
.CreateUniqueTempDir());
138 scoped_ptr
<ServiceWorkerDatabase
> database(
139 CreateDatabase(database_dir
.path()));
141 GURL
origin("http://example.com");
143 // The database has never been used, so returns initial values.
145 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->GetNextAvailableIds(
146 &ids
.reg_id
, &ids
.ver_id
, &ids
.res_id
));
147 EXPECT_EQ(0, ids
.reg_id
);
148 EXPECT_EQ(0, ids
.ver_id
);
149 EXPECT_EQ(0, ids
.res_id
);
151 ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->LazyOpen(true));
152 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->GetNextAvailableIds(
153 &ids
.reg_id
, &ids
.ver_id
, &ids
.res_id
));
154 EXPECT_EQ(0, ids
.reg_id
);
155 EXPECT_EQ(0, ids
.ver_id
);
156 EXPECT_EQ(0, ids
.res_id
);
158 // Writing a registration bumps the next available ids.
159 std::vector
<Resource
> resources
;
160 RegistrationData data1
;
161 ServiceWorkerDatabase::RegistrationData deleted_version
;
162 std::vector
<int64
> newly_purgeable_resources
;
163 data1
.registration_id
= 100;
164 data1
.scope
= URL(origin
, "/foo");
165 data1
.script
= URL(origin
, "/script1.js");
166 data1
.version_id
= 200;
168 ServiceWorkerDatabase::STATUS_OK
,
169 database
->WriteRegistration(
170 data1
, resources
, &deleted_version
, &newly_purgeable_resources
));
172 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->GetNextAvailableIds(
173 &ids
.reg_id
, &ids
.ver_id
, &ids
.res_id
));
174 EXPECT_EQ(101, ids
.reg_id
);
175 EXPECT_EQ(201, ids
.ver_id
);
176 EXPECT_EQ(0, ids
.res_id
);
178 // Writing uncommitted resources bumps the next available id.
179 const int64 kUncommittedIds
[] = {0, 1, 3, 5, 6, 10};
181 ServiceWorkerDatabase::STATUS_OK
,
182 database
->WriteUncommittedResourceIds(std::set
<int64
>(
183 kUncommittedIds
, kUncommittedIds
+ arraysize(kUncommittedIds
))));
185 ServiceWorkerDatabase::STATUS_OK
,
186 database
->GetNextAvailableIds(&ids
.reg_id
, &ids
.ver_id
, &ids
.res_id
));
187 EXPECT_EQ(101, ids
.reg_id
);
188 EXPECT_EQ(201, ids
.ver_id
);
189 EXPECT_EQ(11, ids
.res_id
);
191 // Writing purgeable resources bumps the next available id.
192 const int64 kPurgeableIds
[] = {4, 12, 16, 17, 20};
193 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
194 database
->WriteUncommittedResourceIds(std::set
<int64
>(
195 kPurgeableIds
, kPurgeableIds
+ arraysize(kPurgeableIds
))));
197 ServiceWorkerDatabase::STATUS_OK
,
198 database
->GetNextAvailableIds(&ids
.reg_id
, &ids
.ver_id
, &ids
.res_id
));
199 EXPECT_EQ(101, ids
.reg_id
);
200 EXPECT_EQ(201, ids
.ver_id
);
201 EXPECT_EQ(21, ids
.res_id
);
203 // Writing a registration whose ids are lower than the stored ones should not
204 // bump the next available ids.
205 RegistrationData data2
;
206 data2
.registration_id
= 10;
207 data2
.scope
= URL(origin
, "/bar");
208 data2
.script
= URL(origin
, "/script2.js");
209 data2
.version_id
= 20;
211 ServiceWorkerDatabase::STATUS_OK
,
212 database
->WriteRegistration(
213 data2
, resources
, &deleted_version
, &newly_purgeable_resources
));
215 // Same with resources.
216 int64 kLowResourceId
= 15;
217 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
218 database
->WriteUncommittedResourceIds(
219 std::set
<int64
>(&kLowResourceId
, &kLowResourceId
+ 1)));
221 // Close and reopen the database to verify the stored values.
222 database
.reset(CreateDatabase(database_dir
.path()));
224 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->GetNextAvailableIds(
225 &ids
.reg_id
, &ids
.ver_id
, &ids
.res_id
));
226 EXPECT_EQ(101, ids
.reg_id
);
227 EXPECT_EQ(201, ids
.ver_id
);
228 EXPECT_EQ(21, ids
.res_id
);
231 TEST(ServiceWorkerDatabaseTest
, GetOriginsWithRegistrations
) {
232 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
234 std::set
<GURL
> origins
;
235 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
236 database
->GetOriginsWithRegistrations(&origins
));
237 EXPECT_TRUE(origins
.empty());
239 std::vector
<Resource
> resources
;
240 ServiceWorkerDatabase::RegistrationData deleted_version
;
241 std::vector
<int64
> newly_purgeable_resources
;
243 GURL
origin1("http://example.com");
244 RegistrationData data1
;
245 data1
.registration_id
= 123;
246 data1
.scope
= URL(origin1
, "/foo");
247 data1
.script
= URL(origin1
, "/script1.js");
248 data1
.version_id
= 456;
250 ServiceWorkerDatabase::STATUS_OK
,
251 database
->WriteRegistration(
252 data1
, resources
, &deleted_version
, &newly_purgeable_resources
));
254 GURL
origin2("https://www.example.com");
255 RegistrationData data2
;
256 data2
.registration_id
= 234;
257 data2
.scope
= URL(origin2
, "/bar");
258 data2
.script
= URL(origin2
, "/script2.js");
259 data2
.version_id
= 567;
261 ServiceWorkerDatabase::STATUS_OK
,
262 database
->WriteRegistration(
263 data2
, resources
, &deleted_version
, &newly_purgeable_resources
));
265 GURL
origin3("https://example.org");
266 RegistrationData data3
;
267 data3
.registration_id
= 345;
268 data3
.scope
= URL(origin3
, "/hoge");
269 data3
.script
= URL(origin3
, "/script3.js");
270 data3
.version_id
= 678;
272 ServiceWorkerDatabase::STATUS_OK
,
273 database
->WriteRegistration(
274 data3
, resources
, &deleted_version
, &newly_purgeable_resources
));
276 // |origin3| has two registrations.
277 RegistrationData data4
;
278 data4
.registration_id
= 456;
279 data4
.scope
= URL(origin3
, "/fuga");
280 data4
.script
= URL(origin3
, "/script4.js");
281 data4
.version_id
= 789;
283 ServiceWorkerDatabase::STATUS_OK
,
284 database
->WriteRegistration(
285 data4
, resources
, &deleted_version
, &newly_purgeable_resources
));
288 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
289 database
->GetOriginsWithRegistrations(&origins
));
290 EXPECT_EQ(3U, origins
.size());
291 EXPECT_TRUE(ContainsKey(origins
, origin1
));
292 EXPECT_TRUE(ContainsKey(origins
, origin2
));
293 EXPECT_TRUE(ContainsKey(origins
, origin3
));
295 // |origin3| has another registration, so should not remove it from the
296 // unique origin list.
297 ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK
,
298 database
->DeleteRegistration(data4
.registration_id
,
301 &newly_purgeable_resources
));
302 EXPECT_EQ(data4
.registration_id
, deleted_version
.registration_id
);
305 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
306 database
->GetOriginsWithRegistrations(&origins
));
307 EXPECT_EQ(3U, origins
.size());
308 EXPECT_TRUE(ContainsKey(origins
, origin1
));
309 EXPECT_TRUE(ContainsKey(origins
, origin2
));
310 EXPECT_TRUE(ContainsKey(origins
, origin3
));
312 // |origin3| should be removed from the unique origin list.
313 ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK
,
314 database
->DeleteRegistration(data3
.registration_id
,
317 &newly_purgeable_resources
));
318 EXPECT_EQ(data3
.registration_id
, deleted_version
.registration_id
);
321 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
322 database
->GetOriginsWithRegistrations(&origins
));
323 EXPECT_EQ(2U, origins
.size());
324 EXPECT_TRUE(ContainsKey(origins
, origin1
));
325 EXPECT_TRUE(ContainsKey(origins
, origin2
));
328 TEST(ServiceWorkerDatabaseTest
, GetRegistrationsForOrigin
) {
329 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
331 GURL
origin1("http://example.com");
332 GURL
origin2("https://www.example.com");
333 GURL
origin3("https://example.org");
335 std::vector
<RegistrationData
> registrations
;
336 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
337 database
->GetRegistrationsForOrigin(origin1
, ®istrations
));
338 EXPECT_TRUE(registrations
.empty());
340 std::vector
<Resource
> resources
;
341 ServiceWorkerDatabase::RegistrationData deleted_version
;
342 std::vector
<int64
> newly_purgeable_resources
;
344 RegistrationData data1
;
345 data1
.registration_id
= 100;
346 data1
.scope
= URL(origin1
, "/foo");
347 data1
.script
= URL(origin1
, "/script1.js");
348 data1
.version_id
= 1000;
350 ServiceWorkerDatabase::STATUS_OK
,
351 database
->WriteRegistration(
352 data1
, resources
, &deleted_version
, &newly_purgeable_resources
));
354 RegistrationData data2
;
355 data2
.registration_id
= 200;
356 data2
.scope
= URL(origin2
, "/bar");
357 data2
.script
= URL(origin2
, "/script2.js");
358 data2
.version_id
= 2000;
360 ServiceWorkerDatabase::STATUS_OK
,
361 database
->WriteRegistration(
362 data2
, resources
, &deleted_version
, &newly_purgeable_resources
));
364 RegistrationData data3
;
365 data3
.registration_id
= 300;
366 data3
.scope
= URL(origin3
, "/hoge");
367 data3
.script
= URL(origin3
, "/script3.js");
368 data3
.version_id
= 3000;
370 ServiceWorkerDatabase::STATUS_OK
,
371 database
->WriteRegistration(
372 data3
, resources
, &deleted_version
, &newly_purgeable_resources
));
374 // |origin3| has two registrations.
375 RegistrationData data4
;
376 data4
.registration_id
= 400;
377 data4
.scope
= URL(origin3
, "/fuga");
378 data4
.script
= URL(origin3
, "/script4.js");
379 data4
.version_id
= 4000;
381 ServiceWorkerDatabase::STATUS_OK
,
382 database
->WriteRegistration(
383 data4
, resources
, &deleted_version
, &newly_purgeable_resources
));
385 registrations
.clear();
386 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
387 database
->GetRegistrationsForOrigin(origin3
, ®istrations
));
388 EXPECT_EQ(2U, registrations
.size());
389 VerifyRegistrationData(data3
, registrations
[0]);
390 VerifyRegistrationData(data4
, registrations
[1]);
393 TEST(ServiceWorkerDatabaseTest
, GetAllRegistrations
) {
394 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
396 std::vector
<RegistrationData
> registrations
;
397 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
398 database
->GetAllRegistrations(®istrations
));
399 EXPECT_TRUE(registrations
.empty());
401 std::vector
<Resource
> resources
;
402 ServiceWorkerDatabase::RegistrationData deleted_version
;
403 std::vector
<int64
> newly_purgeable_resources
;
405 GURL
origin1("http://www1.example.com");
406 RegistrationData data1
;
407 data1
.registration_id
= 100;
408 data1
.scope
= URL(origin1
, "/foo");
409 data1
.script
= URL(origin1
, "/script1.js");
410 data1
.version_id
= 1000;
412 ServiceWorkerDatabase::STATUS_OK
,
413 database
->WriteRegistration(
414 data1
, resources
, &deleted_version
, &newly_purgeable_resources
));
416 GURL
origin2("http://www2.example.com");
417 RegistrationData data2
;
418 data2
.registration_id
= 200;
419 data2
.scope
= URL(origin2
, "/bar");
420 data2
.script
= URL(origin2
, "/script2.js");
421 data2
.version_id
= 2000;
423 ServiceWorkerDatabase::STATUS_OK
,
424 database
->WriteRegistration(
425 data2
, resources
, &deleted_version
, &newly_purgeable_resources
));
427 GURL
origin3("http://www3.example.com");
428 RegistrationData data3
;
429 data3
.registration_id
= 300;
430 data3
.scope
= URL(origin3
, "/hoge");
431 data3
.script
= URL(origin3
, "/script3.js");
432 data3
.version_id
= 3000;
434 ServiceWorkerDatabase::STATUS_OK
,
435 database
->WriteRegistration(
436 data3
, resources
, &deleted_version
, &newly_purgeable_resources
));
438 // |origin3| has two registrations.
439 RegistrationData data4
;
440 data4
.registration_id
= 400;
441 data4
.scope
= URL(origin3
, "/fuga");
442 data4
.script
= URL(origin3
, "/script4.js");
443 data4
.version_id
= 4000;
445 ServiceWorkerDatabase::STATUS_OK
,
446 database
->WriteRegistration(
447 data4
, resources
, &deleted_version
, &newly_purgeable_resources
));
449 registrations
.clear();
450 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
451 database
->GetAllRegistrations(®istrations
));
452 EXPECT_EQ(4U, registrations
.size());
453 VerifyRegistrationData(data1
, registrations
[0]);
454 VerifyRegistrationData(data2
, registrations
[1]);
455 VerifyRegistrationData(data3
, registrations
[2]);
456 VerifyRegistrationData(data4
, registrations
[3]);
459 TEST(ServiceWorkerDatabaseTest
, Registration_Basic
) {
460 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
462 GURL
origin("http://example.com");
463 RegistrationData data
;
464 data
.registration_id
= 100;
465 data
.scope
= URL(origin
, "/foo");
466 data
.script
= URL(origin
, "/script.js");
467 data
.version_id
= 200;
468 data
.resources_total_size_bytes
= 10939 + 200;
470 std::vector
<Resource
> resources
;
471 resources
.push_back(CreateResource(1, URL(origin
, "/resource1"), 10939));
472 resources
.push_back(CreateResource(2, URL(origin
, "/resource2"), 200));
474 // Write a resource to the uncommitted list to make sure that writing
475 // registration removes resource ids associated with the registration from
476 // the uncommitted list.
477 std::set
<int64
> uncommitted_ids
;
478 uncommitted_ids
.insert(resources
[0].resource_id
);
479 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
480 database
->WriteUncommittedResourceIds(uncommitted_ids
));
481 std::set
<int64
> uncommitted_ids_out
;
482 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
483 database
->GetUncommittedResourceIds(&uncommitted_ids_out
));
484 EXPECT_EQ(uncommitted_ids
, uncommitted_ids_out
);
486 ServiceWorkerDatabase::RegistrationData deleted_version
;
487 deleted_version
.version_id
= 222; // Dummy initial value
488 std::vector
<int64
> newly_purgeable_resources
;
490 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
491 database
->WriteRegistration(
492 data
, resources
, &deleted_version
, &newly_purgeable_resources
));
493 EXPECT_EQ(kInvalidServiceWorkerVersionId
, deleted_version
.version_id
);
494 EXPECT_TRUE(newly_purgeable_resources
.empty());
496 // Make sure that the registration and resource records are stored.
497 RegistrationData data_out
;
498 std::vector
<Resource
> resources_out
;
499 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
500 database
->ReadRegistration(
501 data
.registration_id
, origin
, &data_out
, &resources_out
));
502 VerifyRegistrationData(data
, data_out
);
503 VerifyResourceRecords(resources
, resources_out
);
505 // Make sure that the resource is removed from the uncommitted list.
506 uncommitted_ids_out
.clear();
507 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
508 database
->GetUncommittedResourceIds(&uncommitted_ids_out
));
509 EXPECT_TRUE(uncommitted_ids_out
.empty());
511 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
512 database
->DeleteRegistration(data
.registration_id
,
515 &newly_purgeable_resources
));
516 EXPECT_EQ(data
.version_id
, deleted_version
.version_id
);
517 ASSERT_EQ(resources
.size(), newly_purgeable_resources
.size());
518 for (size_t i
= 0; i
< resources
.size(); ++i
)
519 EXPECT_EQ(newly_purgeable_resources
[i
], resources
[i
].resource_id
);
521 // Make sure that the registration and resource records are gone.
522 resources_out
.clear();
523 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND
,
524 database
->ReadRegistration(
525 data
.registration_id
, origin
, &data_out
, &resources_out
));
526 EXPECT_TRUE(resources_out
.empty());
528 // Resources should be purgeable because these are no longer referred.
529 std::set
<int64
> purgeable_ids_out
;
530 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
531 database
->GetPurgeableResourceIds(&purgeable_ids_out
));
532 EXPECT_EQ(2u, purgeable_ids_out
.size());
533 EXPECT_TRUE(ContainsKey(purgeable_ids_out
, resources
[0].resource_id
));
534 EXPECT_TRUE(ContainsKey(purgeable_ids_out
, resources
[1].resource_id
));
537 TEST(ServiceWorkerDatabaseTest
, DeleteNonExistentRegistration
) {
538 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
540 GURL
origin("http://example.com");
541 RegistrationData data
;
542 data
.registration_id
= 100;
543 data
.scope
= URL(origin
, "/foo");
544 data
.script
= URL(origin
, "/script.js");
545 data
.version_id
= 200;
546 data
.resources_total_size_bytes
= 19 + 29129;
548 std::vector
<Resource
> resources
;
549 resources
.push_back(CreateResource(1, URL(origin
, "/resource1"), 19));
550 resources
.push_back(CreateResource(2, URL(origin
, "/resource2"), 29129));
552 const int64 kNonExistentRegistrationId
= 999;
553 const int64 kArbitraryVersionId
= 222; // Used as a dummy initial value
555 ServiceWorkerDatabase::RegistrationData deleted_version
;
556 deleted_version
.version_id
= kArbitraryVersionId
;
557 std::vector
<int64
> newly_purgeable_resources
;
558 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
559 database
->WriteRegistration(
560 data
, resources
, &deleted_version
, &newly_purgeable_resources
));
561 EXPECT_EQ(kInvalidServiceWorkerVersionId
, deleted_version
.version_id
);
562 EXPECT_TRUE(newly_purgeable_resources
.empty());
564 // Delete from an origin that has a registration.
565 deleted_version
.version_id
= kArbitraryVersionId
;
566 newly_purgeable_resources
.clear();
567 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
568 database
->DeleteRegistration(kNonExistentRegistrationId
,
571 &newly_purgeable_resources
));
572 EXPECT_EQ(kInvalidServiceWorkerVersionId
, deleted_version
.version_id
);
573 EXPECT_TRUE(newly_purgeable_resources
.empty());
575 // Delete from an origin that has no registration.
576 deleted_version
.version_id
= kArbitraryVersionId
;
577 newly_purgeable_resources
.clear();
578 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
579 database
->DeleteRegistration(kNonExistentRegistrationId
,
580 GURL("http://example.net"),
582 &newly_purgeable_resources
));
583 EXPECT_EQ(kInvalidServiceWorkerVersionId
, deleted_version
.version_id
);
584 EXPECT_TRUE(newly_purgeable_resources
.empty());
587 TEST(ServiceWorkerDatabaseTest
, Registration_Overwrite
) {
588 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
590 GURL
origin("http://example.com");
591 RegistrationData data
;
592 data
.registration_id
= 100;
593 data
.scope
= URL(origin
, "/foo");
594 data
.script
= URL(origin
, "/script.js");
595 data
.version_id
= 200;
596 data
.resources_total_size_bytes
= 10 + 11;
598 std::vector
<Resource
> resources1
;
599 resources1
.push_back(CreateResource(1, URL(origin
, "/resource1"), 10));
600 resources1
.push_back(CreateResource(2, URL(origin
, "/resource2"), 11));
602 ServiceWorkerDatabase::RegistrationData deleted_version
;
603 deleted_version
.version_id
= 222; // Dummy inital value
604 std::vector
<int64
> newly_purgeable_resources
;
607 ServiceWorkerDatabase::STATUS_OK
,
608 database
->WriteRegistration(
609 data
, resources1
, &deleted_version
, &newly_purgeable_resources
));
610 EXPECT_EQ(kInvalidServiceWorkerVersionId
, deleted_version
.version_id
);
611 EXPECT_TRUE(newly_purgeable_resources
.empty());
613 // Make sure that the registration and resource records are stored.
614 RegistrationData data_out
;
615 std::vector
<Resource
> resources_out
;
616 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->ReadRegistration(
617 data
.registration_id
, origin
, &data_out
, &resources_out
));
618 VerifyRegistrationData(data
, data_out
);
619 VerifyResourceRecords(resources1
, resources_out
);
621 // Update the registration.
622 RegistrationData updated_data
= data
;
623 updated_data
.version_id
= data
.version_id
+ 1;
624 updated_data
.resources_total_size_bytes
= 12 + 13;
625 std::vector
<Resource
> resources2
;
626 resources2
.push_back(CreateResource(3, URL(origin
, "/resource3"), 12));
627 resources2
.push_back(CreateResource(4, URL(origin
, "/resource4"), 13));
629 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
630 database
->WriteRegistration(updated_data
,
633 &newly_purgeable_resources
));
634 EXPECT_EQ(data
.version_id
, deleted_version
.version_id
);
635 ASSERT_EQ(resources1
.size(), newly_purgeable_resources
.size());
636 for (size_t i
= 0; i
< resources1
.size(); ++i
)
637 EXPECT_EQ(newly_purgeable_resources
[i
], resources1
[i
].resource_id
);
639 // Make sure that |updated_data| is stored and resources referred from |data|
640 // is moved to the purgeable list.
641 resources_out
.clear();
642 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->ReadRegistration(
643 updated_data
.registration_id
, origin
, &data_out
, &resources_out
));
644 VerifyRegistrationData(updated_data
, data_out
);
645 VerifyResourceRecords(resources2
, resources_out
);
647 std::set
<int64
> purgeable_ids_out
;
648 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
649 database
->GetPurgeableResourceIds(&purgeable_ids_out
));
650 EXPECT_EQ(2u, purgeable_ids_out
.size());
651 EXPECT_TRUE(ContainsKey(purgeable_ids_out
, resources1
[0].resource_id
));
652 EXPECT_TRUE(ContainsKey(purgeable_ids_out
, resources1
[1].resource_id
));
655 TEST(ServiceWorkerDatabaseTest
, Registration_Multiple
) {
656 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
657 GURL
origin("http://example.com");
659 ServiceWorkerDatabase::RegistrationData deleted_version
;
660 std::vector
<int64
> newly_purgeable_resources
;
662 // Add registration1.
663 RegistrationData data1
;
664 data1
.registration_id
= 100;
665 data1
.scope
= URL(origin
, "/foo");
666 data1
.script
= URL(origin
, "/script1.js");
667 data1
.version_id
= 200;
668 data1
.resources_total_size_bytes
= 1451 + 15234;
670 std::vector
<Resource
> resources1
;
671 resources1
.push_back(CreateResource(1, URL(origin
, "/resource1"), 1451));
672 resources1
.push_back(CreateResource(2, URL(origin
, "/resource2"), 15234));
674 ServiceWorkerDatabase::STATUS_OK
,
675 database
->WriteRegistration(
676 data1
, resources1
, &deleted_version
, &newly_purgeable_resources
));
678 // Add registration2.
679 RegistrationData data2
;
680 data2
.registration_id
= 101;
681 data2
.scope
= URL(origin
, "/bar");
682 data2
.script
= URL(origin
, "/script2.js");
683 data2
.version_id
= 201;
684 data2
.resources_total_size_bytes
= 5 + 6;
686 std::vector
<Resource
> resources2
;
687 resources2
.push_back(CreateResource(3, URL(origin
, "/resource3"), 5));
688 resources2
.push_back(CreateResource(4, URL(origin
, "/resource4"), 6));
690 ServiceWorkerDatabase::STATUS_OK
,
691 database
->WriteRegistration(
692 data2
, resources2
, &deleted_version
, &newly_purgeable_resources
));
694 // Make sure that registration1 is stored.
695 RegistrationData data_out
;
696 std::vector
<Resource
> resources_out
;
697 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->ReadRegistration(
698 data1
.registration_id
, origin
, &data_out
, &resources_out
));
699 VerifyRegistrationData(data1
, data_out
);
700 VerifyResourceRecords(resources1
, resources_out
);
702 // Make sure that registration2 is also stored.
703 resources_out
.clear();
704 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->ReadRegistration(
705 data2
.registration_id
, origin
, &data_out
, &resources_out
));
706 VerifyRegistrationData(data2
, data_out
);
707 VerifyResourceRecords(resources2
, resources_out
);
709 std::set
<int64
> purgeable_ids_out
;
710 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
711 database
->GetPurgeableResourceIds(&purgeable_ids_out
));
712 EXPECT_TRUE(purgeable_ids_out
.empty());
714 // Delete registration1.
715 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
716 database
->DeleteRegistration(data1
.registration_id
,
719 &newly_purgeable_resources
));
720 EXPECT_EQ(data1
.registration_id
, deleted_version
.registration_id
);
722 // Make sure that registration1 is gone.
723 resources_out
.clear();
724 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND
,
725 database
->ReadRegistration(
726 data1
.registration_id
, origin
, &data_out
, &resources_out
));
727 EXPECT_TRUE(resources_out
.empty());
729 purgeable_ids_out
.clear();
730 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
731 database
->GetPurgeableResourceIds(&purgeable_ids_out
));
732 EXPECT_EQ(2u, purgeable_ids_out
.size());
733 EXPECT_TRUE(ContainsKey(purgeable_ids_out
, resources1
[0].resource_id
));
734 EXPECT_TRUE(ContainsKey(purgeable_ids_out
, resources1
[1].resource_id
));
736 // Make sure that registration2 is still alive.
737 resources_out
.clear();
738 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->ReadRegistration(
739 data2
.registration_id
, origin
, &data_out
, &resources_out
));
740 VerifyRegistrationData(data2
, data_out
);
741 VerifyResourceRecords(resources2
, resources_out
);
744 TEST(ServiceWorkerDatabaseTest
, UpdateVersionToActive
) {
745 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
746 GURL
origin("http://example.com");
748 ServiceWorkerDatabase::RegistrationData deleted_version
;
749 std::vector
<int64
> newly_purgeable_resources
;
751 // Should be false because a registration does not exist.
752 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND
,
753 database
->UpdateVersionToActive(0, origin
));
755 // Add a registration.
756 RegistrationData data
;
757 data
.registration_id
= 100;
758 data
.scope
= URL(origin
, "/foo");
759 data
.script
= URL(origin
, "/script.js");
760 data
.version_id
= 200;
761 data
.is_active
= false;
762 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
763 database
->WriteRegistration(data
,
764 std::vector
<Resource
>(),
766 &newly_purgeable_resources
));
768 // Make sure that the registration is stored.
769 RegistrationData data_out
;
770 std::vector
<Resource
> resources_out
;
771 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
772 database
->ReadRegistration(
773 data
.registration_id
, origin
, &data_out
, &resources_out
));
774 VerifyRegistrationData(data
, data_out
);
775 EXPECT_TRUE(resources_out
.empty());
777 // Activate the registration.
778 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
779 database
->UpdateVersionToActive(data
.registration_id
, origin
));
781 // Make sure that the registration is activated.
782 resources_out
.clear();
783 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
784 database
->ReadRegistration(
785 data
.registration_id
, origin
, &data_out
, &resources_out
));
786 RegistrationData expected_data
= data
;
787 expected_data
.is_active
= true;
788 VerifyRegistrationData(expected_data
, data_out
);
789 EXPECT_TRUE(resources_out
.empty());
791 // Delete the registration.
792 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
793 database
->DeleteRegistration(data
.registration_id
,
796 &newly_purgeable_resources
));
797 EXPECT_EQ(data
.registration_id
, deleted_version
.registration_id
);
799 // Should be false because the registration is gone.
800 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND
,
801 database
->UpdateVersionToActive(data
.registration_id
, origin
));
804 TEST(ServiceWorkerDatabaseTest
, UpdateLastCheckTime
) {
805 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
806 GURL
origin("http://example.com");
807 ServiceWorkerDatabase::RegistrationData deleted_version
;
808 std::vector
<int64
> newly_purgeable_resources
;
810 // Should be false because a registration does not exist.
811 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND
,
812 database
->UpdateLastCheckTime(0, origin
, base::Time::Now()));
814 // Add a registration.
815 RegistrationData data
;
816 data
.registration_id
= 100;
817 data
.scope
= URL(origin
, "/foo");
818 data
.script
= URL(origin
, "/script.js");
819 data
.version_id
= 200;
820 data
.last_update_check
= base::Time::Now();
821 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
822 database
->WriteRegistration(data
,
823 std::vector
<Resource
>(),
825 &newly_purgeable_resources
));
827 // Make sure that the registration is stored.
828 RegistrationData data_out
;
829 std::vector
<Resource
> resources_out
;
830 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
831 database
->ReadRegistration(
832 data
.registration_id
, origin
, &data_out
, &resources_out
));
833 VerifyRegistrationData(data
, data_out
);
834 EXPECT_TRUE(resources_out
.empty());
836 // Update the last check time.
837 base::Time updated_time
= base::Time::Now();
838 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
839 database
->UpdateLastCheckTime(
840 data
.registration_id
, origin
, updated_time
));
842 // Make sure that the registration is updated.
843 resources_out
.clear();
844 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
845 database
->ReadRegistration(
846 data
.registration_id
, origin
, &data_out
, &resources_out
));
847 RegistrationData expected_data
= data
;
848 expected_data
.last_update_check
= updated_time
;
849 VerifyRegistrationData(expected_data
, data_out
);
850 EXPECT_TRUE(resources_out
.empty());
852 // Delete the registration.
853 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
854 database
->DeleteRegistration(data
.registration_id
,
857 &newly_purgeable_resources
));
858 EXPECT_EQ(data
.registration_id
, deleted_version
.registration_id
);
860 // Should be false because the registration is gone.
861 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND
,
862 database
->UpdateLastCheckTime(
863 data
.registration_id
, origin
, base::Time::Now()));
866 TEST(ServiceWorkerDatabaseTest
, UncommittedResourceIds
) {
867 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
870 std::set
<int64
> ids1
;
874 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
875 database
->WriteUncommittedResourceIds(ids1
));
877 std::set
<int64
> ids_out
;
878 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
879 database
->GetUncommittedResourceIds(&ids_out
));
880 EXPECT_EQ(ids1
, ids_out
);
883 std::set
<int64
> ids2
;
886 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
887 database
->WriteUncommittedResourceIds(ids2
));
890 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
891 database
->GetUncommittedResourceIds(&ids_out
));
892 std::set
<int64
> expected
= base::STLSetUnion
<std::set
<int64
> >(ids1
, ids2
);
893 EXPECT_EQ(expected
, ids_out
);
896 std::set
<int64
> ids3
;
899 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
900 database
->ClearUncommittedResourceIds(ids3
));
903 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
904 database
->GetUncommittedResourceIds(&ids_out
));
905 expected
= base::STLSetDifference
<std::set
<int64
> >(expected
, ids3
);
906 EXPECT_EQ(expected
, ids_out
);
909 TEST(ServiceWorkerDatabaseTest
, PurgeableResourceIds
) {
910 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
913 std::set
<int64
> ids1
;
917 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
918 database
->WritePurgeableResourceIds(ids1
));
920 std::set
<int64
> ids_out
;
921 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
922 database
->GetPurgeableResourceIds(&ids_out
));
923 EXPECT_EQ(ids1
, ids_out
);
926 std::set
<int64
> ids2
;
929 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
930 database
->WritePurgeableResourceIds(ids2
));
933 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
934 database
->GetPurgeableResourceIds(&ids_out
));
935 std::set
<int64
> expected
= base::STLSetUnion
<std::set
<int64
> >(ids1
, ids2
);
936 EXPECT_EQ(expected
, ids_out
);
939 std::set
<int64
> ids3
;
942 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
943 database
->ClearPurgeableResourceIds(ids3
));
946 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
947 database
->GetPurgeableResourceIds(&ids_out
));
948 expected
= base::STLSetDifference
<std::set
<int64
> >(expected
, ids3
);
949 EXPECT_EQ(expected
, ids_out
);
952 TEST(ServiceWorkerDatabaseTest
, DeleteAllDataForOrigin
) {
953 scoped_ptr
<ServiceWorkerDatabase
> database(CreateDatabaseInMemory());
954 ServiceWorkerDatabase::RegistrationData deleted_version
;
955 std::vector
<int64
> newly_purgeable_resources
;
957 // Data associated with |origin1| will be removed.
958 GURL
origin1("http://example.com");
959 GURL
origin2("http://example.org");
961 // |origin1| has two registrations.
962 RegistrationData data1
;
963 data1
.registration_id
= 10;
964 data1
.scope
= URL(origin1
, "/foo");
965 data1
.script
= URL(origin1
, "/script1.js");
966 data1
.version_id
= 100;
967 data1
.resources_total_size_bytes
= 2013 + 512;
969 std::vector
<Resource
> resources1
;
970 resources1
.push_back(CreateResource(1, URL(origin1
, "/resource1"), 2013));
971 resources1
.push_back(CreateResource(2, URL(origin1
, "/resource2"), 512));
973 ServiceWorkerDatabase::STATUS_OK
,
974 database
->WriteRegistration(
975 data1
, resources1
, &deleted_version
, &newly_purgeable_resources
));
977 RegistrationData data2
;
978 data2
.registration_id
= 11;
979 data2
.scope
= URL(origin1
, "/bar");
980 data2
.script
= URL(origin1
, "/script2.js");
981 data2
.version_id
= 101;
982 data2
.resources_total_size_bytes
= 4 + 5;
984 std::vector
<Resource
> resources2
;
985 resources2
.push_back(CreateResource(3, URL(origin1
, "/resource3"), 4));
986 resources2
.push_back(CreateResource(4, URL(origin1
, "/resource4"), 5));
988 ServiceWorkerDatabase::STATUS_OK
,
989 database
->WriteRegistration(
990 data2
, resources2
, &deleted_version
, &newly_purgeable_resources
));
992 // |origin2| has one registration.
993 RegistrationData data3
;
994 data3
.registration_id
= 12;
995 data3
.scope
= URL(origin2
, "/hoge");
996 data3
.script
= URL(origin2
, "/script3.js");
997 data3
.version_id
= 102;
998 data3
.resources_total_size_bytes
= 6 + 7;
1000 std::vector
<Resource
> resources3
;
1001 resources3
.push_back(CreateResource(5, URL(origin2
, "/resource5"), 6));
1002 resources3
.push_back(CreateResource(6, URL(origin2
, "/resource6"), 7));
1004 ServiceWorkerDatabase::STATUS_OK
,
1005 database
->WriteRegistration(
1006 data3
, resources3
, &deleted_version
, &newly_purgeable_resources
));
1008 std::set
<GURL
> origins_to_delete
;
1009 origins_to_delete
.insert(origin1
);
1010 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
1011 database
->DeleteAllDataForOrigins(origins_to_delete
,
1012 &newly_purgeable_resources
));
1014 // |origin1| should be removed from the unique origin list.
1015 std::set
<GURL
> unique_origins
;
1016 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
1017 database
->GetOriginsWithRegistrations(&unique_origins
));
1018 EXPECT_EQ(1u, unique_origins
.size());
1019 EXPECT_TRUE(ContainsKey(unique_origins
, origin2
));
1021 // The registrations for |origin1| should be removed.
1022 std::vector
<RegistrationData
> registrations
;
1023 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
1024 database
->GetRegistrationsForOrigin(origin1
, ®istrations
));
1025 EXPECT_TRUE(registrations
.empty());
1027 // The registration for |origin2| should not be removed.
1028 RegistrationData data_out
;
1029 std::vector
<Resource
> resources_out
;
1030 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->ReadRegistration(
1031 data3
.registration_id
, origin2
, &data_out
, &resources_out
));
1032 VerifyRegistrationData(data3
, data_out
);
1033 VerifyResourceRecords(resources3
, resources_out
);
1035 // The resources associated with |origin1| should be purgeable.
1036 std::set
<int64
> purgeable_ids_out
;
1037 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
,
1038 database
->GetPurgeableResourceIds(&purgeable_ids_out
));
1039 EXPECT_EQ(4u, purgeable_ids_out
.size());
1040 EXPECT_TRUE(ContainsKey(purgeable_ids_out
, 1));
1041 EXPECT_TRUE(ContainsKey(purgeable_ids_out
, 2));
1042 EXPECT_TRUE(ContainsKey(purgeable_ids_out
, 3));
1043 EXPECT_TRUE(ContainsKey(purgeable_ids_out
, 4));
1046 TEST(ServiceWorkerDatabaseTest
, DestroyDatabase
) {
1047 base::ScopedTempDir database_dir
;
1048 ASSERT_TRUE(database_dir
.CreateUniqueTempDir());
1049 scoped_ptr
<ServiceWorkerDatabase
> database(
1050 CreateDatabase(database_dir
.path()));
1052 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->LazyOpen(true));
1053 ASSERT_TRUE(base::DirectoryExists(database_dir
.path()));
1055 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK
, database
->DestroyDatabase());
1056 ASSERT_FALSE(base::DirectoryExists(database_dir
.path()));
1059 } // namespace content