blob: a376c30354ea0212a074a3cf8f5409c802d22b8d [file] [log] [blame]
sorin7c717622015-05-26 19:59:091// Copyright 2015 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
dchenga0ee5fb82016-04-26 02:46:555#include "components/component_updater/component_updater_service.h"
6
sorin7c717622015-05-26 19:59:097#include <limits>
Sorin Jianu990ee142017-06-02 22:34:088#include <memory>
sorin7c717622015-05-26 19:59:099#include <string>
Sorin Jianua8ef73d2017-11-02 16:55:1710#include <utility>
sorin7c717622015-05-26 19:59:0911#include <vector>
12
13#include "base/bind.h"
Tibor Goldschwendt5f173cb2018-06-21 22:50:4014#include "base/bind_helpers.h"
sorin7c717622015-05-26 19:59:0915#include "base/files/file_path.h"
16#include "base/files/file_util.h"
17#include "base/macros.h"
18#include "base/memory/ref_counted.h"
sorin7c717622015-05-26 19:59:0919#include "base/run_loop.h"
Sorin Jianud20ed8532018-06-28 17:24:3120#include "base/stl_util.h"
Gabriel Charette44db1422018-08-06 11:19:3321#include "base/task/post_task.h"
Devlin Cronin69228f42018-06-01 17:25:1022#include "base/test/metrics/histogram_tester.h"
Gabriel Charettec7108742019-08-23 03:31:4023#include "base/test/task_environment.h"
gab7966d312016-05-11 20:35:0124#include "base/threading/thread_task_runner_handle.h"
sorin7c717622015-05-26 19:59:0925#include "base/values.h"
sorin7c717622015-05-26 19:59:0926#include "components/component_updater/component_updater_service_internal.h"
27#include "components/update_client/test_configurator.h"
28#include "components/update_client/test_installer.h"
29#include "components/update_client/update_client.h"
sorin7b8650522016-11-02 18:23:4130#include "components/update_client/update_client_errors.h"
sorin7c717622015-05-26 19:59:0931#include "testing/gmock/include/gmock/gmock.h"
32#include "testing/gtest/include/gtest/gtest.h"
33
34using Configurator = update_client::Configurator;
sorin2892f7212016-11-07 18:59:4335using Result = update_client::CrxInstaller::Result;
sorin7c717622015-05-26 19:59:0936using TestConfigurator = update_client::TestConfigurator;
37using UpdateClient = update_client::UpdateClient;
38
39using ::testing::_;
40using ::testing::AnyNumber;
41using ::testing::Invoke;
42using ::testing::Mock;
43using ::testing::Return;
Sorin Jianua8ef73d2017-11-02 16:55:1744using ::testing::Unused;
sorin7c717622015-05-26 19:59:0945
46namespace component_updater {
47
48class MockInstaller : public CrxInstaller {
49 public:
50 MockInstaller();
51
Sorin Jianua8ef73d2017-11-02 16:55:1752 // gMock does not support mocking functions with parameters which have
53 // move semantics. This function is a shim to work around it.
54 void Install(const base::FilePath& unpack_path,
55 const std::string& public_key,
Sorin Jianu9d64af672020-02-05 19:14:3456 std::unique_ptr<InstallParams> install_params,
Daniel Cheng67848522018-04-27 22:04:4157 update_client::CrxInstaller::Callback callback) override {
Sorin Jianua8ef73d2017-11-02 16:55:1758 DoInstall(unpack_path, callback);
59 }
60
sorin7c717622015-05-26 19:59:0961 MOCK_METHOD1(OnUpdateError, void(int error));
Sorin Jianua8ef73d2017-11-02 16:55:1762 MOCK_METHOD2(DoInstall,
Sorin Jianu7aa6d1f2017-10-13 20:29:2963 void(const base::FilePath& unpack_path,
Sorin Jianuf40ab4b32017-10-06 22:53:4164 const update_client::CrxInstaller::Callback& callback));
sorin7c717622015-05-26 19:59:0965 MOCK_METHOD2(GetInstalledFile,
66 bool(const std::string& file, base::FilePath* installed_file));
67 MOCK_METHOD0(Uninstall, bool());
68
69 private:
70 ~MockInstaller() override;
71};
72
73class MockUpdateClient : public UpdateClient {
74 public:
75 MockUpdateClient();
Vladislav Kuzkokov12eca792017-10-20 12:45:3876
Sorin Jianua8ef73d2017-11-02 16:55:1777 // gMock does not support mocking functions with parameters which have
78 // move semantics. This function is a shim to work around it.
Vladislav Kuzkokov12eca792017-10-20 12:45:3879 void Install(const std::string& id,
Sorin Jianua8ef73d2017-11-02 16:55:1780 CrxDataCallback crx_data_callback,
Sorin Jianudfb12a42020-03-10 04:12:0381 CrxStateChangeCallback crx_state_change_callback,
Vladislav Kuzkokov12eca792017-10-20 12:45:3882 Callback callback) override {
Sorin Jianud20ed8532018-06-28 17:24:3183 DoInstall(id);
Vladislav Kuzkokov12eca792017-10-20 12:45:3884 std::move(callback).Run(update_client::Error::NONE);
85 }
86
87 void Update(const std::vector<std::string>& ids,
Sorin Jianua8ef73d2017-11-02 16:55:1788 CrxDataCallback crx_data_callback,
Sorin Jianudfb12a42020-03-10 04:12:0389 CrxStateChangeCallback crx_state_change_callback,
Sorin Jianub41a592a2018-03-02 16:30:2790 bool is_foreground,
Vladislav Kuzkokov12eca792017-10-20 12:45:3891 Callback callback) override {
Sorin Jianub41a592a2018-03-02 16:30:2792 // All update calls initiated by the component update service are
93 // automatically triggered as background updates without user intervention.
94 EXPECT_FALSE(is_foreground);
Sorin Jianud20ed8532018-06-28 17:24:3195 DoUpdate(ids);
Vladislav Kuzkokov12eca792017-10-20 12:45:3896 std::move(callback).Run(update_client::Error::NONE);
97 }
98
99 void SendUninstallPing(const std::string& id,
100 const base::Version& version,
101 int reason,
Daniel Cheng67848522018-04-27 22:04:41102 Callback callback) override {
Vladislav Kuzkokov12eca792017-10-20 12:45:38103 DoSendUninstallPing(id, version, reason);
104 std::move(callback).Run(update_client::Error::NONE);
105 }
106
sorin7c717622015-05-26 19:59:09107 MOCK_METHOD1(AddObserver, void(Observer* observer));
108 MOCK_METHOD1(RemoveObserver, void(Observer* observer));
Sorin Jianud20ed8532018-06-28 17:24:31109 MOCK_METHOD1(DoInstall, void(const std::string& id));
110 MOCK_METHOD1(DoUpdate, void(const std::vector<std::string>& ids));
sorin7c717622015-05-26 19:59:09111 MOCK_CONST_METHOD2(GetCrxUpdateState,
112 bool(const std::string& id, CrxUpdateItem* update_item));
113 MOCK_CONST_METHOD1(IsUpdating, bool(const std::string& id));
sorinecaad3e2015-11-13 19:15:52114 MOCK_METHOD0(Stop, void());
Vladislav Kuzkokov12eca792017-10-20 12:45:38115 MOCK_METHOD3(DoSendUninstallPing,
sorin8037ac8c2017-04-19 16:28:00116 void(const std::string& id,
117 const base::Version& version,
Vladislav Kuzkokov12eca792017-10-20 12:45:38118 int reason));
sorin7c717622015-05-26 19:59:09119
120 private:
121 ~MockUpdateClient() override;
122};
123
124class MockServiceObserver : public ServiceObserver {
125 public:
126 MockServiceObserver();
127 ~MockServiceObserver() override;
128
129 MOCK_METHOD2(OnEvent, void(Events event, const std::string&));
130};
131
Tibor Goldschwendt5f173cb2018-06-21 22:50:40132class MockUpdateScheduler : public UpdateScheduler {
133 public:
134 MOCK_METHOD4(Schedule,
135 void(const base::TimeDelta& initial_delay,
136 const base::TimeDelta& delay,
137 const UserTask& user_task,
138 const OnStopTaskCallback& on_stop));
139 MOCK_METHOD0(Stop, void());
140};
141
sorin7c717622015-05-26 19:59:09142class ComponentUpdaterTest : public testing::Test {
143 public:
144 ComponentUpdaterTest();
145 ~ComponentUpdaterTest() override;
146
sorin7c717622015-05-26 19:59:09147 // Makes the full path to a component updater test file.
148 const base::FilePath test_file(const char* file);
149
150 MockUpdateClient& update_client() { return *update_client_; }
151 ComponentUpdateService& component_updater() { return *component_updater_; }
152 scoped_refptr<TestConfigurator> configurator() const { return config_; }
Sorin Jianua8ef73d2017-11-02 16:55:17153 base::OnceClosure quit_closure() { return runloop_.QuitClosure(); }
Tibor Goldschwendt5f173cb2018-06-21 22:50:40154 MockUpdateScheduler& scheduler() { return *scheduler_; }
sorin7c717622015-05-26 19:59:09155 static void ReadyCallback() {}
156
157 protected:
158 void RunThreads();
159
160 private:
Tibor Goldschwendt5f173cb2018-06-21 22:50:40161 void RunUpdateTask(const UpdateScheduler::UserTask& user_task);
162 void Schedule(const base::TimeDelta& initial_delay,
163 const base::TimeDelta& delay,
164 const UpdateScheduler::UserTask& user_task,
165 const UpdateScheduler::OnStopTaskCallback& on_stop);
166
Gabriel Charettedfa36042019-08-19 17:30:11167 base::test::TaskEnvironment task_environment_;
sorin7c717622015-05-26 19:59:09168 base::RunLoop runloop_;
sorin7c717622015-05-26 19:59:09169
Sorin Jianucc048f892017-07-26 02:05:54170 scoped_refptr<TestConfigurator> config_ =
171 base::MakeRefCounted<TestConfigurator>();
Tibor Goldschwendt5f173cb2018-06-21 22:50:40172 MockUpdateScheduler* scheduler_;
Sorin Jianucc048f892017-07-26 02:05:54173 scoped_refptr<MockUpdateClient> update_client_ =
174 base::MakeRefCounted<MockUpdateClient>();
dchenga0ee5fb82016-04-26 02:46:55175 std::unique_ptr<ComponentUpdateService> component_updater_;
sorin7c717622015-05-26 19:59:09176
177 DISALLOW_COPY_AND_ASSIGN(ComponentUpdaterTest);
178};
179
180class OnDemandTester {
181 public:
Sorin Jianud20ed8532018-06-28 17:24:31182 void OnDemand(ComponentUpdateService* cus,
183 const std::string& id,
184 OnDemandUpdater::Priority priority);
sorin7b8650522016-11-02 18:23:41185 update_client::Error error() const { return error_; }
sorin4c520182016-08-19 17:27:44186
187 private:
sorin7b8650522016-11-02 18:23:41188 void OnDemandComplete(update_client::Error error);
sorin4c520182016-08-19 17:27:44189
sorin7b8650522016-11-02 18:23:41190 update_client::Error error_ = update_client::Error::NONE;
sorin7c717622015-05-26 19:59:09191};
192
Sorin Jianudfb12a42020-03-10 04:12:03193MockInstaller::MockInstaller() = default;
194MockInstaller::~MockInstaller() = default;
195MockUpdateClient::MockUpdateClient() = default;
196MockUpdateClient::~MockUpdateClient() = default;
197MockServiceObserver::MockServiceObserver() = default;
198MockServiceObserver::~MockServiceObserver() = default;
sorin7c717622015-05-26 19:59:09199
sorin4c520182016-08-19 17:27:44200void OnDemandTester::OnDemand(ComponentUpdateService* cus,
Sorin Jianud20ed8532018-06-28 17:24:31201 const std::string& id,
202 OnDemandUpdater::Priority priority) {
sorin4c520182016-08-19 17:27:44203 cus->GetOnDemandUpdater().OnDemandUpdate(
Sorin Jianud20ed8532018-06-28 17:24:31204 id, priority,
205 base::BindOnce(&OnDemandTester::OnDemandComplete,
206 base::Unretained(this)));
sorin4c520182016-08-19 17:27:44207}
208
sorin7b8650522016-11-02 18:23:41209void OnDemandTester::OnDemandComplete(update_client::Error error) {
sorin4c520182016-08-19 17:27:44210 error_ = error;
sorin7c717622015-05-26 19:59:09211}
212
dchenga0ee5fb82016-04-26 02:46:55213std::unique_ptr<ComponentUpdateService> TestComponentUpdateServiceFactory(
Sorin Jianu49126332018-02-13 17:07:42214 scoped_refptr<Configurator> config) {
sorin7c717622015-05-26 19:59:09215 DCHECK(config);
Gyuyoung Kim6afb5082018-01-19 13:35:57216 return std::make_unique<CrxUpdateService>(
Tibor Goldschwendt5f173cb2018-06-21 22:50:40217 config, std::make_unique<MockUpdateScheduler>(),
218 base::MakeRefCounted<MockUpdateClient>());
sorin7c717622015-05-26 19:59:09219}
220
Sorin Jianucc048f892017-07-26 02:05:54221ComponentUpdaterTest::ComponentUpdaterTest() {
sorin7c717622015-05-26 19:59:09222 EXPECT_CALL(update_client(), AddObserver(_)).Times(1);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40223 auto scheduler = std::make_unique<MockUpdateScheduler>();
224 scheduler_ = scheduler.get();
225 ON_CALL(*scheduler_, Schedule(_, _, _, _))
226 .WillByDefault(Invoke(this, &ComponentUpdaterTest::Schedule));
227 component_updater_ = std::make_unique<CrxUpdateService>(
228 config_, std::move(scheduler), update_client_);
sorin7c717622015-05-26 19:59:09229}
230
231ComponentUpdaterTest::~ComponentUpdaterTest() {
232 EXPECT_CALL(update_client(), RemoveObserver(_)).Times(1);
sorin7c717622015-05-26 19:59:09233 component_updater_.reset();
234}
235
sorin7c717622015-05-26 19:59:09236void ComponentUpdaterTest::RunThreads() {
237 runloop_.Run();
238}
239
Tibor Goldschwendt5f173cb2018-06-21 22:50:40240void ComponentUpdaterTest::RunUpdateTask(
241 const UpdateScheduler::UserTask& user_task) {
Gabriel Charettedfa36042019-08-19 17:30:11242 task_environment_.GetMainThreadTaskRunner()->PostTask(
Tibor Goldschwendt5f173cb2018-06-21 22:50:40243 FROM_HERE, base::BindRepeating(
244 [](const UpdateScheduler::UserTask& user_task,
245 ComponentUpdaterTest* test) {
246 user_task.Run(base::BindOnce(
247 [](const UpdateScheduler::UserTask& user_task,
248 ComponentUpdaterTest* test) {
249 test->RunUpdateTask(user_task);
250 },
251 user_task, base::Unretained(test)));
252 },
253 user_task, base::Unretained(this)));
254}
255
256void ComponentUpdaterTest::Schedule(
257 const base::TimeDelta& initial_delay,
258 const base::TimeDelta& delay,
259 const UpdateScheduler::UserTask& user_task,
260 const UpdateScheduler::OnStopTaskCallback& on_stop) {
261 RunUpdateTask(user_task);
262}
263
sorin7c717622015-05-26 19:59:09264TEST_F(ComponentUpdaterTest, AddObserver) {
265 MockServiceObserver observer;
266 EXPECT_CALL(update_client(), AddObserver(&observer)).Times(1);
sorinecaad3e2015-11-13 19:15:52267 EXPECT_CALL(update_client(), Stop()).Times(1);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40268 EXPECT_CALL(scheduler(), Stop()).Times(1);
sorin7c717622015-05-26 19:59:09269 component_updater().AddObserver(&observer);
270}
271
272TEST_F(ComponentUpdaterTest, RemoveObserver) {
273 MockServiceObserver observer;
274 EXPECT_CALL(update_client(), RemoveObserver(&observer)).Times(1);
sorinecaad3e2015-11-13 19:15:52275 EXPECT_CALL(update_client(), Stop()).Times(1);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40276 EXPECT_CALL(scheduler(), Stop()).Times(1);
sorin7c717622015-05-26 19:59:09277 component_updater().RemoveObserver(&observer);
278}
279
280// Tests that UpdateClient::Update is called by the timer loop when
281// components are registered, and the component update starts.
282// Also tests that Uninstall is called when a component is unregistered.
283TEST_F(ComponentUpdaterTest, RegisterComponent) {
284 class LoopHandler {
285 public:
Sorin Jianua8ef73d2017-11-02 16:55:17286 LoopHandler(int max_cnt, base::OnceClosure quit_closure)
287 : max_cnt_(max_cnt), quit_closure_(std::move(quit_closure)) {}
sorin7c717622015-05-26 19:59:09288
Sorin Jianud20ed8532018-06-28 17:24:31289 void OnUpdate(const std::vector<std::string>& ids) {
sorin7c717622015-05-26 19:59:09290 static int cnt = 0;
291 ++cnt;
292 if (cnt >= max_cnt_)
Sorin Jianua8ef73d2017-11-02 16:55:17293 std::move(quit_closure_).Run();
sorin7c717622015-05-26 19:59:09294 }
295
296 private:
297 const int max_cnt_;
Sorin Jianua8ef73d2017-11-02 16:55:17298 base::OnceClosure quit_closure_;
sorin7c717622015-05-26 19:59:09299 };
300
sorin85953dc2016-03-10 00:32:48301 base::HistogramTester ht;
302
Sorin Jianua8ef73d2017-11-02 16:55:17303 scoped_refptr<MockInstaller> installer =
304 base::MakeRefCounted<MockInstaller>();
sorin7c717622015-05-26 19:59:09305 EXPECT_CALL(*installer, Uninstall()).WillOnce(Return(true));
306
307 using update_client::jebg_hash;
308 using update_client::abag_hash;
309
310 const std::string id1 = "abagagagagagagagagagagagagagagag";
311 const std::string id2 = "jebgalgnebhfojomionfpkfelancnnkf";
312 std::vector<std::string> ids;
313 ids.push_back(id1);
314 ids.push_back(id2);
315
316 CrxComponent crx_component1;
Joshua Pawlicki9656e3922019-09-16 16:34:51317 crx_component1.app_id = id1;
Sorin Jianud20ed8532018-06-28 17:24:31318 crx_component1.pk_hash.assign(abag_hash, abag_hash + base::size(abag_hash));
pwnall15745b312016-08-19 21:45:29319 crx_component1.version = base::Version("1.0");
sorin7c717622015-05-26 19:59:09320 crx_component1.installer = installer;
321
322 CrxComponent crx_component2;
Joshua Pawlicki9656e3922019-09-16 16:34:51323 crx_component2.app_id = id2;
Sorin Jianud20ed8532018-06-28 17:24:31324 crx_component2.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
pwnall15745b312016-08-19 21:45:29325 crx_component2.version = base::Version("0.9");
sorin7c717622015-05-26 19:59:09326 crx_component2.installer = installer;
327
328 // Quit after two update checks have fired.
329 LoopHandler loop_handler(2, quit_closure());
Sorin Jianud20ed8532018-06-28 17:24:31330 EXPECT_CALL(update_client(), DoUpdate(ids))
sorin7c717622015-05-26 19:59:09331 .WillRepeatedly(Invoke(&loop_handler, &LoopHandler::OnUpdate));
332
333 EXPECT_CALL(update_client(), IsUpdating(id1)).Times(1);
sorinecaad3e2015-11-13 19:15:52334 EXPECT_CALL(update_client(), Stop()).Times(1);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40335 EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
336 EXPECT_CALL(scheduler(), Stop()).Times(1);
sorin7c717622015-05-26 19:59:09337
338 EXPECT_TRUE(component_updater().RegisterComponent(crx_component1));
339 EXPECT_TRUE(component_updater().RegisterComponent(crx_component2));
340
341 RunThreads();
sorin7c717622015-05-26 19:59:09342 EXPECT_TRUE(component_updater().UnregisterComponent(id1));
sorin85953dc2016-03-10 00:32:48343
344 ht.ExpectUniqueSample("ComponentUpdater.Calls", 1, 2);
345 ht.ExpectUniqueSample("ComponentUpdater.UpdateCompleteResult", 0, 2);
346 ht.ExpectTotalCount("ComponentUpdater.UpdateCompleteTime", 2);
sorin7c717622015-05-26 19:59:09347}
348
349// Tests that on-demand updates invoke UpdateClient::Install.
350TEST_F(ComponentUpdaterTest, OnDemandUpdate) {
351 class LoopHandler {
352 public:
sorin7b8650522016-11-02 18:23:41353 explicit LoopHandler(int max_cnt) : max_cnt_(max_cnt) {}
sorin7c717622015-05-26 19:59:09354
Sorin Jianud20ed8532018-06-28 17:24:31355 void OnInstall(const std::string& ids) {
356 ++cnt_;
357 if (cnt_ >= max_cnt_) {
358 base::ThreadTaskRunnerHandle::Get()->PostTask(
359 FROM_HERE,
360 base::BindOnce(&LoopHandler::Quit, base::Unretained(this)));
361 }
362 }
363
364 void OnUpdate(const std::vector<std::string>& ids) {
365 ++cnt_;
366 if (cnt_ >= max_cnt_) {
sorin4c520182016-08-19 17:27:44367 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuebd652462017-07-23 02:00:58368 FROM_HERE,
369 base::BindOnce(&LoopHandler::Quit, base::Unretained(this)));
sorin4c520182016-08-19 17:27:44370 }
sorin7c717622015-05-26 19:59:09371 }
372
373 private:
Gabriel Charette53a9ef812017-07-26 12:36:23374 void Quit() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
sorin4c520182016-08-19 17:27:44375
Sorin Jianud20ed8532018-06-28 17:24:31376 int cnt_ = 0;
sorin7c717622015-05-26 19:59:09377 const int max_cnt_;
sorin7c717622015-05-26 19:59:09378 };
379
sorin85953dc2016-03-10 00:32:48380 base::HistogramTester ht;
381
Tibor Goldschwendt5f173cb2018-06-21 22:50:40382 // Don't run periodic update task.
383 ON_CALL(scheduler(), Schedule(_, _, _, _)).WillByDefault(Return());
sorin7c717622015-05-26 19:59:09384
385 auto& cus = component_updater();
386
sorin4c520182016-08-19 17:27:44387 // Tests calling OnDemand for an unregistered component. This call results in
388 // an error, which is recorded by the OnDemandTester instance. Since the
389 // component was not registered, the call is ignored for UMA metrics.
390 OnDemandTester ondemand_tester_component_not_registered;
391 ondemand_tester_component_not_registered.OnDemand(
Sorin Jianud20ed8532018-06-28 17:24:31392 &cus, "ihfokbkgjpifnbbojhneepfflplebdkc",
393 OnDemandUpdater::Priority::FOREGROUND);
sorin7c717622015-05-26 19:59:09394
Sorin Jianud20ed8532018-06-28 17:24:31395 // Register two components, then call |OnDemand| for each component, with
396 // foreground and background priorities. Expect calls to |Schedule| because
397 // components have registered, calls to |Install| and |Update| corresponding
398 // to each |OnDemand| invocation, and calls to |Stop| when the mocks are
399 // torn down.
400 LoopHandler loop_handler(2);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40401 EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
Sorin Jianud20ed8532018-06-28 17:24:31402 EXPECT_CALL(update_client(), DoInstall("jebgalgnebhfojomionfpkfelancnnkf"))
403 .WillOnce(Invoke(&loop_handler, &LoopHandler::OnInstall));
404 EXPECT_CALL(
405 update_client(),
406 DoUpdate(std::vector<std::string>({"abagagagagagagagagagagagagagagag"})))
407 .WillOnce(Invoke(&loop_handler, &LoopHandler::OnUpdate));
408 EXPECT_CALL(update_client(), Stop()).Times(1);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40409 EXPECT_CALL(scheduler(), Stop()).Times(1);
sorin7c717622015-05-26 19:59:09410
Sorin Jianud20ed8532018-06-28 17:24:31411 {
412 using update_client::jebg_hash;
413 CrxComponent crx_component;
Joshua Pawlicki9656e3922019-09-16 16:34:51414 crx_component.app_id = "jebgalgnebhfojomionfpkfelancnnkf";
Sorin Jianud20ed8532018-06-28 17:24:31415 crx_component.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
416 crx_component.version = base::Version("0.9");
417 crx_component.installer = base::MakeRefCounted<MockInstaller>();
418 EXPECT_TRUE(cus.RegisterComponent(crx_component));
419 }
420 {
421 using update_client::abag_hash;
422 CrxComponent crx_component;
Joshua Pawlicki9656e3922019-09-16 16:34:51423 crx_component.app_id = "abagagagagagagagagagagagagagagag";
Sorin Jianud20ed8532018-06-28 17:24:31424 crx_component.pk_hash.assign(abag_hash, abag_hash + base::size(abag_hash));
425 crx_component.version = base::Version("0.9");
426 crx_component.installer = base::MakeRefCounted<MockInstaller>();
427 EXPECT_TRUE(cus.RegisterComponent(crx_component));
428 }
sorin7c717622015-05-26 19:59:09429
Sorin Jianud20ed8532018-06-28 17:24:31430 OnDemandTester ondemand_tester;
431 ondemand_tester.OnDemand(&cus, "jebgalgnebhfojomionfpkfelancnnkf",
432 OnDemandUpdater::Priority::FOREGROUND);
433 ondemand_tester.OnDemand(&cus, "abagagagagagagagagagagagagagagag",
434 OnDemandUpdater::Priority::BACKGROUND);
sorin4c520182016-08-19 17:27:44435 base::RunLoop().Run();
436
sorin7b8650522016-11-02 18:23:41437 EXPECT_EQ(update_client::Error::INVALID_ARGUMENT,
438 ondemand_tester_component_not_registered.error());
439 EXPECT_EQ(update_client::Error::NONE, ondemand_tester.error());
sorin85953dc2016-03-10 00:32:48440
Sorin Jianud20ed8532018-06-28 17:24:31441 ht.ExpectUniqueSample("ComponentUpdater.Calls", 0, 2);
442 ht.ExpectUniqueSample("ComponentUpdater.UpdateCompleteResult", 0, 2);
443 ht.ExpectTotalCount("ComponentUpdater.UpdateCompleteTime", 2);
sorin7c717622015-05-26 19:59:09444}
445
446// Tests that throttling an update invokes UpdateClient::Install.
447TEST_F(ComponentUpdaterTest, MaybeThrottle) {
448 class LoopHandler {
449 public:
Sorin Jianua8ef73d2017-11-02 16:55:17450 LoopHandler(int max_cnt, base::OnceClosure quit_closure)
451 : max_cnt_(max_cnt), quit_closure_(std::move(quit_closure)) {}
sorin7c717622015-05-26 19:59:09452
Sorin Jianud20ed8532018-06-28 17:24:31453 void OnInstall(const std::string& ids) {
sorin7c717622015-05-26 19:59:09454 static int cnt = 0;
455 ++cnt;
456 if (cnt >= max_cnt_)
Sorin Jianua8ef73d2017-11-02 16:55:17457 std::move(quit_closure_).Run();
sorin7c717622015-05-26 19:59:09458 }
459
460 private:
461 const int max_cnt_;
Sorin Jianua8ef73d2017-11-02 16:55:17462 base::OnceClosure quit_closure_;
sorin7c717622015-05-26 19:59:09463 };
464
sorin85953dc2016-03-10 00:32:48465 base::HistogramTester ht;
466
Tibor Goldschwendt5f173cb2018-06-21 22:50:40467 // Don't run periodic update task.
468 ON_CALL(scheduler(), Schedule(_, _, _, _)).WillByDefault(Return());
sorin7c717622015-05-26 19:59:09469
Sorin Jianua8ef73d2017-11-02 16:55:17470 scoped_refptr<MockInstaller> installer =
471 base::MakeRefCounted<MockInstaller>();
sorin7c717622015-05-26 19:59:09472
473 using update_client::jebg_hash;
474 CrxComponent crx_component;
Joshua Pawlicki9656e3922019-09-16 16:34:51475 crx_component.app_id = "jebgalgnebhfojomionfpkfelancnnkf";
Sorin Jianud20ed8532018-06-28 17:24:31476 crx_component.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
pwnall15745b312016-08-19 21:45:29477 crx_component.version = base::Version("0.9");
sorin7c717622015-05-26 19:59:09478 crx_component.installer = installer;
479
480 LoopHandler loop_handler(1, quit_closure());
Sorin Jianud20ed8532018-06-28 17:24:31481 EXPECT_CALL(update_client(), DoInstall("jebgalgnebhfojomionfpkfelancnnkf"))
sorin7c717622015-05-26 19:59:09482 .WillOnce(Invoke(&loop_handler, &LoopHandler::OnInstall));
sorinecaad3e2015-11-13 19:15:52483 EXPECT_CALL(update_client(), Stop()).Times(1);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40484 EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
485 EXPECT_CALL(scheduler(), Stop()).Times(1);
sorin7c717622015-05-26 19:59:09486
487 EXPECT_TRUE(component_updater().RegisterComponent(crx_component));
488 component_updater().MaybeThrottle(
489 "jebgalgnebhfojomionfpkfelancnnkf",
Sorin Jianua8ef73d2017-11-02 16:55:17490 base::BindOnce(&ComponentUpdaterTest::ReadyCallback));
sorin7c717622015-05-26 19:59:09491
492 RunThreads();
sorin85953dc2016-03-10 00:32:48493
494 ht.ExpectUniqueSample("ComponentUpdater.Calls", 0, 1);
495 ht.ExpectUniqueSample("ComponentUpdater.UpdateCompleteResult", 0, 1);
496 ht.ExpectTotalCount("ComponentUpdater.UpdateCompleteTime", 1);
sorin7c717622015-05-26 19:59:09497}
498
499} // namespace component_updater