service_worker_database_unittest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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. 4 5#include "content/browser/service_worker/service_worker_database.h" 6 7#include <string> 8 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" 15 16namespace content { 17 18namespace { 19 20typedef ServiceWorkerDatabase::RegistrationData RegistrationData; 21typedef ServiceWorkerDatabase::ResourceRecord Resource; 22 23struct AvailableIds { 24 int64 reg_id; 25 int64 res_id; 26 int64 ver_id; 27 28 AvailableIds() : reg_id(-1), res_id(-1), ver_id(-1) {} 29 ~AvailableIds() {} 30}; 31 32GURL 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()); 37 return out; 38} 39 40Resource CreateResource(int64 resource_id, const GURL& url) { 41 EXPECT_TRUE(url.is_valid()); 42 Resource resource; 43 resource.resource_id = resource_id; 44 resource.url = url; 45 return resource; 46} 47 48ServiceWorkerDatabase* CreateDatabase(const base::FilePath& path) { 49 return new ServiceWorkerDatabase(path); 50} 51 52ServiceWorkerDatabase* CreateDatabaseInMemory() { 53 return new ServiceWorkerDatabase(base::FilePath()); 54} 55 56void VerifyRegistrationData(const RegistrationData& expected, 57 const RegistrationData& actual) { 58 EXPECT_EQ(expected.registration_id, actual.registration_id); 59 EXPECT_EQ(expected.scope, actual.scope); 60 EXPECT_EQ(expected.script, actual.script); 61 EXPECT_EQ(expected.version_id, actual.version_id); 62 EXPECT_EQ(expected.is_active, actual.is_active); 63 EXPECT_EQ(expected.has_fetch_handler, actual.has_fetch_handler); 64 EXPECT_EQ(expected.last_update_check, actual.last_update_check); 65} 66 67void VerifyResourceRecords(const std::vector<Resource>& expected, 68 const std::vector<Resource>& actual) { 69 ASSERT_EQ(expected.size(), actual.size()); 70 for (size_t i = 0; i < expected.size(); ++i) { 71 EXPECT_EQ(expected[i].resource_id, actual[i].resource_id); 72 EXPECT_EQ(expected[i].url, actual[i].url); 73 } 74} 75 76} // namespace 77 78TEST(ServiceWorkerDatabaseTest, OpenDatabase) { 79 base::ScopedTempDir database_dir; 80 ASSERT_TRUE(database_dir.CreateUniqueTempDir()); 81 scoped_ptr<ServiceWorkerDatabase> database( 82 CreateDatabase(database_dir.path())); 83 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)); 87 88 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true)); 89 90 database.reset(CreateDatabase(database_dir.path())); 91 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(false)); 92} 93 94TEST(ServiceWorkerDatabaseTest, OpenDatabase_InMemory) { 95 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 96 97 // Should be false because the database does not exist in memory. 98 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, 99 database->LazyOpen(false)); 100 101 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true)); 102 database.reset(CreateDatabaseInMemory()); 103 104 // Should be false because the database is not persistent. 105 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, 106 database->LazyOpen(false)); 107} 108 109TEST(ServiceWorkerDatabaseTest, DatabaseVersion) { 110 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 111 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true)); 112 113 // Opening a new database does not write anything, so its schema version 114 // should be 0. 115 int64 db_version = -1; 116 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 117 database->ReadDatabaseVersion(&db_version)); 118 EXPECT_EQ(0u, db_version); 119 120 // First writing triggers database initialization and bumps the schema 121 // version. 122 std::vector<ServiceWorkerDatabase::ResourceRecord> resources; 123 int64 deleted_version_id; 124 std::vector<int64> newly_purgeable_resources; 125 ServiceWorkerDatabase::RegistrationData data; 126 ASSERT_EQ( 127 ServiceWorkerDatabase::STATUS_OK, 128 database->WriteRegistration( 129 data, resources, &deleted_version_id, &newly_purgeable_resources)); 130 131 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 132 database->ReadDatabaseVersion(&db_version)); 133 EXPECT_LT(0, db_version); 134} 135 136TEST(ServiceWorkerDatabaseTest, GetNextAvailableIds) { 137 base::ScopedTempDir database_dir; 138 ASSERT_TRUE(database_dir.CreateUniqueTempDir()); 139 scoped_ptr<ServiceWorkerDatabase> database( 140 CreateDatabase(database_dir.path())); 141 142 GURL origin("http://example.com"); 143 144 // The database has never been used, so returns initial values. 145 AvailableIds ids; 146 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds( 147 &ids.reg_id, &ids.ver_id, &ids.res_id)); 148 EXPECT_EQ(0, ids.reg_id); 149 EXPECT_EQ(0, ids.ver_id); 150 EXPECT_EQ(0, ids.res_id); 151 152 ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true)); 153 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds( 154 &ids.reg_id, &ids.ver_id, &ids.res_id)); 155 EXPECT_EQ(0, ids.reg_id); 156 EXPECT_EQ(0, ids.ver_id); 157 EXPECT_EQ(0, ids.res_id); 158 159 // Writing a registration bumps the next available ids. 160 std::vector<Resource> resources; 161 RegistrationData data1; 162 int64 deleted_version_id; 163 std::vector<int64> newly_purgeable_resources; 164 data1.registration_id = 100; 165 data1.scope = URL(origin, "/foo"); 166 data1.script = URL(origin, "/script1.js"); 167 data1.version_id = 200; 168 ASSERT_EQ( 169 ServiceWorkerDatabase::STATUS_OK, 170 database->WriteRegistration( 171 data1, resources, &deleted_version_id, &newly_purgeable_resources)); 172 173 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds( 174 &ids.reg_id, &ids.ver_id, &ids.res_id)); 175 EXPECT_EQ(101, ids.reg_id); 176 EXPECT_EQ(201, ids.ver_id); 177 EXPECT_EQ(0, ids.res_id); 178 179 // Writing uncommitted resources bumps the next available id. 180 const int64 kUncommittedIds[] = {0, 1, 3, 5, 6, 10}; 181 EXPECT_EQ( 182 ServiceWorkerDatabase::STATUS_OK, 183 database->WriteUncommittedResourceIds(std::set<int64>( 184 kUncommittedIds, kUncommittedIds + arraysize(kUncommittedIds)))); 185 EXPECT_EQ( 186 ServiceWorkerDatabase::STATUS_OK, 187 database->GetNextAvailableIds(&ids.reg_id, &ids.ver_id, &ids.res_id)); 188 EXPECT_EQ(101, ids.reg_id); 189 EXPECT_EQ(201, ids.ver_id); 190 EXPECT_EQ(11, ids.res_id); 191 192 // Writing purgeable resources bumps the next available id. 193 const int64 kPurgeableIds[] = {4, 12, 16, 17, 20}; 194 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 195 database->WriteUncommittedResourceIds(std::set<int64>( 196 kPurgeableIds, kPurgeableIds + arraysize(kPurgeableIds)))); 197 EXPECT_EQ( 198 ServiceWorkerDatabase::STATUS_OK, 199 database->GetNextAvailableIds(&ids.reg_id, &ids.ver_id, &ids.res_id)); 200 EXPECT_EQ(101, ids.reg_id); 201 EXPECT_EQ(201, ids.ver_id); 202 EXPECT_EQ(21, ids.res_id); 203 204 // Writing a registration whose ids are lower than the stored ones should not 205 // bump the next available ids. 206 RegistrationData data2; 207 data2.registration_id = 10; 208 data2.scope = URL(origin, "/bar"); 209 data2.script = URL(origin, "/script2.js"); 210 data2.version_id = 20; 211 ASSERT_EQ( 212 ServiceWorkerDatabase::STATUS_OK, 213 database->WriteRegistration( 214 data2, resources, &deleted_version_id, &newly_purgeable_resources)); 215 216 // Same with resources. 217 int64 kLowResourceId = 15; 218 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 219 database->WriteUncommittedResourceIds( 220 std::set<int64>(&kLowResourceId, &kLowResourceId + 1))); 221 222 // Close and reopen the database to verify the stored values. 223 database.reset(CreateDatabase(database_dir.path())); 224 225 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds( 226 &ids.reg_id, &ids.ver_id, &ids.res_id)); 227 EXPECT_EQ(101, ids.reg_id); 228 EXPECT_EQ(201, ids.ver_id); 229 EXPECT_EQ(21, ids.res_id); 230} 231 232TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) { 233 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 234 235 std::set<GURL> origins; 236 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 237 database->GetOriginsWithRegistrations(&origins)); 238 EXPECT_TRUE(origins.empty()); 239 240 std::vector<Resource> resources; 241 int64 deleted_version_id; 242 std::vector<int64> newly_purgeable_resources; 243 244 GURL origin1("http://example.com"); 245 RegistrationData data1; 246 data1.registration_id = 123; 247 data1.scope = URL(origin1, "/foo"); 248 data1.script = URL(origin1, "/script1.js"); 249 data1.version_id = 456; 250 ASSERT_EQ( 251 ServiceWorkerDatabase::STATUS_OK, 252 database->WriteRegistration( 253 data1, resources, &deleted_version_id, &newly_purgeable_resources)); 254 255 GURL origin2("https://www.example.com"); 256 RegistrationData data2; 257 data2.registration_id = 234; 258 data2.scope = URL(origin2, "/bar"); 259 data2.script = URL(origin2, "/script2.js"); 260 data2.version_id = 567; 261 ASSERT_EQ( 262 ServiceWorkerDatabase::STATUS_OK, 263 database->WriteRegistration( 264 data2, resources, &deleted_version_id, &newly_purgeable_resources)); 265 266 GURL origin3("https://example.org"); 267 RegistrationData data3; 268 data3.registration_id = 345; 269 data3.scope = URL(origin3, "/hoge"); 270 data3.script = URL(origin3, "/script3.js"); 271 data3.version_id = 678; 272 ASSERT_EQ( 273 ServiceWorkerDatabase::STATUS_OK, 274 database->WriteRegistration( 275 data3, resources, &deleted_version_id, &newly_purgeable_resources)); 276 277 // |origin3| has two registrations. 278 RegistrationData data4; 279 data4.registration_id = 456; 280 data4.scope = URL(origin3, "/fuga"); 281 data4.script = URL(origin3, "/script4.js"); 282 data4.version_id = 789; 283 ASSERT_EQ( 284 ServiceWorkerDatabase::STATUS_OK, 285 database->WriteRegistration( 286 data4, resources, &deleted_version_id, &newly_purgeable_resources)); 287 288 origins.clear(); 289 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 290 database->GetOriginsWithRegistrations(&origins)); 291 EXPECT_EQ(3U, origins.size()); 292 EXPECT_TRUE(ContainsKey(origins, origin1)); 293 EXPECT_TRUE(ContainsKey(origins, origin2)); 294 EXPECT_TRUE(ContainsKey(origins, origin3)); 295 296 // |origin3| has another registration, so should not remove it from the 297 // unique origin list. 298 int64 version_id; 299 ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, 300 database->DeleteRegistration(data4.registration_id, 301 origin3, 302 &version_id, 303 &newly_purgeable_resources)); 304 305 origins.clear(); 306 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 307 database->GetOriginsWithRegistrations(&origins)); 308 EXPECT_EQ(3U, origins.size()); 309 EXPECT_TRUE(ContainsKey(origins, origin1)); 310 EXPECT_TRUE(ContainsKey(origins, origin2)); 311 EXPECT_TRUE(ContainsKey(origins, origin3)); 312 313 // |origin3| should be removed from the unique origin list. 314 ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, 315 database->DeleteRegistration(data3.registration_id, 316 origin3, 317 &version_id, 318 &newly_purgeable_resources)); 319 320 origins.clear(); 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)); 326} 327 328TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) { 329 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 330 331 GURL origin1("http://example.com"); 332 GURL origin2("https://www.example.com"); 333 GURL origin3("https://example.org"); 334 335 std::vector<RegistrationData> registrations; 336 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 337 database->GetRegistrationsForOrigin(origin1, ®istrations)); 338 EXPECT_TRUE(registrations.empty()); 339 340 std::vector<Resource> resources; 341 int64 deleted_version_id; 342 std::vector<int64> newly_purgeable_resources; 343 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; 349 ASSERT_EQ( 350 ServiceWorkerDatabase::STATUS_OK, 351 database->WriteRegistration( 352 data1, resources, &deleted_version_id, &newly_purgeable_resources)); 353 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; 359 ASSERT_EQ( 360 ServiceWorkerDatabase::STATUS_OK, 361 database->WriteRegistration( 362 data2, resources, &deleted_version_id, &newly_purgeable_resources)); 363 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; 369 ASSERT_EQ( 370 ServiceWorkerDatabase::STATUS_OK, 371 database->WriteRegistration( 372 data3, resources, &deleted_version_id, &newly_purgeable_resources)); 373 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; 380 ASSERT_EQ( 381 ServiceWorkerDatabase::STATUS_OK, 382 database->WriteRegistration( 383 data4, resources, &deleted_version_id, &newly_purgeable_resources)); 384 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]); 391} 392 393TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) { 394 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 395 396 std::vector<RegistrationData> registrations; 397 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 398 database->GetAllRegistrations(®istrations)); 399 EXPECT_TRUE(registrations.empty()); 400 401 std::vector<Resource> resources; 402 int64 deleted_version_id; 403 std::vector<int64> newly_purgeable_resources; 404 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; 411 ASSERT_EQ( 412 ServiceWorkerDatabase::STATUS_OK, 413 database->WriteRegistration( 414 data1, resources, &deleted_version_id, &newly_purgeable_resources)); 415 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; 422 ASSERT_EQ( 423 ServiceWorkerDatabase::STATUS_OK, 424 database->WriteRegistration( 425 data2, resources, &deleted_version_id, &newly_purgeable_resources)); 426 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; 433 ASSERT_EQ( 434 ServiceWorkerDatabase::STATUS_OK, 435 database->WriteRegistration( 436 data3, resources, &deleted_version_id, &newly_purgeable_resources)); 437 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; 444 ASSERT_EQ( 445 ServiceWorkerDatabase::STATUS_OK, 446 database->WriteRegistration( 447 data4, resources, &deleted_version_id, &newly_purgeable_resources)); 448 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]); 457} 458 459TEST(ServiceWorkerDatabaseTest, Registration_Basic) { 460 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 461 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 469 std::vector<Resource> resources; 470 resources.push_back(CreateResource(1, URL(origin, "/resource1"))); 471 resources.push_back(CreateResource(2, URL(origin, "/resource2"))); 472 473 // Write a resource to the uncommitted list to make sure that writing 474 // registration removes resource ids associated with the registration from 475 // the uncommitted list. 476 std::set<int64> uncommitted_ids; 477 uncommitted_ids.insert(resources[0].resource_id); 478 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 479 database->WriteUncommittedResourceIds(uncommitted_ids)); 480 std::set<int64> uncommitted_ids_out; 481 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 482 database->GetUncommittedResourceIds(&uncommitted_ids_out)); 483 EXPECT_EQ(uncommitted_ids, uncommitted_ids_out); 484 485 int64 deleted_version_id = 222; // Dummy initial value 486 std::vector<int64> newly_purgeable_resources; 487 488 EXPECT_EQ( 489 ServiceWorkerDatabase::STATUS_OK, 490 database->WriteRegistration( 491 data, resources, &deleted_version_id, &newly_purgeable_resources)); 492 EXPECT_EQ(kInvalidServiceWorkerVersionId, deleted_version_id); 493 EXPECT_TRUE(newly_purgeable_resources.empty()); 494 495 // Make sure that the registration and resource records are stored. 496 RegistrationData data_out; 497 std::vector<Resource> resources_out; 498 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 499 database->ReadRegistration( 500 data.registration_id, origin, &data_out, &resources_out)); 501 VerifyRegistrationData(data, data_out); 502 VerifyResourceRecords(resources, resources_out); 503 504 // Make sure that the resource is removed from the uncommitted list. 505 uncommitted_ids_out.clear(); 506 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 507 database->GetUncommittedResourceIds(&uncommitted_ids_out)); 508 EXPECT_TRUE(uncommitted_ids_out.empty()); 509 510 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 511 database->DeleteRegistration(data.registration_id, 512 origin, 513 &deleted_version_id, 514 &newly_purgeable_resources)); 515 EXPECT_EQ(data.version_id, deleted_version_id); 516 ASSERT_EQ(resources.size(), newly_purgeable_resources.size()); 517 for (size_t i = 0; i < resources.size(); ++i) 518 EXPECT_EQ(newly_purgeable_resources[i], resources[i].resource_id); 519 520 // Make sure that the registration and resource records are gone. 521 resources_out.clear(); 522 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, 523 database->ReadRegistration( 524 data.registration_id, origin, &data_out, &resources_out)); 525 EXPECT_TRUE(resources_out.empty()); 526 527 // Resources should be purgeable because these are no longer referred. 528 std::set<int64> purgeable_ids_out; 529 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 530 database->GetPurgeableResourceIds(&purgeable_ids_out)); 531 EXPECT_EQ(2u, purgeable_ids_out.size()); 532 EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources[0].resource_id)); 533 EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources[1].resource_id)); 534} 535 536TEST(ServiceWorkerDatabaseTest, DeleteNonExistentRegistration) { 537 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 538 539 GURL origin("http://example.com"); 540 RegistrationData data; 541 data.registration_id = 100; 542 data.scope = URL(origin, "/foo"); 543 data.script = URL(origin, "/script.js"); 544 data.version_id = 200; 545 546 std::vector<Resource> resources; 547 resources.push_back(CreateResource(1, URL(origin, "/resource1"))); 548 resources.push_back(CreateResource(2, URL(origin, "/resource2"))); 549 550 const int64 kNonExistentRegistrationId = 999; 551 const int64 kArbitraryVersionId = 222; // Used as a dummy initial value 552 553 int64 deleted_version_id = kArbitraryVersionId; 554 std::vector<int64> newly_purgeable_resources; 555 EXPECT_EQ( 556 ServiceWorkerDatabase::STATUS_OK, 557 database->WriteRegistration( 558 data, resources, &deleted_version_id, &newly_purgeable_resources)); 559 EXPECT_EQ(kInvalidServiceWorkerVersionId, deleted_version_id); 560 EXPECT_TRUE(newly_purgeable_resources.empty()); 561 562 // Delete from an origin that has a registration. 563 deleted_version_id = kArbitraryVersionId; 564 newly_purgeable_resources.clear(); 565 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 566 database->DeleteRegistration(kNonExistentRegistrationId, 567 origin, 568 &deleted_version_id, 569 &newly_purgeable_resources)); 570 EXPECT_EQ(kInvalidServiceWorkerVersionId, deleted_version_id); 571 EXPECT_TRUE(newly_purgeable_resources.empty()); 572 573 // Delete from an origin that has no registration. 574 deleted_version_id = kArbitraryVersionId; 575 newly_purgeable_resources.clear(); 576 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 577 database->DeleteRegistration(kNonExistentRegistrationId, 578 GURL("http://example.net"), 579 &deleted_version_id, 580 &newly_purgeable_resources)); 581 EXPECT_EQ(kInvalidServiceWorkerVersionId, deleted_version_id); 582 EXPECT_TRUE(newly_purgeable_resources.empty()); 583} 584 585TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) { 586 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 587 588 GURL origin("http://example.com"); 589 RegistrationData data; 590 data.registration_id = 100; 591 data.scope = URL(origin, "/foo"); 592 data.script = URL(origin, "/script.js"); 593 data.version_id = 200; 594 595 std::vector<Resource> resources1; 596 resources1.push_back(CreateResource(1, URL(origin, "/resource1"))); 597 resources1.push_back(CreateResource(2, URL(origin, "/resource2"))); 598 599 int64 deleted_version_id = 222; // Dummy inital value 600 std::vector<int64> newly_purgeable_resources; 601 602 EXPECT_EQ( 603 ServiceWorkerDatabase::STATUS_OK, 604 database->WriteRegistration( 605 data, resources1, &deleted_version_id, &newly_purgeable_resources)); 606 EXPECT_EQ(kInvalidServiceWorkerVersionId, deleted_version_id); 607 EXPECT_TRUE(newly_purgeable_resources.empty()); 608 609 // Make sure that the registration and resource records are stored. 610 RegistrationData data_out; 611 std::vector<Resource> resources_out; 612 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( 613 data.registration_id, origin, &data_out, &resources_out)); 614 VerifyRegistrationData(data, data_out); 615 VerifyResourceRecords(resources1, resources_out); 616 617 // Update the registration. 618 RegistrationData updated_data = data; 619 updated_data.version_id = data.version_id + 1; 620 std::vector<Resource> resources2; 621 resources2.push_back(CreateResource(3, URL(origin, "/resource3"))); 622 resources2.push_back(CreateResource(4, URL(origin, "/resource4"))); 623 624 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 625 database->WriteRegistration(updated_data, 626 resources2, 627 &deleted_version_id, 628 &newly_purgeable_resources)); 629 EXPECT_EQ(data.version_id, deleted_version_id); 630 ASSERT_EQ(resources1.size(), newly_purgeable_resources.size()); 631 for (size_t i = 0; i < resources1.size(); ++i) 632 EXPECT_EQ(newly_purgeable_resources[i], resources1[i].resource_id); 633 634 // Make sure that |updated_data| is stored and resources referred from |data| 635 // is moved to the purgeable list. 636 resources_out.clear(); 637 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( 638 updated_data.registration_id, origin, &data_out, &resources_out)); 639 VerifyRegistrationData(updated_data, data_out); 640 VerifyResourceRecords(resources2, resources_out); 641 642 std::set<int64> purgeable_ids_out; 643 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 644 database->GetPurgeableResourceIds(&purgeable_ids_out)); 645 EXPECT_EQ(2u, purgeable_ids_out.size()); 646 EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources1[0].resource_id)); 647 EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources1[1].resource_id)); 648} 649 650TEST(ServiceWorkerDatabaseTest, Registration_Multiple) { 651 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 652 GURL origin("http://example.com"); 653 654 int64 deleted_version_id; 655 std::vector<int64> newly_purgeable_resources; 656 657 // Add registration1. 658 RegistrationData data1; 659 data1.registration_id = 100; 660 data1.scope = URL(origin, "/foo"); 661 data1.script = URL(origin, "/script1.js"); 662 data1.version_id = 200; 663 664 std::vector<Resource> resources1; 665 resources1.push_back(CreateResource(1, URL(origin, "/resource1"))); 666 resources1.push_back(CreateResource(2, URL(origin, "/resource2"))); 667 EXPECT_EQ( 668 ServiceWorkerDatabase::STATUS_OK, 669 database->WriteRegistration( 670 data1, resources1, &deleted_version_id, &newly_purgeable_resources)); 671 672 // Add registration2. 673 RegistrationData data2; 674 data2.registration_id = 101; 675 data2.scope = URL(origin, "/bar"); 676 data2.script = URL(origin, "/script2.js"); 677 data2.version_id = 201; 678 679 std::vector<Resource> resources2; 680 resources2.push_back(CreateResource(3, URL(origin, "/resource3"))); 681 resources2.push_back(CreateResource(4, URL(origin, "/resource4"))); 682 EXPECT_EQ( 683 ServiceWorkerDatabase::STATUS_OK, 684 database->WriteRegistration( 685 data2, resources2, &deleted_version_id, &newly_purgeable_resources)); 686 687 // Make sure that registration1 is stored. 688 RegistrationData data_out; 689 std::vector<Resource> resources_out; 690 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( 691 data1.registration_id, origin, &data_out, &resources_out)); 692 VerifyRegistrationData(data1, data_out); 693 VerifyResourceRecords(resources1, resources_out); 694 695 // Make sure that registration2 is also stored. 696 resources_out.clear(); 697 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( 698 data2.registration_id, origin, &data_out, &resources_out)); 699 VerifyRegistrationData(data2, data_out); 700 VerifyResourceRecords(resources2, resources_out); 701 702 std::set<int64> purgeable_ids_out; 703 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 704 database->GetPurgeableResourceIds(&purgeable_ids_out)); 705 EXPECT_TRUE(purgeable_ids_out.empty()); 706 707 // Delete registration1. 708 int64 version_id; 709 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 710 database->DeleteRegistration(data1.registration_id, 711 origin, 712 &version_id, 713 &newly_purgeable_resources)); 714 715 // Make sure that registration1 is gone. 716 resources_out.clear(); 717 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, 718 database->ReadRegistration( 719 data1.registration_id, origin, &data_out, &resources_out)); 720 EXPECT_TRUE(resources_out.empty()); 721 722 purgeable_ids_out.clear(); 723 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 724 database->GetPurgeableResourceIds(&purgeable_ids_out)); 725 EXPECT_EQ(2u, purgeable_ids_out.size()); 726 EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources1[0].resource_id)); 727 EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources1[1].resource_id)); 728 729 // Make sure that registration2 is still alive. 730 resources_out.clear(); 731 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( 732 data2.registration_id, origin, &data_out, &resources_out)); 733 VerifyRegistrationData(data2, data_out); 734 VerifyResourceRecords(resources2, resources_out); 735} 736 737TEST(ServiceWorkerDatabaseTest, UpdateVersionToActive) { 738 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 739 GURL origin("http://example.com"); 740 741 int64 deleted_version_id; 742 std::vector<int64> newly_purgeable_resources; 743 744 // Should be false because a registration does not exist. 745 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, 746 database->UpdateVersionToActive(0, origin)); 747 748 // Add a registration. 749 RegistrationData data; 750 data.registration_id = 100; 751 data.scope = URL(origin, "/foo"); 752 data.script = URL(origin, "/script.js"); 753 data.version_id = 200; 754 data.is_active = false; 755 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 756 database->WriteRegistration(data, 757 std::vector<Resource>(), 758 &deleted_version_id, 759 &newly_purgeable_resources)); 760 761 // Make sure that the registration is stored. 762 RegistrationData data_out; 763 std::vector<Resource> resources_out; 764 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 765 database->ReadRegistration( 766 data.registration_id, origin, &data_out, &resources_out)); 767 VerifyRegistrationData(data, data_out); 768 EXPECT_TRUE(resources_out.empty()); 769 770 // Activate the registration. 771 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 772 database->UpdateVersionToActive(data.registration_id, origin)); 773 774 // Make sure that the registration is activated. 775 resources_out.clear(); 776 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 777 database->ReadRegistration( 778 data.registration_id, origin, &data_out, &resources_out)); 779 RegistrationData expected_data = data; 780 expected_data.is_active = true; 781 VerifyRegistrationData(expected_data, data_out); 782 EXPECT_TRUE(resources_out.empty()); 783 784 // Delete the registration. 785 int64 version_id; 786 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 787 database->DeleteRegistration(data.registration_id, 788 origin, 789 &version_id, 790 &newly_purgeable_resources)); 791 792 // Should be false because the registration is gone. 793 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, 794 database->UpdateVersionToActive(data.registration_id, origin)); 795} 796 797TEST(ServiceWorkerDatabaseTest, UpdateLastCheckTime) { 798 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 799 GURL origin("http://example.com"); 800 int64 deleted_version_id; 801 std::vector<int64> newly_purgeable_resources; 802 803 // Should be false because a registration does not exist. 804 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, 805 database->UpdateLastCheckTime(0, origin, base::Time::Now())); 806 807 // Add a registration. 808 RegistrationData data; 809 data.registration_id = 100; 810 data.scope = URL(origin, "/foo"); 811 data.script = URL(origin, "/script.js"); 812 data.version_id = 200; 813 data.last_update_check = base::Time::Now(); 814 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 815 database->WriteRegistration(data, 816 std::vector<Resource>(), 817 &deleted_version_id, 818 &newly_purgeable_resources)); 819 820 // Make sure that the registration is stored. 821 RegistrationData data_out; 822 std::vector<Resource> resources_out; 823 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 824 database->ReadRegistration( 825 data.registration_id, origin, &data_out, &resources_out)); 826 VerifyRegistrationData(data, data_out); 827 EXPECT_TRUE(resources_out.empty()); 828 829 // Update the last check time. 830 base::Time updated_time = base::Time::Now(); 831 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 832 database->UpdateLastCheckTime( 833 data.registration_id, origin, updated_time)); 834 835 // Make sure that the registration is updated. 836 resources_out.clear(); 837 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 838 database->ReadRegistration( 839 data.registration_id, origin, &data_out, &resources_out)); 840 RegistrationData expected_data = data; 841 expected_data.last_update_check = updated_time; 842 VerifyRegistrationData(expected_data, data_out); 843 EXPECT_TRUE(resources_out.empty()); 844 845 // Delete the registration. 846 int64 version_id; 847 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 848 database->DeleteRegistration(data.registration_id, 849 origin, 850 &version_id, 851 &newly_purgeable_resources)); 852 853 // Should be false because the registration is gone. 854 EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, 855 database->UpdateLastCheckTime( 856 data.registration_id, origin, base::Time::Now())); 857} 858 859TEST(ServiceWorkerDatabaseTest, UncommittedResourceIds) { 860 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 861 862 // Write {1, 2, 3}. 863 std::set<int64> ids1; 864 ids1.insert(1); 865 ids1.insert(2); 866 ids1.insert(3); 867 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 868 database->WriteUncommittedResourceIds(ids1)); 869 870 std::set<int64> ids_out; 871 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 872 database->GetUncommittedResourceIds(&ids_out)); 873 EXPECT_EQ(ids1, ids_out); 874 875 // Write {2, 4}. 876 std::set<int64> ids2; 877 ids2.insert(2); 878 ids2.insert(4); 879 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 880 database->WriteUncommittedResourceIds(ids2)); 881 882 ids_out.clear(); 883 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 884 database->GetUncommittedResourceIds(&ids_out)); 885 std::set<int64> expected = base::STLSetUnion<std::set<int64> >(ids1, ids2); 886 EXPECT_EQ(expected, ids_out); 887 888 // Delete {2, 3}. 889 std::set<int64> ids3; 890 ids3.insert(2); 891 ids3.insert(3); 892 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 893 database->ClearUncommittedResourceIds(ids3)); 894 895 ids_out.clear(); 896 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 897 database->GetUncommittedResourceIds(&ids_out)); 898 expected = base::STLSetDifference<std::set<int64> >(expected, ids3); 899 EXPECT_EQ(expected, ids_out); 900} 901 902TEST(ServiceWorkerDatabaseTest, PurgeableResourceIds) { 903 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 904 905 // Write {1, 2, 3}. 906 std::set<int64> ids1; 907 ids1.insert(1); 908 ids1.insert(2); 909 ids1.insert(3); 910 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 911 database->WritePurgeableResourceIds(ids1)); 912 913 std::set<int64> ids_out; 914 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 915 database->GetPurgeableResourceIds(&ids_out)); 916 EXPECT_EQ(ids1, ids_out); 917 918 // Write {2, 4}. 919 std::set<int64> ids2; 920 ids2.insert(2); 921 ids2.insert(4); 922 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 923 database->WritePurgeableResourceIds(ids2)); 924 925 ids_out.clear(); 926 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 927 database->GetPurgeableResourceIds(&ids_out)); 928 std::set<int64> expected = base::STLSetUnion<std::set<int64> >(ids1, ids2); 929 EXPECT_EQ(expected, ids_out); 930 931 // Delete {2, 3}. 932 std::set<int64> ids3; 933 ids3.insert(2); 934 ids3.insert(3); 935 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 936 database->ClearPurgeableResourceIds(ids3)); 937 938 ids_out.clear(); 939 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 940 database->GetPurgeableResourceIds(&ids_out)); 941 expected = base::STLSetDifference<std::set<int64> >(expected, ids3); 942 EXPECT_EQ(expected, ids_out); 943} 944 945TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) { 946 scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); 947 int64 deleted_version_id; 948 std::vector<int64> newly_purgeable_resources; 949 950 // Data associated with |origin1| will be removed. 951 GURL origin1("http://example.com"); 952 GURL origin2("http://example.org"); 953 954 // |origin1| has two registrations. 955 RegistrationData data1; 956 data1.registration_id = 10; 957 data1.scope = URL(origin1, "/foo"); 958 data1.script = URL(origin1, "/script1.js"); 959 data1.version_id = 100; 960 961 std::vector<Resource> resources1; 962 resources1.push_back(CreateResource(1, URL(origin1, "/resource1"))); 963 resources1.push_back(CreateResource(2, URL(origin1, "/resource2"))); 964 ASSERT_EQ( 965 ServiceWorkerDatabase::STATUS_OK, 966 database->WriteRegistration( 967 data1, resources1, &deleted_version_id, &newly_purgeable_resources)); 968 969 RegistrationData data2; 970 data2.registration_id = 11; 971 data2.scope = URL(origin1, "/bar"); 972 data2.script = URL(origin1, "/script2.js"); 973 data2.version_id = 101; 974 975 std::vector<Resource> resources2; 976 resources2.push_back(CreateResource(3, URL(origin1, "/resource3"))); 977 resources2.push_back(CreateResource(4, URL(origin1, "/resource4"))); 978 ASSERT_EQ( 979 ServiceWorkerDatabase::STATUS_OK, 980 database->WriteRegistration( 981 data2, resources2, &deleted_version_id, &newly_purgeable_resources)); 982 983 // |origin2| has one registration. 984 RegistrationData data3; 985 data3.registration_id = 12; 986 data3.scope = URL(origin2, "/hoge"); 987 data3.script = URL(origin2, "/script3.js"); 988 data3.version_id = 102; 989 990 std::vector<Resource> resources3; 991 resources3.push_back(CreateResource(5, URL(origin2, "/resource5"))); 992 resources3.push_back(CreateResource(6, URL(origin2, "/resource6"))); 993 ASSERT_EQ( 994 ServiceWorkerDatabase::STATUS_OK, 995 database->WriteRegistration( 996 data3, resources3, &deleted_version_id, &newly_purgeable_resources)); 997 998 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 999 database->DeleteAllDataForOrigin(origin1, 1000 &newly_purgeable_resources)); 1001 1002 // |origin1| should be removed from the unique origin list. 1003 std::set<GURL> unique_origins; 1004 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 1005 database->GetOriginsWithRegistrations(&unique_origins)); 1006 EXPECT_EQ(1u, unique_origins.size()); 1007 EXPECT_TRUE(ContainsKey(unique_origins, origin2)); 1008 1009 // The registrations for |origin1| should be removed. 1010 std::vector<RegistrationData> registrations; 1011 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 1012 database->GetRegistrationsForOrigin(origin1, ®istrations)); 1013 EXPECT_TRUE(registrations.empty()); 1014 1015 // The registration for |origin2| should not be removed. 1016 RegistrationData data_out; 1017 std::vector<Resource> resources_out; 1018 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( 1019 data3.registration_id, origin2, &data_out, &resources_out)); 1020 VerifyRegistrationData(data3, data_out); 1021 VerifyResourceRecords(resources3, resources_out); 1022 1023 // The resources associated with |origin1| should be purgeable. 1024 std::set<int64> purgeable_ids_out; 1025 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 1026 database->GetPurgeableResourceIds(&purgeable_ids_out)); 1027 EXPECT_EQ(4u, purgeable_ids_out.size()); 1028 EXPECT_TRUE(ContainsKey(purgeable_ids_out, 1)); 1029 EXPECT_TRUE(ContainsKey(purgeable_ids_out, 2)); 1030 EXPECT_TRUE(ContainsKey(purgeable_ids_out, 3)); 1031 EXPECT_TRUE(ContainsKey(purgeable_ids_out, 4)); 1032} 1033 1034TEST(ServiceWorkerDatabaseTest, DestroyDatabase) { 1035 base::ScopedTempDir database_dir; 1036 ASSERT_TRUE(database_dir.CreateUniqueTempDir()); 1037 scoped_ptr<ServiceWorkerDatabase> database( 1038 CreateDatabase(database_dir.path())); 1039 1040 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true)); 1041 ASSERT_TRUE(base::DirectoryExists(database_dir.path())); 1042 1043 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->DestroyDatabase()); 1044 ASSERT_FALSE(base::DirectoryExists(database_dir.path())); 1045} 1046 1047} // namespace content 1048