[M120 Migration][VD] Enable direct rendering for TVPlus
[platform/framework/web/chromium-efl.git] / components / component_updater / component_installer_unittest.cc
1 // Copyright 2016 The Chromium Authors
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 <iterator>
6 #include <memory>
7 #include <string>
8 #include <utility>
9 #include <vector>
10
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/functional/bind.h"
14 #include "base/functional/callback.h"
15 #include "base/functional/callback_helpers.h"
16 #include "base/memory/raw_ptr.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/path_service.h"
19 #include "base/run_loop.h"
20 #include "base/sequence_checker.h"
21 #include "base/strings/strcat.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/task/sequenced_task_runner.h"
24 #include "base/test/bind.h"
25 #include "base/test/scoped_path_override.h"
26 #include "base/test/task_environment.h"
27 #include "base/values.h"
28 #include "base/version.h"
29 #include "components/component_updater/component_installer.h"
30 #include "components/component_updater/component_updater_paths.h"
31 #include "components/component_updater/component_updater_service.h"
32 #include "components/component_updater/component_updater_service_internal.h"
33 #include "components/crx_file/crx_verifier.h"
34 #include "components/prefs/testing_pref_service.h"
35 #include "components/update_client/component_unpacker.h"
36 #include "components/update_client/crx_update_item.h"
37 #include "components/update_client/patcher.h"
38 #include "components/update_client/test_configurator.h"
39 #include "components/update_client/test_utils.h"
40 #include "components/update_client/unzipper.h"
41 #include "components/update_client/update_client.h"
42 #include "components/update_client/update_client_errors.h"
43 #include "testing/gmock/include/gmock/gmock.h"
44 #include "testing/gtest/include/gtest/gtest.h"
45 #include "third_party/abseil-cpp/absl/types/optional.h"
46
47 using ComponentUnpacker = update_client::ComponentUnpacker;
48 using Configurator = update_client::Configurator;
49 using CrxUpdateItem = update_client::CrxUpdateItem;
50 using TestConfigurator = update_client::TestConfigurator;
51 using UpdateClient = update_client::UpdateClient;
52
53 using ::testing::_;
54 using ::testing::Invoke;
55
56 namespace component_updater {
57 namespace {
58
59 // This hash corresponds to jebgalgnebhfojomionfpkfelancnnkf.crx.
60 constexpr uint8_t kSha256Hash[] = {
61     0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec, 0x8e, 0xd5, 0xfa,
62     0x54, 0xb0, 0xd2, 0xdd, 0xa5, 0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47,
63     0xf6, 0xc4, 0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40};
64 constexpr base::FilePath::CharType relative_install_dir[] =
65     FILE_PATH_LITERAL("fake");
66
67 class MockUpdateClient : public UpdateClient {
68  public:
69   MockUpdateClient() = default;
70
71   base::RepeatingClosure Install(
72       const std::string& id,
73       CrxDataCallback crx_data_callback,
74       CrxStateChangeCallback crx_state_change_callback,
75       Callback callback) override {
76     DoInstall(id, std::move(crx_data_callback));
77     std::move(callback).Run(update_client::Error::NONE);
78     return base::DoNothing();
79   }
80
81   void Update(const std::vector<std::string>& ids,
82               CrxDataCallback crx_data_callback,
83               CrxStateChangeCallback crx_state_change_callback,
84               bool is_foreground,
85               Callback callback) override {
86     DoUpdate(ids, std::move(crx_data_callback));
87     std::move(callback).Run(update_client::Error::NONE);
88   }
89
90   void SendUninstallPing(const CrxComponent& crx_component,
91                          int reason,
92                          Callback callback) override {
93     DoSendUninstallPing(crx_component, reason);
94     std::move(callback).Run(update_client::Error::NONE);
95   }
96
97   MOCK_METHOD5(SendInstallPing,
98                void(const CrxComponent& crx_component,
99                     bool success,
100                     int error_code,
101                     int extra_code1,
102                     Callback callback));
103   MOCK_METHOD1(AddObserver, void(Observer* observer));
104   MOCK_METHOD1(RemoveObserver, void(Observer* observer));
105   MOCK_METHOD2(DoInstall,
106                void(const std::string& id,
107                     const CrxDataCallback& crx_data_callback));
108   MOCK_METHOD2(DoUpdate,
109                void(const std::vector<std::string>& ids,
110                     const CrxDataCallback& crx_data_callback));
111   MOCK_METHOD5(CheckForUpdate,
112                void(const std::string& ids,
113                     CrxDataCallback crx_data_callback,
114                     CrxStateChangeCallback crx_state_change_callback,
115                     bool is_foreground,
116                     Callback callback));
117   MOCK_CONST_METHOD2(GetCrxUpdateState,
118                      bool(const std::string& id, CrxUpdateItem* update_item));
119   MOCK_CONST_METHOD1(IsUpdating, bool(const std::string& id));
120   MOCK_METHOD0(Stop, void());
121   MOCK_METHOD2(DoSendUninstallPing,
122                void(const CrxComponent& crx_component, int reason));
123
124  private:
125   ~MockUpdateClient() override = default;
126 };
127
128 class MockInstallerPolicy : public ComponentInstallerPolicy {
129  public:
130   using ComponentReadyCallback =
131       base::OnceCallback<void(const base::Version& version,
132                               const base::FilePath& install_dir,
133                               base::Value::Dict manifest)>;
134   explicit MockInstallerPolicy(
135       ComponentReadyCallback component_ready_cb = ComponentReadyCallback())
136       : component_ready_cb_(std::move(component_ready_cb)) {}
137   ~MockInstallerPolicy() override = default;
138
139   bool VerifyInstallation(const base::Value::Dict& manifest,
140                           const base::FilePath& dir) const override {
141     return true;
142   }
143
144   bool SupportsGroupPolicyEnabledComponentUpdates() const override {
145     return true;
146   }
147
148   bool RequiresNetworkEncryption() const override { return true; }
149
150   update_client::CrxInstaller::Result OnCustomInstall(
151       const base::Value::Dict& manifest,
152       const base::FilePath& install_dir) override {
153     return update_client::CrxInstaller::Result(0);
154   }
155
156   void OnCustomUninstall() override {}
157
158   void ComponentReady(const base::Version& version,
159                       const base::FilePath& install_dir,
160                       base::Value::Dict manifest) override {
161     if (component_ready_cb_) {
162       std::move(component_ready_cb_)
163           .Run(version, install_dir, std::move(manifest));
164     }
165   }
166
167   base::FilePath GetRelativeInstallDir() const override {
168     return base::FilePath(relative_install_dir);
169   }
170
171   void GetHash(std::vector<uint8_t>* hash) const override { GetPkHash(hash); }
172
173   std::string GetName() const override { return "fake name"; }
174
175   update_client::InstallerAttributes GetInstallerAttributes() const override {
176     update_client::InstallerAttributes installer_attributes;
177     installer_attributes["ap"] = "fake-ap";
178     installer_attributes["is-enterprise"] = "1";
179     return installer_attributes;
180   }
181
182  private:
183   static void GetPkHash(std::vector<uint8_t>* hash) {
184     hash->assign(std::begin(kSha256Hash), std::end(kSha256Hash));
185   }
186
187   ComponentReadyCallback component_ready_cb_;
188 };
189
190 class MockUpdateScheduler : public UpdateScheduler {
191  public:
192   MOCK_METHOD4(Schedule,
193                void(const base::TimeDelta& initial_delay,
194                     const base::TimeDelta& delay,
195                     const UserTask& user_task,
196                     const OnStopTaskCallback& on_stop));
197   MOCK_METHOD0(Stop, void());
198 };
199
200 class ComponentInstallerTest : public testing::Test {
201  public:
202   ComponentInstallerTest();
203   ~ComponentInstallerTest() override;
204
205   MockUpdateClient& update_client() { return *update_client_; }
206   ComponentUpdateService* component_updater() {
207     return component_updater_.get();
208   }
209   scoped_refptr<TestConfigurator> configurator() const { return config_; }
210   base::OnceClosure quit_closure() { return runloop_.QuitClosure(); }
211   MockUpdateScheduler& scheduler() { return *scheduler_; }
212
213  protected:
214   void RunThreads();
215   void Unpack(const base::FilePath& crx_path);
216   ComponentUnpacker::Result result() const { return result_; }
217
218   base::test::TaskEnvironment task_environment_;
219
220  private:
221   void UnpackComplete(const ComponentUnpacker::Result& result);
222   void Schedule(const base::TimeDelta& initial_delay,
223                 const base::TimeDelta& delay,
224                 const UpdateScheduler::UserTask& user_task,
225                 const UpdateScheduler::OnStopTaskCallback& on_stop);
226
227   const scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_ =
228       base::SequencedTaskRunner::GetCurrentDefault();
229   base::RunLoop runloop_;
230
231   std::unique_ptr<TestingPrefServiceSimple> pref_ =
232       std::make_unique<TestingPrefServiceSimple>();
233
234   scoped_refptr<TestConfigurator> config_ =
235       base::MakeRefCounted<TestConfigurator>(pref_.get());
236   scoped_refptr<MockUpdateClient> update_client_ =
237       base::MakeRefCounted<MockUpdateClient>();
238   ComponentUnpacker::Result result_;
239   std::unique_ptr<ComponentUpdateService> component_updater_;
240   raw_ptr<MockUpdateScheduler> scheduler_ = nullptr;
241 };
242
243 ComponentInstallerTest::ComponentInstallerTest() {
244   EXPECT_CALL(update_client(), AddObserver(_)).Times(1);
245   auto scheduler = std::make_unique<MockUpdateScheduler>();
246   scheduler_ = scheduler.get();
247   ON_CALL(*scheduler_, Schedule(_, _, _, _))
248       .WillByDefault(Invoke(this, &ComponentInstallerTest::Schedule));
249   component_updater_ = std::make_unique<CrxUpdateService>(
250       config_, std::move(scheduler), update_client_, "");
251   RegisterComponentUpdateServicePrefs(pref_->registry());
252   update_client::RegisterPrefs(pref_->registry());
253 }
254
255 ComponentInstallerTest::~ComponentInstallerTest() {
256   EXPECT_CALL(update_client(), RemoveObserver(_)).Times(1);
257 }
258
259 void ComponentInstallerTest::RunThreads() {
260   runloop_.Run();
261 }
262
263 void ComponentInstallerTest::Unpack(const base::FilePath& crx_path) {
264   auto config = base::MakeRefCounted<TestConfigurator>();
265   auto component_unpacker = base::MakeRefCounted<ComponentUnpacker>(
266       std::vector<uint8_t>(std::begin(kSha256Hash), std::end(kSha256Hash)),
267       crx_path, nullptr, config->GetUnzipperFactory()->Create(),
268       config->GetPatcherFactory()->Create(), crx_file::VerifierFormat::CRX3);
269   component_unpacker->Unpack(base::BindOnce(
270       &ComponentInstallerTest::UnpackComplete, base::Unretained(this)));
271   RunThreads();
272 }
273
274 void ComponentInstallerTest::UnpackComplete(
275     const ComponentUnpacker::Result& result) {
276   result_ = result;
277
278   EXPECT_EQ(update_client::UnpackerError::kNone, result_.error);
279   EXPECT_EQ(0, result_.extended_error);
280
281   main_thread_task_runner_->PostTask(FROM_HERE, quit_closure());
282 }
283
284 void ComponentInstallerTest::Schedule(
285     const base::TimeDelta& initial_delay,
286     const base::TimeDelta& delay,
287     const UpdateScheduler::UserTask& user_task,
288     const UpdateScheduler::OnStopTaskCallback& on_stop) {
289   user_task.Run(base::DoNothing());
290 }
291
292 }  // namespace
293
294 absl::optional<base::FilePath> CreateComponentDirectory(
295     const base::FilePath& base_dir,
296     const std::string& name,
297     const std::string& version,
298     const std::string& min_env_version) {
299   base::FilePath component_dir =
300       base_dir.AppendASCII(name).AppendASCII(version);
301
302   if (!base::CreateDirectory(component_dir))
303     return absl::nullopt;
304
305   if (!base::WriteFile(component_dir.AppendASCII("manifest.json"),
306                        base::StringPrintf(R"({
307         "name": "%s",
308         "version": "%s",
309         "min_env_version": "%s"
310     })",
311                                           name.c_str(), version.c_str(),
312                                           min_env_version.c_str())))
313     return absl::nullopt;
314
315   return absl::make_optional(component_dir);
316 }
317
318 // Tests that the component metadata is propagated from the component installer
319 // and its component policy, through the instance of the CrxComponent, to the
320 // component updater service.
321 TEST_F(ComponentInstallerTest, RegisterComponent) {
322   class LoopHandler {
323    public:
324     LoopHandler(int max_cnt, base::OnceClosure quit_closure)
325         : max_cnt_(max_cnt), quit_closure_(std::move(quit_closure)) {}
326
327     void OnUpdate(const std::vector<std::string>& ids,
328                   const UpdateClient::CrxDataCallback& crx_data_callback) {
329       static int cnt = 0;
330       ++cnt;
331       if (cnt >= max_cnt_)
332         std::move(quit_closure_).Run();
333     }
334
335    private:
336     const int max_cnt_;
337     base::OnceClosure quit_closure_;
338   };
339
340   base::ScopedPathOverride scoped_path_override(DIR_COMPONENT_USER);
341
342   const std::string id("jebgalgnebhfojomionfpkfelancnnkf");
343
344   // Quit after one update check has been fired.
345   LoopHandler loop_handler(1, quit_closure());
346   EXPECT_CALL(update_client(), DoUpdate(_, _))
347       .WillRepeatedly(Invoke(&loop_handler, &LoopHandler::OnUpdate));
348
349   EXPECT_CALL(update_client(), GetCrxUpdateState(id, _)).Times(1);
350   EXPECT_CALL(update_client(), Stop()).Times(1);
351   EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
352   EXPECT_CALL(scheduler(), Stop()).Times(1);
353
354   auto installer = base::MakeRefCounted<ComponentInstaller>(
355       std::make_unique<MockInstallerPolicy>());
356   installer->Register(component_updater(), base::OnceClosure());
357
358   RunThreads();
359
360   CrxUpdateItem item;
361   EXPECT_TRUE(component_updater()->GetComponentDetails(id, &item));
362   ASSERT_TRUE(item.component);
363   const CrxComponent& component = *item.component;
364
365   update_client::InstallerAttributes expected_attrs;
366   expected_attrs["ap"] = "fake-ap";
367   expected_attrs["is-enterprise"] = "1";
368
369   EXPECT_EQ(
370       std::vector<uint8_t>(std::begin(kSha256Hash), std::end(kSha256Hash)),
371       component.pk_hash);
372   EXPECT_EQ(base::Version("0.0.0.0"), component.version);
373   EXPECT_TRUE(component.fingerprint.empty());
374   EXPECT_STREQ("fake name", component.name.c_str());
375   EXPECT_EQ(expected_attrs, component.installer_attributes);
376   EXPECT_TRUE(component.requires_network_encryption);
377 }
378
379 // Tests that `ComponentInstallerPolicy::ComponentReady` and the completion
380 // callback of `ComponentInstaller::Register` are called in sequence.
381 TEST_F(ComponentInstallerTest, InstallerRegister_CheckSequence) {
382   class RegisterHandler {
383    public:
384     virtual ~RegisterHandler() = default;
385
386     virtual void ComponentReady() = 0;
387     virtual void RegisterComplete() = 0;
388   };
389
390   // Allows defining call expectations on its functions when the functions
391   // are invoked by callbacks posted from `ComponentInstaller::Register`.
392   class MockRegisterHandler : public RegisterHandler {
393    public:
394     MockRegisterHandler() {
395       ON_CALL(*this, ComponentReady)
396           .WillByDefault(Invoke(this, &MockRegisterHandler::CheckSequence));
397       ON_CALL(*this, RegisterComplete)
398           .WillByDefault(Invoke(this, &MockRegisterHandler::CheckSequence));
399     }
400
401     MOCK_METHOD(void, ComponentReady, (), (override));
402     MOCK_METHOD(void, RegisterComplete, (), (override));
403
404    private:
405     void CheckSequence() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); }
406     SEQUENCE_CHECKER(sequence_checker_);
407   };
408
409   base::ScopedPathOverride scoped_path_override(DIR_COMPONENT_USER);
410
411   // Install a CRX component so that `ComponentInstallerPolicy::ComponentReady`
412   // can be invoked later on.
413   {
414     base::RunLoop run_loop;
415     auto installer = base::MakeRefCounted<ComponentInstaller>(
416         std::make_unique<MockInstallerPolicy>());
417     Unpack(
418         update_client::GetTestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"));
419     ASSERT_EQ(result().error, update_client::UnpackerError::kNone);
420     base::FilePath base_dir;
421     ASSERT_TRUE(base::PathService::Get(DIR_COMPONENT_USER, &base_dir));
422     base_dir = base_dir.Append(relative_install_dir);
423     ASSERT_TRUE(base::CreateDirectory(base_dir));
424     installer->Install(
425         result().unpack_path, update_client::jebg_public_key, nullptr,
426         base::DoNothing(),
427         base::BindLambdaForTesting(
428             [&run_loop](const update_client::CrxInstaller::Result& result) {
429               ASSERT_EQ(result.error, 0);
430               run_loop.QuitClosure().Run();
431             }));
432     run_loop.Run();
433   }
434
435   base::RunLoop run_loop;
436   EXPECT_CALL(update_client(), DoUpdate(_, _)).WillOnce(Invoke([&run_loop]() {
437     run_loop.QuitClosure().Run();
438   }));
439
440   // Set up expectations for uninteresting calls on the mocks due to component
441   // updater waking up after the component is registered.
442   EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
443   EXPECT_CALL(scheduler(), Stop()).Times(1);
444   EXPECT_CALL(update_client(), Stop()).Times(1);
445
446   MockRegisterHandler mock_register_handler;
447   {
448     ::testing::InSequence seq;
449     EXPECT_CALL(mock_register_handler, ComponentReady()).Times(1);
450     EXPECT_CALL(mock_register_handler, RegisterComplete()).Times(1);
451   }
452
453   auto installer_policy =
454       std::make_unique<MockInstallerPolicy>(base::BindLambdaForTesting(
455           [&mock_register_handler](const base::Version& version,
456                                    const base::FilePath& install_dir,
457                                    base::Value::Dict manifest) {
458             EXPECT_EQ(version.GetString(), "1.0");
459             mock_register_handler.ComponentReady();
460           }));
461   auto installer =
462       base::MakeRefCounted<ComponentInstaller>(std::move(installer_policy));
463   installer->Register(component_updater(),
464                       base::BindLambdaForTesting([&mock_register_handler]() {
465                         mock_register_handler.RegisterComplete();
466                       }));
467   run_loop.Run();
468 }
469
470 // Tests that the unpack path is removed when the install succeeded.
471 TEST_F(ComponentInstallerTest, UnpackPathInstallSuccess) {
472   auto installer = base::MakeRefCounted<ComponentInstaller>(
473       std::make_unique<MockInstallerPolicy>());
474
475   Unpack(
476       update_client::GetTestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"));
477
478   const auto unpack_path = result().unpack_path;
479   EXPECT_TRUE(base::DirectoryExists(unpack_path));
480   EXPECT_EQ(update_client::jebg_public_key, result().public_key);
481
482   base::ScopedPathOverride scoped_path_override(DIR_COMPONENT_USER);
483   base::FilePath base_dir;
484   EXPECT_TRUE(base::PathService::Get(DIR_COMPONENT_USER, &base_dir));
485   base_dir = base_dir.Append(relative_install_dir);
486   EXPECT_TRUE(base::CreateDirectory(base_dir));
487   installer->Install(
488       unpack_path, update_client::jebg_public_key, nullptr, base::DoNothing(),
489       base::BindOnce([](const update_client::CrxInstaller::Result& result) {
490         EXPECT_EQ(0, result.error);
491       }));
492
493   task_environment_.RunUntilIdle();
494
495   EXPECT_FALSE(base::PathExists(unpack_path));
496   EXPECT_CALL(update_client(), Stop()).Times(1);
497   EXPECT_CALL(scheduler(), Stop()).Times(1);
498 }
499
500 // Tests that the unpack path is removed when the install failed.
501 TEST_F(ComponentInstallerTest, UnpackPathInstallError) {
502   auto installer = base::MakeRefCounted<ComponentInstaller>(
503       std::make_unique<MockInstallerPolicy>());
504
505   Unpack(
506       update_client::GetTestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"));
507
508   const auto unpack_path = result().unpack_path;
509   EXPECT_TRUE(base::DirectoryExists(unpack_path));
510
511   // Test the precondition that DIR_COMPONENT_USER is not registered with
512   // the path service.
513   base::FilePath base_dir;
514   EXPECT_FALSE(base::PathService::Get(DIR_COMPONENT_USER, &base_dir));
515
516   // Calling |Install| fails since DIR_COMPONENT_USER does not exist.
517   installer->Install(
518       unpack_path, update_client::jebg_public_key, nullptr, base::DoNothing(),
519       base::BindOnce([](const update_client::CrxInstaller::Result& result) {
520         EXPECT_EQ(static_cast<int>(
521                       update_client::InstallError::NO_DIR_COMPONENT_USER),
522                   result.error);
523       }));
524
525   task_environment_.RunUntilIdle();
526
527   EXPECT_FALSE(base::PathExists(unpack_path));
528   EXPECT_CALL(update_client(), Stop()).Times(1);
529   EXPECT_CALL(scheduler(), Stop()).Times(1);
530 }
531
532 TEST_F(ComponentInstallerTest, SelectComponentVersion) {
533   auto installer = base::MakeRefCounted<ComponentInstaller>(
534       std::make_unique<MockInstallerPolicy>());
535
536   base::FilePath base_dir;
537   base::ScopedPathOverride scoped_path_override(DIR_COMPONENT_USER);
538   ASSERT_TRUE(base::PathService::Get(DIR_COMPONENT_USER, &base_dir));
539   base_dir = base_dir.AppendASCII("select_component_version_test");
540
541   for (const auto* n : {"1", "2", "3", "4", "5", "6", "7"}) {
542     CreateComponentDirectory(base_dir, "test_component",
543                              base::StrCat({n, ".0.0.0"}), "0.0.1");
544   }
545
546   base_dir = base_dir.AppendASCII("test_component");
547
548   absl::optional<base::Version> selected_component;
549
550   auto registration_info =
551       base::MakeRefCounted<ComponentInstaller::RegistrationInfo>();
552   selected_component = installer->SelectComponentVersion(
553       base::Version("1.0.0.0"), base_dir, registration_info);
554   ASSERT_TRUE(selected_component &&
555               selected_component == base::Version("1.0.0.0"));
556   ASSERT_EQ(registration_info->version, base::Version("1.0.0.0"));
557
558   // Case where no valid bundled or registered version.
559   registration_info =
560       base::MakeRefCounted<ComponentInstaller::RegistrationInfo>();
561   selected_component = installer->SelectComponentVersion(
562       base::Version("0.0.0.0"), base_dir, registration_info);
563   ASSERT_TRUE(selected_component &&
564               *selected_component == base::Version("7.0.0.0"));
565   ASSERT_EQ(registration_info->version, base::Version("7.0.0.0"));
566
567   registration_info->version = base::Version("3.0.0.0");
568   selected_component = installer->SelectComponentVersion(
569       base::Version("5.0.0.0"), base_dir, registration_info);
570   ASSERT_TRUE(selected_component &&
571               *selected_component == base::Version("5.0.0.0"));
572   ASSERT_EQ(registration_info->version, base::Version("5.0.0.0"));
573
574   registration_info->version = base::Version("4.0.0.0");
575   selected_component = installer->SelectComponentVersion(
576       base::Version("0.0.0.0"), base_dir, registration_info);
577   ASSERT_TRUE(selected_component &&
578               *selected_component == base::Version("7.0.0.0"));
579   ASSERT_EQ(registration_info->version, base::Version("7.0.0.0"));
580
581   registration_info->version = base::Version("12.0.0.0");
582   selected_component = installer->SelectComponentVersion(
583       base::Version("1.0.0.0"), base_dir, registration_info);
584   ASSERT_FALSE(selected_component);
585   ASSERT_EQ(registration_info->version, base::Version("12.0.0.0"));
586
587   registration_info->version = base::Version("6.0.0.0");
588   selected_component = installer->SelectComponentVersion(
589       base::Version("1.0.0.0"), base_dir, registration_info);
590   ASSERT_TRUE(selected_component &&
591               *selected_component == base::Version("7.0.0.0"));
592   ASSERT_EQ(registration_info->version, base::Version("7.0.0.0"));
593 }
594
595 }  // namespace component_updater