Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(826)

Unified Diff: content/browser/background_sync/background_sync_manager_unittest.cc

Issue 950343006: [BackgroundSync] Initial land of the BackgroundSyncManager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Mapped registrations, more tests, register overwrites existing, unique ids for registrations Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/background_sync/background_sync_manager_unittest.cc
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..28035f95ee6f1fed5950165f8ff69c5d259f8283
--- /dev/null
+++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -0,0 +1,504 @@
+// Copyright 2015 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/background_sync/background_sync_manager.h"
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+const char kOriginUrl[] = "https://example.com";
+const int64 kServiceWorkerVersionId = 0;
+const int64 kServiceWorkerId1 = 1;
+const int64 kServiceWorkerId2 = 2;
+}
+
+namespace content {
+
+// A BackgroundSyncManager that can simulate delaying and corrupting the
+// backend. This class assumes (and verifies) that only one operation runs at a
+// time.
+class TestBackgroundSyncManager : public BackgroundSyncManager {
+ public:
+ explicit TestBackgroundSyncManager(
+ const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
+ : BackgroundSyncManager(service_worker_context) {}
+
+ void DoInit() { Init(); }
+
+ void StoreDataInBackendContinue(
+ int64 sw_registration_id,
+ const GURL& origin,
+ const std::string& key,
+ const std::string& data,
+ const ServiceWorkerStorage::StatusCallback& callback) {
+ BackgroundSyncManager::StoreDataInBackend(sw_registration_id, origin, key,
+ data, callback);
+ }
+
+ void GetDataFromBackendContinue(
+ const std::string& key,
+ const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback&
+ callback) {
+ BackgroundSyncManager::GetDataFromBackend(key, callback);
+ }
+
+ void Continue() {
+ continuation_.Run();
+ continuation_.Reset();
+ }
+
+ void set_corrupt_backend(bool corrupt_backend) {
+ corrupt_backend_ = corrupt_backend;
+ }
+ void set_delay_backend(bool delay_backend) { delay_backend_ = delay_backend; }
+
+ protected:
+ void StoreDataInBackend(
+ int64 sw_registration_id,
+ const GURL& origin,
+ const std::string& key,
+ const std::string& data,
+ const ServiceWorkerStorage::StatusCallback& callback) override {
+ EXPECT_TRUE(continuation_.is_null());
+ if (corrupt_backend_) {
+ callback.Run(SERVICE_WORKER_ERROR_FAILED);
davidben 2015/03/25 16:01:10 Nit: The real StoreDataInBackend never calls the c
jkarlin 2015/03/25 19:24:18 Done.
+ return;
+ }
+ continuation_ =
+ base::Bind(&TestBackgroundSyncManager::StoreDataInBackendContinue,
+ base::Unretained(this), sw_registration_id, origin, key,
+ data, callback);
+ if (delay_backend_)
+ return;
+
+ Continue();
+ }
+
+ void GetDataFromBackend(
+ const std::string& key,
+ const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback&
+ callback) override {
+ EXPECT_TRUE(continuation_.is_null());
+ if (corrupt_backend_) {
+ callback.Run(std::vector<std::pair<int64, std::string>>(),
davidben 2015/03/25 16:01:10 Nit: Ditto about it being reentrant.
jkarlin 2015/03/25 19:24:19 Done.
+ SERVICE_WORKER_ERROR_FAILED);
+ return;
+ }
+ continuation_ =
+ base::Bind(&TestBackgroundSyncManager::GetDataFromBackendContinue,
+ base::Unretained(this), key, callback);
+ if (delay_backend_)
+ return;
+
+ Continue();
+ }
+
+ private:
+ bool corrupt_backend_ = false;
+ bool delay_backend_ = false;
+ base::Closure continuation_;
+};
+
+class BackgroundSyncManagerTest : public testing::Test {
+ public:
+ BackgroundSyncManagerTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+ service_worker_context_(new ServiceWorkerContextWrapper(NULL)),
+ origin_(kOriginUrl),
+ sync_reg_1_(BackgroundSyncManager::BackgroundSyncRegistration("foo")),
+ sync_reg_2_(BackgroundSyncManager::BackgroundSyncRegistration("bar")),
+ callback_error_(BackgroundSyncManager::ERROR_TYPE_OK),
+ callback_sw_status_code_(SERVICE_WORKER_OK) {}
+
+ void SetUp() override {
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
+ new MockServiceWorkerDatabaseTaskManager(
+ base::ThreadTaskRunnerHandle::Get()));
+
+ service_worker_context_->InitInternal(
+ base::FilePath(), base::ThreadTaskRunnerHandle::Get(),
+ database_task_manager.Pass(), base::ThreadTaskRunnerHandle::Get(), NULL,
+ NULL);
+ context_ptr_ = service_worker_context_->context()->AsWeakPtr();
+
+ background_sync_manager_ =
+ BackgroundSyncManager::Create(service_worker_context_);
+
+ // Wait for storage to finish initializing before registering service
+ // workers.
+ base::RunLoop().RunUntilIdle();
+
+ RegisterServiceWorker(kServiceWorkerId1);
+ RegisterServiceWorker(kServiceWorkerId2);
+ }
+
+ void StatusAndRegistrationCallback(
+ bool* was_called,
+ BackgroundSyncManager::ErrorType error,
+ const BackgroundSyncManager::BackgroundSyncRegistration& registration) {
+ *was_called = true;
+ callback_error_ = error;
+ callback_registration_ = registration;
+ }
+
+ void StatusCallback(bool* was_called,
+ BackgroundSyncManager::ErrorType error) {
+ *was_called = true;
+ callback_error_ = error;
+ }
+
+ protected:
+ TestBackgroundSyncManager* UseTestBackgroundSyncManager() {
+ TestBackgroundSyncManager* manager =
+ new TestBackgroundSyncManager(service_worker_context_);
+ background_sync_manager_.reset(manager);
+ manager->DoInit();
+ return manager;
+ }
+
+ bool Register(const BackgroundSyncManager::BackgroundSyncRegistration&
+ sync_registration) {
+ return RegisterWithServiceWorkerId(kServiceWorkerId1, sync_registration);
+ }
+
+ bool RegisterWithServiceWorkerId(
+ int64 sw_registration_id,
+ const BackgroundSyncManager::BackgroundSyncRegistration&
+ sync_registration) {
+ bool was_called = false;
+ background_sync_manager_->Register(
+ origin_, sw_registration_id, sync_registration,
+ base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
+ base::Unretained(this), &was_called));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+ return callback_error_ == BackgroundSyncManager::ERROR_TYPE_OK;
+ }
+
+ bool Unregister(const BackgroundSyncManager::BackgroundSyncRegistration&
+ sync_registration) {
+ return UnregisterWithServiceWorkerId(kServiceWorkerId1, sync_registration);
+ }
+
+ bool UnregisterWithServiceWorkerId(
+ int64 sw_registration_id,
+ const BackgroundSyncManager::BackgroundSyncRegistration&
+ sync_registration) {
+ bool was_called = false;
+ background_sync_manager_->Unregister(
+ origin_, sw_registration_id, sync_registration.name,
+ sync_registration.id,
+ base::Bind(&BackgroundSyncManagerTest::StatusCallback,
+ base::Unretained(this), &was_called));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+ return callback_error_ == BackgroundSyncManager::ERROR_TYPE_OK;
+ }
+
+ bool GetRegistration(const std::string& sync_registration_name) {
+ return GetRegistrationWithServiceWorkerId(kServiceWorkerId1,
+ sync_registration_name);
+ }
+
+ bool GetRegistrationWithServiceWorkerId(
+ int64 sw_registration_id,
+ const std::string& sync_registration_name) {
+ bool was_called = false;
+ background_sync_manager_->GetRegistration(
+ origin_, sw_registration_id, sync_registration_name,
+ base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
+ base::Unretained(this), &was_called));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+
+ if (callback_error_ == BackgroundSyncManager::ERROR_TYPE_OK)
+ EXPECT_TRUE(sync_registration_name == callback_registration_.name);
+
+ return callback_error_ == BackgroundSyncManager::ERROR_TYPE_OK;
+ }
+
+ void StorageRegistrationCallback(ServiceWorkerStatusCode result) {
+ callback_sw_status_code_ = result;
+ }
+
+ void RegisterServiceWorker(uint64 sw_registration_id) {
+ scoped_refptr<ServiceWorkerRegistration> live_registration =
+ new ServiceWorkerRegistration(origin_, sw_registration_id,
+ context_ptr_);
+
+ scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
+ live_registration.get(), GURL(std::string(kOriginUrl) + "/script.js"),
+ kServiceWorkerVersionId, context_ptr_);
+ live_version->SetStatus(ServiceWorkerVersion::INSTALLED);
+ live_registration->SetWaitingVersion(live_version.get());
+
+ service_worker_context_->context()->storage()->StoreRegistration(
+ live_registration.get(), live_version.get(),
+ base::Bind(&BackgroundSyncManagerTest::StorageRegistrationCallback,
+ base::Unretained(this)));
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, callback_sw_status_code_);
+ }
+
+ TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+ scoped_ptr<BackgroundSyncManager> background_sync_manager_;
+ base::WeakPtr<ServiceWorkerContextCore> context_ptr_;
+
+ const GURL origin_;
+ BackgroundSyncManager::BackgroundSyncRegistration sync_reg_1_;
+ BackgroundSyncManager::BackgroundSyncRegistration sync_reg_2_;
+
+ // Callback values.
+ BackgroundSyncManager::ErrorType callback_error_;
+ BackgroundSyncManager::BackgroundSyncRegistration callback_registration_;
+ ServiceWorkerStatusCode callback_sw_status_code_;
+};
+
+TEST_F(BackgroundSyncManagerTest, Register) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+}
+
+TEST_F(BackgroundSyncManagerTest, RegistractionIntact) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+ EXPECT_STREQ(sync_reg_1_.name.c_str(), callback_registration_.name.c_str());
+ EXPECT_NE(sync_reg_1_.id, callback_registration_.id);
davidben 2015/03/25 16:01:10 Nit: I'd replace sync_reg_1_.id with BackgroundSyn
jkarlin 2015/03/25 19:24:18 Done.
+}
+
+TEST_F(BackgroundSyncManagerTest, RegisterExistingKeepsId) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+ BackgroundSyncManager::BackgroundSyncRegistration first_registration =
+ callback_registration_;
+ EXPECT_TRUE(Register(sync_reg_1_));
+ EXPECT_TRUE(callback_registration_.Equals(first_registration));
+ EXPECT_EQ(first_registration.id, callback_registration_.id);
+}
+
+TEST_F(BackgroundSyncManagerTest, RegisterOverwrites) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+ BackgroundSyncManager::BackgroundSyncRegistration first_registration =
+ callback_registration_;
+
+ sync_reg_1_.min_period = 100;
+ EXPECT_TRUE(Register(sync_reg_1_));
+ EXPECT_LT(first_registration.id, callback_registration_.id);
+ EXPECT_FALSE(callback_registration_.Equals(first_registration));
+}
+
+TEST_F(BackgroundSyncManagerTest, RegisterBadBackend) {
+ TestBackgroundSyncManager* manager = UseTestBackgroundSyncManager();
+ manager->set_corrupt_backend(true);
+ EXPECT_FALSE(Register(sync_reg_1_));
+ manager->set_corrupt_backend(false);
+ EXPECT_FALSE(GetRegistration(sync_reg_1_.name));
+}
+
+TEST_F(BackgroundSyncManagerTest, RegisterOverwriteBadBackend) {
+ TestBackgroundSyncManager* manager = UseTestBackgroundSyncManager();
+ EXPECT_TRUE(Register(sync_reg_1_));
+ BackgroundSyncManager::BackgroundSyncRegistration first_registration =
+ callback_registration_;
+
+ sync_reg_1_.min_period = 100;
+
+ manager->set_corrupt_backend(true);
+ EXPECT_FALSE(Register(sync_reg_1_));
+ EXPECT_TRUE(GetRegistration(sync_reg_1_.name));
+ EXPECT_EQ(callback_registration_.id, first_registration.id);
+ EXPECT_TRUE(callback_registration_.Equals(first_registration));
+}
+
+TEST_F(BackgroundSyncManagerTest, TwoRegistrations) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+ EXPECT_TRUE(Register(sync_reg_2_));
+}
+
+TEST_F(BackgroundSyncManagerTest, GetRegistrationNonExisting) {
+ EXPECT_FALSE(GetRegistration(sync_reg_1_.name));
+}
+
+TEST_F(BackgroundSyncManagerTest, GetRegistrationExisting) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+ EXPECT_TRUE(GetRegistration(sync_reg_1_.name));
+ EXPECT_FALSE(GetRegistration(sync_reg_2_.name));
+}
+
+TEST_F(BackgroundSyncManagerTest, GetRegistrationBadBackend) {
+ TestBackgroundSyncManager* manager = UseTestBackgroundSyncManager();
+ EXPECT_TRUE(Register(sync_reg_1_));
+ manager->set_corrupt_backend(true);
+ EXPECT_TRUE(GetRegistration(sync_reg_1_.name));
+ EXPECT_FALSE(GetRegistration(sync_reg_2_.name));
+ manager->set_corrupt_backend(false);
+ EXPECT_TRUE(GetRegistration(sync_reg_1_.name));
+ EXPECT_FALSE(GetRegistration(sync_reg_2_.name));
+}
+
+TEST_F(BackgroundSyncManagerTest, Unregister) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+ EXPECT_TRUE(Unregister(callback_registration_));
+ EXPECT_FALSE(GetRegistration(sync_reg_1_.name));
+}
+
+TEST_F(BackgroundSyncManagerTest, UnregisterWrongId) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+ callback_registration_.id = 10012310;
davidben 2015/03/25 16:01:10 Nit: That's a very weird number. :-) Maybe just ca
jkarlin 2015/03/25 19:24:18 Done.
+ EXPECT_FALSE(Unregister(callback_registration_));
+}
+
+TEST_F(BackgroundSyncManagerTest, Reregister) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+ EXPECT_TRUE(Unregister(callback_registration_));
+ EXPECT_TRUE(Register(sync_reg_1_));
+}
+
+TEST_F(BackgroundSyncManagerTest, UnregisterNonExisting) {
+ EXPECT_FALSE(Unregister(sync_reg_1_));
+ EXPECT_EQ(BackgroundSyncManager::ERROR_TYPE_NOT_FOUND, callback_error_);
+}
+
+TEST_F(BackgroundSyncManagerTest, UnregisterSecond) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+ EXPECT_TRUE(Register(sync_reg_2_));
+ EXPECT_TRUE(Unregister(callback_registration_));
+ EXPECT_TRUE(GetRegistration(sync_reg_1_.name));
+ EXPECT_TRUE(Register(sync_reg_2_));
+}
+
+TEST_F(BackgroundSyncManagerTest, UnregisterBadBackend) {
+ TestBackgroundSyncManager* manager = UseTestBackgroundSyncManager();
+ EXPECT_TRUE(Register(sync_reg_1_));
+ manager->set_corrupt_backend(true);
+ EXPECT_FALSE(Unregister(sync_reg_1_));
+ manager->set_corrupt_backend(false);
+ EXPECT_TRUE(GetRegistration(sync_reg_1_.name));
davidben 2015/03/25 16:01:10 Probably should add some assertions that callback_
jkarlin 2015/03/25 19:24:18 Yep, done. Verified that updated test fails withou
+}
+
+TEST_F(BackgroundSyncManagerTest, RegistrationIncreasesId) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+ BackgroundSyncManager::BackgroundSyncRegistration registered_sync =
+ callback_registration_;
+ BackgroundSyncManager::BackgroundSyncRegistration::RegistrationId cur_id =
+ callback_registration_.id;
+
+ EXPECT_TRUE(GetRegistration(sync_reg_1_.name));
+ EXPECT_TRUE(Register(sync_reg_2_));
+ EXPECT_LT(cur_id, callback_registration_.id);
+ cur_id = callback_registration_.id;
+
+ EXPECT_TRUE(Unregister(registered_sync));
+ EXPECT_TRUE(Register(sync_reg_1_));
+ EXPECT_LT(cur_id, callback_registration_.id);
+}
+
+TEST_F(BackgroundSyncManagerTest, RebootRecovery) {
+ EXPECT_TRUE(Register(sync_reg_1_));
+
+ background_sync_manager_ =
+ BackgroundSyncManager::Create(service_worker_context_);
+
+ EXPECT_TRUE(GetRegistration(sync_reg_1_.name));
+ EXPECT_FALSE(GetRegistration(sync_reg_2_.name));
+}
+
+TEST_F(BackgroundSyncManagerTest, RebootRecoveryTwoServiceWorkers) {
+ EXPECT_TRUE(RegisterWithServiceWorkerId(kServiceWorkerId1, sync_reg_1_));
+ EXPECT_TRUE(RegisterWithServiceWorkerId(kServiceWorkerId2, sync_reg_2_));
+
+ background_sync_manager_ =
+ BackgroundSyncManager::Create(service_worker_context_);
+
+ EXPECT_TRUE(
+ GetRegistrationWithServiceWorkerId(kServiceWorkerId1, sync_reg_1_.name));
+ EXPECT_FALSE(
+ GetRegistrationWithServiceWorkerId(kServiceWorkerId1, sync_reg_2_.name));
+ EXPECT_FALSE(
+ GetRegistrationWithServiceWorkerId(kServiceWorkerId2, sync_reg_1_.name));
+ EXPECT_TRUE(
+ GetRegistrationWithServiceWorkerId(kServiceWorkerId2, sync_reg_2_.name));
+
+ EXPECT_TRUE(
+ GetRegistrationWithServiceWorkerId(kServiceWorkerId1, sync_reg_1_.name));
+ EXPECT_TRUE(
+ GetRegistrationWithServiceWorkerId(kServiceWorkerId2, sync_reg_2_.name));
+
+ EXPECT_TRUE(RegisterWithServiceWorkerId(kServiceWorkerId1, sync_reg_2_));
+ EXPECT_TRUE(RegisterWithServiceWorkerId(kServiceWorkerId2, sync_reg_1_));
+}
+
+TEST_F(BackgroundSyncManagerTest, InitWithCorruptBackend) {
+ TestBackgroundSyncManager* manager =
+ new TestBackgroundSyncManager(service_worker_context_);
+ background_sync_manager_.reset(manager);
+ manager->set_corrupt_backend(true);
+ manager->DoInit();
+
+ EXPECT_FALSE(Register(sync_reg_1_));
+ EXPECT_FALSE(GetRegistration(sync_reg_1_.name));
+ EXPECT_FALSE(Unregister(sync_reg_1_));
+}
+
+TEST_F(BackgroundSyncManagerTest, SequentialOperations) {
+ // Schedule Init and all of the operations on a delayed backend. Verify that
+ // the operations complete sequentially.
+ TestBackgroundSyncManager* manager =
+ new TestBackgroundSyncManager(service_worker_context_);
+ background_sync_manager_.reset(manager);
+ manager->set_delay_backend(true);
+ manager->DoInit();
+
+ const int64 kExpectedInitialId =
+ BackgroundSyncManager::BackgroundSyncRegistrations::kInitialCounterId;
+
+ bool register_called = false;
+ bool unregister_called = false;
+ bool get_registration_called = false;
+ manager->Register(
+ origin_, kServiceWorkerId1, sync_reg_1_,
+ base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
+ base::Unretained(this), &register_called));
+ manager->Unregister(origin_, kServiceWorkerId1, sync_reg_1_.name,
+ kExpectedInitialId,
+ base::Bind(&BackgroundSyncManagerTest::StatusCallback,
+ base::Unretained(this), &unregister_called));
+ manager->GetRegistration(
+ origin_, kServiceWorkerId1, sync_reg_1_.name,
+ base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
+ base::Unretained(this), &get_registration_called));
+
+ base::RunLoop().RunUntilIdle();
+ // Init should be blocked while loading from the backend.
+ EXPECT_FALSE(register_called || unregister_called || get_registration_called);
davidben 2015/03/25 16:01:10 Nit: I'd expand these out individually (and ditto
jkarlin 2015/03/25 19:24:18 Done.
+
+ manager->Continue();
+ base::RunLoop().RunUntilIdle();
+ // Register should be blocked while storing to the backend.
+ EXPECT_FALSE(register_called || unregister_called || get_registration_called);
+
+ manager->Continue();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(register_called);
+ EXPECT_EQ(kExpectedInitialId, callback_registration_.id);
+ EXPECT_EQ(BackgroundSyncManager::ERROR_TYPE_OK, callback_error_);
+ // Unregister should be blocked while storing to the backend.
+ EXPECT_FALSE(unregister_called || get_registration_called);
+
+ manager->Continue();
+ base::RunLoop().RunUntilIdle();
+ // Unregister should be done and since GetRegistration doesn't require the
+ // backend it should be done too.
+ EXPECT_EQ(BackgroundSyncManager::ERROR_TYPE_NOT_FOUND, callback_error_);
+ EXPECT_TRUE(unregister_called && get_registration_called);
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698