| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/service_worker/service_worker_database.h" |
| |
| #include <string> |
| |
| #include "base/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/stl_util.h" |
| #include "content/browser/service_worker/service_worker_database.pb.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| typedef ServiceWorkerDatabase::RegistrationData RegistrationData; |
| typedef ServiceWorkerDatabase::ResourceRecord Resource; |
| |
| struct AvailableIds { |
| int64 reg_id; |
| int64 res_id; |
| int64 ver_id; |
| |
| AvailableIds() : reg_id(-1), res_id(-1), ver_id(-1) {} |
| ~AvailableIds() {} |
| }; |
| |
| GURL URL(const GURL& origin, const std::string& path) { |
| EXPECT_TRUE(origin.is_valid()); |
| EXPECT_EQ(origin, origin.GetOrigin()); |
| GURL out(origin.spec() + path); |
| EXPECT_TRUE(out.is_valid()); |
| return out; |
| } |
| |
| Resource CreateResource(int64 resource_id, const GURL& url) { |
| EXPECT_TRUE(url.is_valid()); |
| Resource resource; |
| resource.resource_id = resource_id; |
| resource.url = url; |
| return resource; |
| } |
| |
| ServiceWorkerDatabase* CreateDatabase(const base::FilePath& path) { |
| return new ServiceWorkerDatabase(path); |
| } |
| |
| ServiceWorkerDatabase* CreateDatabaseInMemory() { |
| return new ServiceWorkerDatabase(base::FilePath()); |
| } |
| |
| void VerifyRegistrationData(const RegistrationData& expected, |
| const RegistrationData& actual) { |
| EXPECT_EQ(expected.registration_id, actual.registration_id); |
| EXPECT_EQ(expected.scope, actual.scope); |
| EXPECT_EQ(expected.script, actual.script); |
| EXPECT_EQ(expected.version_id, actual.version_id); |
| EXPECT_EQ(expected.is_active, actual.is_active); |
| EXPECT_EQ(expected.has_fetch_handler, actual.has_fetch_handler); |
| EXPECT_EQ(expected.last_update_check, actual.last_update_check); |
| } |
| |
| void VerifyResourceRecords(const std::vector<Resource>& expected, |
| const std::vector<Resource>& actual) { |
| ASSERT_EQ(expected.size(), actual.size()); |
| for (size_t i = 0; i < expected.size(); ++i) { |
| EXPECT_EQ(expected[i].resource_id, actual[i].resource_id); |
| EXPECT_EQ(expected[i].url, actual[i].url); |
| } |
| } |
| |
| } // namespace |
| |
| TEST(ServiceWorkerDatabaseTest, OpenDatabase) { |
| base::ScopedTempDir database_dir; |
| ASSERT_TRUE(database_dir.CreateUniqueTempDir()); |
| scoped_ptr<ServiceWorkerDatabase> database( |
| CreateDatabase(database_dir.path())); |
| |
| // Should be false because the database does not exist at the path. |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, |
| database->LazyOpen(false)); |
| |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true)); |
| |
| database.reset(CreateDatabase(database_dir.path())); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(false)); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, OpenDatabase_InMemory) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| |
| // Should be false because the database does not exist in memory. |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, |
| database->LazyOpen(false)); |
| |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true)); |
| database.reset(CreateDatabaseInMemory()); |
| |
| // Should be false because the database is not persistent. |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, |
| database->LazyOpen(false)); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, DatabaseVersion) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true)); |
| |
| // Opening a new database does not write anything, so its schema version |
| // should be 0. |
| int64 db_version = -1; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->ReadDatabaseVersion(&db_version)); |
| EXPECT_EQ(0u, db_version); |
| |
| // First writing triggers database initialization and bumps the schema |
| // version. |
| std::vector<ServiceWorkerDatabase::ResourceRecord> resources; |
| std::vector<int64> newly_purgeable_resources; |
| ServiceWorkerDatabase::RegistrationData data; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data, resources, |
| &newly_purgeable_resources)); |
| |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->ReadDatabaseVersion(&db_version)); |
| EXPECT_LT(0, db_version); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, GetNextAvailableIds) { |
| base::ScopedTempDir database_dir; |
| ASSERT_TRUE(database_dir.CreateUniqueTempDir()); |
| scoped_ptr<ServiceWorkerDatabase> database( |
| CreateDatabase(database_dir.path())); |
| |
| GURL origin("http://example.com"); |
| |
| // The database has never been used, so returns initial values. |
| AvailableIds ids; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds( |
| &ids.reg_id, &ids.ver_id, &ids.res_id)); |
| EXPECT_EQ(0, ids.reg_id); |
| EXPECT_EQ(0, ids.ver_id); |
| EXPECT_EQ(0, ids.res_id); |
| |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true)); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds( |
| &ids.reg_id, &ids.ver_id, &ids.res_id)); |
| EXPECT_EQ(0, ids.reg_id); |
| EXPECT_EQ(0, ids.ver_id); |
| EXPECT_EQ(0, ids.res_id); |
| |
| // Writing a registration bumps the next available ids. |
| std::vector<Resource> resources; |
| RegistrationData data1; |
| std::vector<int64> newly_purgeable_resources; |
| data1.registration_id = 100; |
| data1.scope = URL(origin, "/foo"); |
| data1.script = URL(origin, "/script1.js"); |
| data1.version_id = 200; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data1, resources, |
| &newly_purgeable_resources)); |
| |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds( |
| &ids.reg_id, &ids.ver_id, &ids.res_id)); |
| EXPECT_EQ(101, ids.reg_id); |
| EXPECT_EQ(201, ids.ver_id); |
| EXPECT_EQ(0, ids.res_id); |
| |
| // Writing a registration whose ids are lower than the stored ones should not |
| // bump the next available ids. |
| RegistrationData data2; |
| data2.registration_id = 10; |
| data2.scope = URL(origin, "/bar"); |
| data2.script = URL(origin, "/script2.js"); |
| data2.version_id = 20; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data2, resources, |
| &newly_purgeable_resources)); |
| |
| // Close and reopen the database to verify the stored values. |
| database.reset(CreateDatabase(database_dir.path())); |
| |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds( |
| &ids.reg_id, &ids.ver_id, &ids.res_id)); |
| EXPECT_EQ(101, ids.reg_id); |
| EXPECT_EQ(201, ids.ver_id); |
| EXPECT_EQ(0, ids.res_id); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| |
| std::set<GURL> origins; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetOriginsWithRegistrations(&origins)); |
| EXPECT_TRUE(origins.empty()); |
| |
| std::vector<Resource> resources; |
| std::vector<int64> newly_purgeable_resources; |
| |
| GURL origin1("http://example.com"); |
| RegistrationData data1; |
| data1.registration_id = 123; |
| data1.scope = URL(origin1, "/foo"); |
| data1.script = URL(origin1, "/script1.js"); |
| data1.version_id = 456; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data1, resources, |
| &newly_purgeable_resources)); |
| |
| GURL origin2("https://www.example.com"); |
| RegistrationData data2; |
| data2.registration_id = 234; |
| data2.scope = URL(origin2, "/bar"); |
| data2.script = URL(origin2, "/script2.js"); |
| data2.version_id = 567; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data2, resources, |
| &newly_purgeable_resources)); |
| |
| GURL origin3("https://example.org"); |
| RegistrationData data3; |
| data3.registration_id = 345; |
| data3.scope = URL(origin3, "/hoge"); |
| data3.script = URL(origin3, "/script3.js"); |
| data3.version_id = 678; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data3, resources, |
| &newly_purgeable_resources)); |
| |
| // |origin3| has two registrations. |
| RegistrationData data4; |
| data4.registration_id = 456; |
| data4.scope = URL(origin3, "/fuga"); |
| data4.script = URL(origin3, "/script4.js"); |
| data4.version_id = 789; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data4, resources, |
| &newly_purgeable_resources)); |
| |
| origins.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetOriginsWithRegistrations(&origins)); |
| EXPECT_EQ(3U, origins.size()); |
| EXPECT_TRUE(ContainsKey(origins, origin1)); |
| EXPECT_TRUE(ContainsKey(origins, origin2)); |
| EXPECT_TRUE(ContainsKey(origins, origin3)); |
| |
| // |origin3| has another registration, so should not remove it from the |
| // unique origin list. |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->DeleteRegistration(data4.registration_id, origin3, |
| &newly_purgeable_resources)); |
| |
| origins.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetOriginsWithRegistrations(&origins)); |
| EXPECT_EQ(3U, origins.size()); |
| EXPECT_TRUE(ContainsKey(origins, origin1)); |
| EXPECT_TRUE(ContainsKey(origins, origin2)); |
| EXPECT_TRUE(ContainsKey(origins, origin3)); |
| |
| // |origin3| should be removed from the unique origin list. |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->DeleteRegistration(data3.registration_id, origin3, |
| &newly_purgeable_resources)); |
| |
| origins.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetOriginsWithRegistrations(&origins)); |
| EXPECT_EQ(2U, origins.size()); |
| EXPECT_TRUE(ContainsKey(origins, origin1)); |
| EXPECT_TRUE(ContainsKey(origins, origin2)); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| |
| GURL origin1("http://example.com"); |
| GURL origin2("https://www.example.com"); |
| GURL origin3("https://example.org"); |
| |
| std::vector<RegistrationData> registrations; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetRegistrationsForOrigin(origin1, ®istrations)); |
| EXPECT_TRUE(registrations.empty()); |
| |
| std::vector<Resource> resources; |
| std::vector<int64> newly_purgeable_resources; |
| |
| RegistrationData data1; |
| data1.registration_id = 100; |
| data1.scope = URL(origin1, "/foo"); |
| data1.script = URL(origin1, "/script1.js"); |
| data1.version_id = 1000; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data1, resources, |
| &newly_purgeable_resources)); |
| |
| RegistrationData data2; |
| data2.registration_id = 200; |
| data2.scope = URL(origin2, "/bar"); |
| data2.script = URL(origin2, "/script2.js"); |
| data2.version_id = 2000; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data2, resources, |
| &newly_purgeable_resources)); |
| |
| RegistrationData data3; |
| data3.registration_id = 300; |
| data3.scope = URL(origin3, "/hoge"); |
| data3.script = URL(origin3, "/script3.js"); |
| data3.version_id = 3000; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data3, resources, |
| &newly_purgeable_resources)); |
| |
| // |origin3| has two registrations. |
| RegistrationData data4; |
| data4.registration_id = 400; |
| data4.scope = URL(origin3, "/fuga"); |
| data4.script = URL(origin3, "/script4.js"); |
| data4.version_id = 4000; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data4, resources, |
| &newly_purgeable_resources)); |
| |
| registrations.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetRegistrationsForOrigin(origin3, ®istrations)); |
| EXPECT_EQ(2U, registrations.size()); |
| VerifyRegistrationData(data3, registrations[0]); |
| VerifyRegistrationData(data4, registrations[1]); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| |
| std::vector<RegistrationData> registrations; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetAllRegistrations(®istrations)); |
| EXPECT_TRUE(registrations.empty()); |
| |
| std::vector<Resource> resources; |
| std::vector<int64> newly_purgeable_resources; |
| |
| GURL origin1("http://www1.example.com"); |
| RegistrationData data1; |
| data1.registration_id = 100; |
| data1.scope = URL(origin1, "/foo"); |
| data1.script = URL(origin1, "/script1.js"); |
| data1.version_id = 1000; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data1, resources, |
| &newly_purgeable_resources)); |
| |
| GURL origin2("http://www2.example.com"); |
| RegistrationData data2; |
| data2.registration_id = 200; |
| data2.scope = URL(origin2, "/bar"); |
| data2.script = URL(origin2, "/script2.js"); |
| data2.version_id = 2000; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data2, resources, |
| &newly_purgeable_resources)); |
| |
| GURL origin3("http://www3.example.com"); |
| RegistrationData data3; |
| data3.registration_id = 300; |
| data3.scope = URL(origin3, "/hoge"); |
| data3.script = URL(origin3, "/script3.js"); |
| data3.version_id = 3000; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data3, resources, |
| &newly_purgeable_resources)); |
| |
| // |origin3| has two registrations. |
| RegistrationData data4; |
| data4.registration_id = 400; |
| data4.scope = URL(origin3, "/fuga"); |
| data4.script = URL(origin3, "/script4.js"); |
| data4.version_id = 4000; |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data4, resources, |
| &newly_purgeable_resources)); |
| |
| registrations.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetAllRegistrations(®istrations)); |
| EXPECT_EQ(4U, registrations.size()); |
| VerifyRegistrationData(data1, registrations[0]); |
| VerifyRegistrationData(data2, registrations[1]); |
| VerifyRegistrationData(data3, registrations[2]); |
| VerifyRegistrationData(data4, registrations[3]); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, Registration_Basic) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| |
| GURL origin("http://example.com"); |
| RegistrationData data; |
| data.registration_id = 100; |
| data.scope = URL(origin, "/foo"); |
| data.script = URL(origin, "/script.js"); |
| data.version_id = 200; |
| |
| std::vector<Resource> resources; |
| resources.push_back(CreateResource(1, URL(origin, "/resource1"))); |
| resources.push_back(CreateResource(2, URL(origin, "/resource2"))); |
| |
| // Write a resource to the uncommitted list to make sure that writing |
| // registration removes resource ids associated with the registration from |
| // the uncommitted list. |
| std::set<int64> uncommitted_ids; |
| uncommitted_ids.insert(resources[0].resource_id); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteUncommittedResourceIds(uncommitted_ids)); |
| std::set<int64> uncommitted_ids_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetUncommittedResourceIds(&uncommitted_ids_out)); |
| EXPECT_EQ(uncommitted_ids, uncommitted_ids_out); |
| |
| std::vector<int64> newly_purgeable_resources; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data, resources, |
| &newly_purgeable_resources)); |
| |
| // Make sure that the registration and resource records are stored. |
| RegistrationData data_out; |
| std::vector<Resource> resources_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->ReadRegistration( |
| data.registration_id, origin, &data_out, &resources_out)); |
| VerifyRegistrationData(data, data_out); |
| VerifyResourceRecords(resources, resources_out); |
| |
| // Make sure that the resource is removed from the uncommitted list. |
| uncommitted_ids_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetUncommittedResourceIds(&uncommitted_ids_out)); |
| EXPECT_TRUE(uncommitted_ids_out.empty()); |
| |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->DeleteRegistration(data.registration_id, origin, |
| &newly_purgeable_resources)); |
| ASSERT_EQ(resources.size(), newly_purgeable_resources.size()); |
| for (size_t i = 0; i < resources.size(); ++i) |
| EXPECT_EQ(newly_purgeable_resources[i], resources[i].resource_id); |
| |
| // Make sure that the registration and resource records are gone. |
| resources_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, |
| database->ReadRegistration( |
| data.registration_id, origin, &data_out, &resources_out)); |
| EXPECT_TRUE(resources_out.empty()); |
| |
| // Resources should be purgeable because these are no longer referred. |
| std::set<int64> purgeable_ids_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetPurgeableResourceIds(&purgeable_ids_out)); |
| EXPECT_EQ(2u, purgeable_ids_out.size()); |
| EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources[0].resource_id)); |
| EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources[1].resource_id)); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| |
| GURL origin("http://example.com"); |
| RegistrationData data; |
| data.registration_id = 100; |
| data.scope = URL(origin, "/foo"); |
| data.script = URL(origin, "/script.js"); |
| data.version_id = 200; |
| |
| std::vector<Resource> resources1; |
| resources1.push_back(CreateResource(1, URL(origin, "/resource1"))); |
| resources1.push_back(CreateResource(2, URL(origin, "/resource2"))); |
| std::vector<int64> newly_purgeable_resources; |
| |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data, resources1, |
| &newly_purgeable_resources)); |
| EXPECT_TRUE(newly_purgeable_resources.empty()); |
| |
| // Make sure that the registration and resource records are stored. |
| RegistrationData data_out; |
| std::vector<Resource> resources_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( |
| data.registration_id, origin, &data_out, &resources_out)); |
| VerifyRegistrationData(data, data_out); |
| VerifyResourceRecords(resources1, resources_out); |
| |
| // Update the registration. |
| RegistrationData updated_data = data; |
| updated_data.version_id = data.version_id + 1; |
| std::vector<Resource> resources2; |
| resources2.push_back(CreateResource(3, URL(origin, "/resource3"))); |
| resources2.push_back(CreateResource(4, URL(origin, "/resource4"))); |
| |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(updated_data, resources2, |
| &newly_purgeable_resources)); |
| ASSERT_EQ(resources1.size(), newly_purgeable_resources.size()); |
| for(size_t i = 0; i < resources1.size(); ++i) |
| EXPECT_EQ(newly_purgeable_resources[i], resources1[i].resource_id); |
| |
| // Make sure that |updated_data| is stored and resources referred from |data| |
| // is moved to the purgeable list. |
| resources_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( |
| updated_data.registration_id, origin, &data_out, &resources_out)); |
| VerifyRegistrationData(updated_data, data_out); |
| VerifyResourceRecords(resources2, resources_out); |
| |
| std::set<int64> purgeable_ids_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetPurgeableResourceIds(&purgeable_ids_out)); |
| EXPECT_EQ(2u, purgeable_ids_out.size()); |
| EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources1[0].resource_id)); |
| EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources1[1].resource_id)); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, Registration_Multiple) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| GURL origin("http://example.com"); |
| |
| std::vector<int64> newly_purgeable_resources; |
| |
| // Add registration1. |
| RegistrationData data1; |
| data1.registration_id = 100; |
| data1.scope = URL(origin, "/foo"); |
| data1.script = URL(origin, "/script1.js"); |
| data1.version_id = 200; |
| |
| std::vector<Resource> resources1; |
| resources1.push_back(CreateResource(1, URL(origin, "/resource1"))); |
| resources1.push_back(CreateResource(2, URL(origin, "/resource2"))); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data1, resources1, |
| &newly_purgeable_resources)); |
| |
| // Add registration2. |
| RegistrationData data2; |
| data2.registration_id = 101; |
| data2.scope = URL(origin, "/bar"); |
| data2.script = URL(origin, "/script2.js"); |
| data2.version_id = 201; |
| |
| std::vector<Resource> resources2; |
| resources2.push_back(CreateResource(3, URL(origin, "/resource3"))); |
| resources2.push_back(CreateResource(4, URL(origin, "/resource4"))); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data2, resources2, |
| &newly_purgeable_resources)); |
| |
| // Make sure that registration1 is stored. |
| RegistrationData data_out; |
| std::vector<Resource> resources_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( |
| data1.registration_id, origin, &data_out, &resources_out)); |
| VerifyRegistrationData(data1, data_out); |
| VerifyResourceRecords(resources1, resources_out); |
| |
| // Make sure that registration2 is also stored. |
| resources_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( |
| data2.registration_id, origin, &data_out, &resources_out)); |
| VerifyRegistrationData(data2, data_out); |
| VerifyResourceRecords(resources2, resources_out); |
| |
| std::set<int64> purgeable_ids_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetPurgeableResourceIds(&purgeable_ids_out)); |
| EXPECT_TRUE(purgeable_ids_out.empty()); |
| |
| // Delete registration1. |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->DeleteRegistration(data1.registration_id, origin, |
| &newly_purgeable_resources)); |
| |
| // Make sure that registration1 is gone. |
| resources_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, |
| database->ReadRegistration( |
| data1.registration_id, origin, &data_out, &resources_out)); |
| EXPECT_TRUE(resources_out.empty()); |
| |
| purgeable_ids_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetPurgeableResourceIds(&purgeable_ids_out)); |
| EXPECT_EQ(2u, purgeable_ids_out.size()); |
| EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources1[0].resource_id)); |
| EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources1[1].resource_id)); |
| |
| // Make sure that registration2 is still alive. |
| resources_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( |
| data2.registration_id, origin, &data_out, &resources_out)); |
| VerifyRegistrationData(data2, data_out); |
| VerifyResourceRecords(resources2, resources_out); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, UpdateVersionToActive) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| GURL origin("http://example.com"); |
| |
| std::vector<int64> newly_purgeable_resources; |
| |
| // Should be false because a registration does not exist. |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, |
| database->UpdateVersionToActive(0, origin)); |
| |
| // Add a registration. |
| RegistrationData data; |
| data.registration_id = 100; |
| data.scope = URL(origin, "/foo"); |
| data.script = URL(origin, "/script.js"); |
| data.version_id = 200; |
| data.is_active = false; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data, std::vector<Resource>(), |
| &newly_purgeable_resources)); |
| |
| // Make sure that the registration is stored. |
| RegistrationData data_out; |
| std::vector<Resource> resources_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->ReadRegistration( |
| data.registration_id, origin, &data_out, &resources_out)); |
| VerifyRegistrationData(data, data_out); |
| EXPECT_TRUE(resources_out.empty()); |
| |
| // Activate the registration. |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->UpdateVersionToActive(data.registration_id, origin)); |
| |
| // Make sure that the registration is activated. |
| resources_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->ReadRegistration( |
| data.registration_id, origin, &data_out, &resources_out)); |
| RegistrationData expected_data = data; |
| expected_data.is_active = true; |
| VerifyRegistrationData(expected_data, data_out); |
| EXPECT_TRUE(resources_out.empty()); |
| |
| // Delete the registration. |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->DeleteRegistration(data.registration_id, origin, |
| &newly_purgeable_resources)); |
| |
| // Should be false because the registration is gone. |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, |
| database->UpdateVersionToActive(data.registration_id, origin)); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, UpdateLastCheckTime) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| GURL origin("http://example.com"); |
| std::vector<int64> newly_purgeable_resources; |
| |
| // Should be false because a registration does not exist. |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, |
| database->UpdateLastCheckTime(0, origin, base::Time::Now())); |
| |
| // Add a registration. |
| RegistrationData data; |
| data.registration_id = 100; |
| data.scope = URL(origin, "/foo"); |
| data.script = URL(origin, "/script.js"); |
| data.version_id = 200; |
| data.last_update_check = base::Time::Now(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data, std::vector<Resource>(), |
| &newly_purgeable_resources)); |
| |
| // Make sure that the registration is stored. |
| RegistrationData data_out; |
| std::vector<Resource> resources_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->ReadRegistration( |
| data.registration_id, origin, &data_out, &resources_out)); |
| VerifyRegistrationData(data, data_out); |
| EXPECT_TRUE(resources_out.empty()); |
| |
| // Update the last check time. |
| base::Time updated_time = base::Time::Now(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->UpdateLastCheckTime( |
| data.registration_id, origin, updated_time)); |
| |
| // Make sure that the registration is updated. |
| resources_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->ReadRegistration( |
| data.registration_id, origin, &data_out, &resources_out)); |
| RegistrationData expected_data = data; |
| expected_data.last_update_check = updated_time; |
| VerifyRegistrationData(expected_data, data_out); |
| EXPECT_TRUE(resources_out.empty()); |
| |
| // Delete the registration. |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->DeleteRegistration(data.registration_id, origin, |
| &newly_purgeable_resources)); |
| |
| // Should be false because the registration is gone. |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND, |
| database->UpdateLastCheckTime( |
| data.registration_id, origin, base::Time::Now())); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, UncommittedResourceIds) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| |
| // Write {1, 2, 3}. |
| std::set<int64> ids1; |
| ids1.insert(1); |
| ids1.insert(2); |
| ids1.insert(3); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteUncommittedResourceIds(ids1)); |
| |
| std::set<int64> ids_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetUncommittedResourceIds(&ids_out)); |
| EXPECT_EQ(ids1, ids_out); |
| |
| // Write {2, 4}. |
| std::set<int64> ids2; |
| ids2.insert(2); |
| ids2.insert(4); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteUncommittedResourceIds(ids2)); |
| |
| ids_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetUncommittedResourceIds(&ids_out)); |
| std::set<int64> expected = base::STLSetUnion<std::set<int64> >(ids1, ids2); |
| EXPECT_EQ(expected, ids_out); |
| |
| // Delete {2, 3}. |
| std::set<int64> ids3; |
| ids3.insert(2); |
| ids3.insert(3); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->ClearUncommittedResourceIds(ids3)); |
| |
| ids_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetUncommittedResourceIds(&ids_out)); |
| expected = base::STLSetDifference<std::set<int64> >(expected, ids3); |
| EXPECT_EQ(expected, ids_out); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, PurgeableResourceIds) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| |
| // Write {1, 2, 3}. |
| std::set<int64> ids1; |
| ids1.insert(1); |
| ids1.insert(2); |
| ids1.insert(3); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WritePurgeableResourceIds(ids1)); |
| |
| std::set<int64> ids_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetPurgeableResourceIds(&ids_out)); |
| EXPECT_EQ(ids1, ids_out); |
| |
| // Write {2, 4}. |
| std::set<int64> ids2; |
| ids2.insert(2); |
| ids2.insert(4); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WritePurgeableResourceIds(ids2)); |
| |
| ids_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetPurgeableResourceIds(&ids_out)); |
| std::set<int64> expected = base::STLSetUnion<std::set<int64> >(ids1, ids2); |
| EXPECT_EQ(expected, ids_out); |
| |
| // Delete {2, 3}. |
| std::set<int64> ids3; |
| ids3.insert(2); |
| ids3.insert(3); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->ClearPurgeableResourceIds(ids3)); |
| |
| ids_out.clear(); |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetPurgeableResourceIds(&ids_out)); |
| expected = base::STLSetDifference<std::set<int64> >(expected, ids3); |
| EXPECT_EQ(expected, ids_out); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) { |
| scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); |
| std::vector<int64> newly_purgeable_resources; |
| |
| // Data associated with |origin1| will be removed. |
| GURL origin1("http://example.com"); |
| GURL origin2("http://example.org"); |
| |
| // |origin1| has two registrations. |
| RegistrationData data1; |
| data1.registration_id = 10; |
| data1.scope = URL(origin1, "/foo"); |
| data1.script = URL(origin1, "/script1.js"); |
| data1.version_id = 100; |
| |
| std::vector<Resource> resources1; |
| resources1.push_back(CreateResource(1, URL(origin1, "/resource1"))); |
| resources1.push_back(CreateResource(2, URL(origin1, "/resource2"))); |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data1, resources1, |
| &newly_purgeable_resources)); |
| |
| RegistrationData data2; |
| data2.registration_id = 11; |
| data2.scope = URL(origin1, "/bar"); |
| data2.script = URL(origin1, "/script2.js"); |
| data2.version_id = 101; |
| |
| std::vector<Resource> resources2; |
| resources2.push_back(CreateResource(3, URL(origin1, "/resource3"))); |
| resources2.push_back(CreateResource(4, URL(origin1, "/resource4"))); |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data2, resources2, |
| &newly_purgeable_resources)); |
| |
| // |origin2| has one registration. |
| RegistrationData data3; |
| data3.registration_id = 12; |
| data3.scope = URL(origin2, "/hoge"); |
| data3.script = URL(origin2, "/script3.js"); |
| data3.version_id = 102; |
| |
| std::vector<Resource> resources3; |
| resources3.push_back(CreateResource(5, URL(origin2, "/resource5"))); |
| resources3.push_back(CreateResource(6, URL(origin2, "/resource6"))); |
| ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->WriteRegistration(data3, resources3, |
| &newly_purgeable_resources)); |
| |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->DeleteAllDataForOrigin(origin1, |
| &newly_purgeable_resources)); |
| |
| // |origin1| should be removed from the unique origin list. |
| std::set<GURL> unique_origins; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetOriginsWithRegistrations(&unique_origins)); |
| EXPECT_EQ(1u, unique_origins.size()); |
| EXPECT_TRUE(ContainsKey(unique_origins, origin2)); |
| |
| // The registrations for |origin1| should be removed. |
| std::vector<RegistrationData> registrations; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetRegistrationsForOrigin(origin1, ®istrations)); |
| EXPECT_TRUE(registrations.empty()); |
| |
| // The registration for |origin2| should not be removed. |
| RegistrationData data_out; |
| std::vector<Resource> resources_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->ReadRegistration( |
| data3.registration_id, origin2, &data_out, &resources_out)); |
| VerifyRegistrationData(data3, data_out); |
| VerifyResourceRecords(resources3, resources_out); |
| |
| // The resources associated with |origin1| should be purgeable. |
| std::set<int64> purgeable_ids_out; |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, |
| database->GetPurgeableResourceIds(&purgeable_ids_out)); |
| EXPECT_EQ(4u, purgeable_ids_out.size()); |
| EXPECT_TRUE(ContainsKey(purgeable_ids_out, 1)); |
| EXPECT_TRUE(ContainsKey(purgeable_ids_out, 2)); |
| EXPECT_TRUE(ContainsKey(purgeable_ids_out, 3)); |
| EXPECT_TRUE(ContainsKey(purgeable_ids_out, 4)); |
| } |
| |
| TEST(ServiceWorkerDatabaseTest, DestroyDatabase) { |
| base::ScopedTempDir database_dir; |
| ASSERT_TRUE(database_dir.CreateUniqueTempDir()); |
| scoped_ptr<ServiceWorkerDatabase> database( |
| CreateDatabase(database_dir.path())); |
| |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true)); |
| ASSERT_TRUE(base::DirectoryExists(database_dir.path())); |
| |
| EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->DestroyDatabase()); |
| ASSERT_FALSE(base::DirectoryExists(database_dir.path())); |
| } |
| |
| } // namespace content |