diff options
author | sorin <sorin@chromium.org> | 2015-05-26 12:59:09 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-26 20:00:01 +0000 |
commit | 7c7176234e553c35a2d8ec014f2caa29f7278065 (patch) | |
tree | 70eb3c58c82369cc13c939c17ae63344644c4b31 /components/component_updater/component_updater_service_unittest.cc | |
parent | 92780e77b6e0755e1d4bacbd493032969d04293b (diff) | |
download | chromium_src-7c7176234e553c35a2d8ec014f2caa29f7278065.zip chromium_src-7c7176234e553c35a2d8ec014f2caa29f7278065.tar.gz chromium_src-7c7176234e553c35a2d8ec014f2caa29f7278065.tar.bz2 |
Rewrite component update service in terms of components/update_client.
The goal of this change is to re-implement the component updater by
reusing the common code in components/update_client while keeping
the its public interface the same as before, in order to minimize
changes in its existing clients.
BUG=450337
Review URL: https://codereview.chromium.org/1133443002
Cr-Commit-Position: refs/heads/master@{#331412}
Diffstat (limited to 'components/component_updater/component_updater_service_unittest.cc')
-rw-r--r-- | components/component_updater/component_updater_service_unittest.cc | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/components/component_updater/component_updater_service_unittest.cc b/components/component_updater/component_updater_service_unittest.cc new file mode 100644 index 0000000..597135b --- /dev/null +++ b/components/component_updater/component_updater_service_unittest.cc @@ -0,0 +1,355 @@ +// 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 <limits> +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/thread_task_runner_handle.h" +#include "base/threading/sequenced_worker_pool.h" +#include "base/values.h" +#include "components/component_updater/component_updater_service.h" +#include "components/component_updater/component_updater_service_internal.h" +#include "components/update_client/test_configurator.h" +#include "components/update_client/test_installer.h" +#include "components/update_client/update_client.h" + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using Configurator = update_client::Configurator; +using TestConfigurator = update_client::TestConfigurator; +using UpdateClient = update_client::UpdateClient; + +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::Invoke; +using ::testing::Mock; +using ::testing::Return; + +namespace component_updater { + +class MockInstaller : public CrxInstaller { + public: + MockInstaller(); + + MOCK_METHOD1(OnUpdateError, void(int error)); + MOCK_METHOD2(Install, + bool(const base::DictionaryValue& manifest, + const base::FilePath& unpack_path)); + MOCK_METHOD2(GetInstalledFile, + bool(const std::string& file, base::FilePath* installed_file)); + MOCK_METHOD0(Uninstall, bool()); + + private: + ~MockInstaller() override; +}; + +class MockUpdateClient : public UpdateClient { + public: + MockUpdateClient(); + MOCK_METHOD1(AddObserver, void(Observer* observer)); + MOCK_METHOD1(RemoveObserver, void(Observer* observer)); + MOCK_METHOD3(Install, + void(const std::string& id, + const CrxDataCallback& crx_data_callback, + const CompletionCallback& completion_callback)); + MOCK_METHOD3(Update, + void(const std::vector<std::string>& ids, + const CrxDataCallback& crx_data_callback, + const CompletionCallback& completion_callback)); + MOCK_CONST_METHOD2(GetCrxUpdateState, + bool(const std::string& id, CrxUpdateItem* update_item)); + MOCK_CONST_METHOD1(IsUpdating, bool(const std::string& id)); + + private: + ~MockUpdateClient() override; +}; + +class MockServiceObserver : public ServiceObserver { + public: + MockServiceObserver(); + ~MockServiceObserver() override; + + MOCK_METHOD2(OnEvent, void(Events event, const std::string&)); +}; + +class ComponentUpdaterTest : public testing::Test { + public: + ComponentUpdaterTest(); + ~ComponentUpdaterTest() override; + + void SetUp() override; + + void TearDown() override; + + // Makes the full path to a component updater test file. + const base::FilePath test_file(const char* file); + + MockUpdateClient& update_client() { return *update_client_; } + ComponentUpdateService& component_updater() { return *component_updater_; } + scoped_refptr<TestConfigurator> configurator() const { return config_; } + base::Closure quit_closure() const { return quit_closure_; } + static void ReadyCallback() {} + + protected: + void RunThreads(); + + private: + static const int kNumWorkerThreads_ = 2; + + base::MessageLoopForUI message_loop_; + base::RunLoop runloop_; + base::Closure quit_closure_; + + scoped_refptr<base::SequencedWorkerPool> worker_pool_; + + scoped_refptr<TestConfigurator> config_; + scoped_refptr<MockUpdateClient> update_client_; + scoped_ptr<ComponentUpdateService> component_updater_; + + DISALLOW_COPY_AND_ASSIGN(ComponentUpdaterTest); +}; + +class OnDemandTester { + public: + static bool OnDemand(ComponentUpdateService* cus, const std::string& id); +}; + +MockInstaller::MockInstaller() { +} + +MockInstaller::~MockInstaller() { +} + +MockUpdateClient::MockUpdateClient() { +} + +MockUpdateClient::~MockUpdateClient() { +} + +MockServiceObserver::MockServiceObserver() { +} + +MockServiceObserver::~MockServiceObserver() { +} + +bool OnDemandTester::OnDemand(ComponentUpdateService* cus, + const std::string& id) { + return cus->GetOnDemandUpdater().OnDemandUpdate(id); +} + +scoped_ptr<ComponentUpdateService> TestComponentUpdateServiceFactory( + const scoped_refptr<Configurator>& config) { + DCHECK(config); + return scoped_ptr<ComponentUpdateService>( + new CrxUpdateService(config, new MockUpdateClient())); +} + +ComponentUpdaterTest::ComponentUpdaterTest() + : worker_pool_(new base::SequencedWorkerPool(kNumWorkerThreads_, "test")) { + quit_closure_ = runloop_.QuitClosure(); + + config_ = new TestConfigurator( + worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()), + message_loop_.task_runner()); + + update_client_ = new MockUpdateClient(); + EXPECT_CALL(update_client(), AddObserver(_)).Times(1); + component_updater_.reset(new CrxUpdateService(config_, update_client_)); +} + +ComponentUpdaterTest::~ComponentUpdaterTest() { + EXPECT_CALL(update_client(), RemoveObserver(_)).Times(1); + worker_pool_->Shutdown(); + component_updater_.reset(); +} + +void ComponentUpdaterTest::SetUp() { +} + +void ComponentUpdaterTest::TearDown() { +} + +void ComponentUpdaterTest::RunThreads() { + runloop_.Run(); +} + +TEST_F(ComponentUpdaterTest, AddObserver) { + MockServiceObserver observer; + EXPECT_CALL(update_client(), AddObserver(&observer)).Times(1); + component_updater().AddObserver(&observer); +} + +TEST_F(ComponentUpdaterTest, RemoveObserver) { + MockServiceObserver observer; + EXPECT_CALL(update_client(), RemoveObserver(&observer)).Times(1); + component_updater().RemoveObserver(&observer); +} + +// Tests that UpdateClient::Update is called by the timer loop when +// components are registered, and the component update starts. +// Also tests that Uninstall is called when a component is unregistered. +TEST_F(ComponentUpdaterTest, RegisterComponent) { + class LoopHandler { + public: + LoopHandler(int max_cnt, const base::Closure& quit_closure) + : max_cnt_(max_cnt), quit_closure_(quit_closure) {} + + void OnUpdate(const std::vector<std::string>& ids, + const UpdateClient::CrxDataCallback& crx_data_callback, + const UpdateClient::CompletionCallback& completion_callback) { + static int cnt = 0; + ++cnt; + if (cnt >= max_cnt_) + quit_closure_.Run(); + } + + private: + const int max_cnt_; + base::Closure quit_closure_; + }; + + scoped_refptr<MockInstaller> installer(new MockInstaller()); + EXPECT_CALL(*installer, Uninstall()).WillOnce(Return(true)); + + using update_client::jebg_hash; + using update_client::abag_hash; + + const std::string id1 = "abagagagagagagagagagagagagagagag"; + const std::string id2 = "jebgalgnebhfojomionfpkfelancnnkf"; + std::vector<std::string> ids; + ids.push_back(id1); + ids.push_back(id2); + + CrxComponent crx_component1; + crx_component1.pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash)); + crx_component1.version = Version("1.0"); + crx_component1.installer = installer; + + CrxComponent crx_component2; + crx_component2.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); + crx_component2.version = Version("0.9"); + crx_component2.installer = installer; + + // Quit after two update checks have fired. + LoopHandler loop_handler(2, quit_closure()); + EXPECT_CALL(update_client(), Update(ids, _, _)) + .WillRepeatedly(Invoke(&loop_handler, &LoopHandler::OnUpdate)); + + EXPECT_CALL(update_client(), IsUpdating(id1)).Times(1); + + EXPECT_TRUE(component_updater().RegisterComponent(crx_component1)); + EXPECT_TRUE(component_updater().RegisterComponent(crx_component2)); + + RunThreads(); + + EXPECT_TRUE(component_updater().UnregisterComponent(id1)); +} + +// Tests that on-demand updates invoke UpdateClient::Install. +TEST_F(ComponentUpdaterTest, OnDemandUpdate) { + class LoopHandler { + public: + LoopHandler(int max_cnt, const base::Closure& quit_closure) + : max_cnt_(max_cnt), quit_closure_(quit_closure) {} + + void OnInstall( + const std::string& ids, + const UpdateClient::CrxDataCallback& crx_data_callback, + const UpdateClient::CompletionCallback& completion_callback) { + static int cnt = 0; + ++cnt; + if (cnt >= max_cnt_) + quit_closure_.Run(); + } + + private: + const int max_cnt_; + base::Closure quit_closure_; + }; + + auto config = configurator(); + config->SetInitialDelay(3600); + + auto& cus = component_updater(); + + const std::string id = "jebgalgnebhfojomionfpkfelancnnkf"; + EXPECT_FALSE(OnDemandTester::OnDemand(&cus, id)); + + scoped_refptr<MockInstaller> installer(new MockInstaller()); + + using update_client::jebg_hash; + CrxComponent crx_component; + crx_component.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); + crx_component.version = Version("0.9"); + crx_component.installer = installer; + + LoopHandler loop_handler(1, quit_closure()); + EXPECT_CALL(update_client(), + Install("jebgalgnebhfojomionfpkfelancnnkf", _, _)) + .WillOnce(Invoke(&loop_handler, &LoopHandler::OnInstall)); + + EXPECT_TRUE(cus.RegisterComponent(crx_component)); + EXPECT_TRUE(OnDemandTester::OnDemand(&cus, id)); + + RunThreads(); +} + +// Tests that throttling an update invokes UpdateClient::Install. +TEST_F(ComponentUpdaterTest, MaybeThrottle) { + class LoopHandler { + public: + LoopHandler(int max_cnt, const base::Closure& quit_closure) + : max_cnt_(max_cnt), quit_closure_(quit_closure) {} + + void OnInstall( + const std::string& ids, + const UpdateClient::CrxDataCallback& crx_data_callback, + const UpdateClient::CompletionCallback& completion_callback) { + static int cnt = 0; + ++cnt; + if (cnt >= max_cnt_) + quit_closure_.Run(); + } + + private: + const int max_cnt_; + base::Closure quit_closure_; + }; + + auto config = configurator(); + config->SetInitialDelay(3600); + + scoped_refptr<MockInstaller> installer(new MockInstaller()); + + using update_client::jebg_hash; + CrxComponent crx_component; + crx_component.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); + crx_component.version = Version("0.9"); + crx_component.installer = installer; + + LoopHandler loop_handler(1, quit_closure()); + EXPECT_CALL(update_client(), + Install("jebgalgnebhfojomionfpkfelancnnkf", _, _)) + .WillOnce(Invoke(&loop_handler, &LoopHandler::OnInstall)); + + EXPECT_TRUE(component_updater().RegisterComponent(crx_component)); + component_updater().MaybeThrottle( + "jebgalgnebhfojomionfpkfelancnnkf", + base::Bind(&ComponentUpdaterTest::ReadyCallback)); + + RunThreads(); +} + +} // namespace component_updater |