| // Copyright 2020 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 "chrome/browser/upgrade_detector/get_installed_version.h" |
| |
| #include <stdio.h> |
| #include <string> |
| |
| #include "base/base_switches.h" |
| #include "base/command_line.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "components/version_info/version_info.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/multiprocess_func_list.h" |
| |
| namespace { |
| |
| constexpr char kChildModeSwitch[] = |
| "get-installed-version-linux-unittest-child-mode"; |
| |
| enum class ChildMode { |
| kNoVersion = 0, |
| kProcessError = 1, |
| kWithMonkey = 2, |
| kWithVersion = 3, |
| }; |
| |
| ChildMode GetChildMode() { |
| const auto switch_value = |
| base::CommandLine::ForCurrentProcess()->GetSwitchValueNative( |
| kChildModeSwitch); |
| int mode_int = 0; |
| base::StringToInt(switch_value, &mode_int); |
| return static_cast<ChildMode>(mode_int); |
| } |
| |
| } // namespace |
| |
| // A function run in a child process to print the desired version to stdout, |
| // just like Chrome does. |
| MULTIPROCESS_TEST_MAIN(GetProductVersionInChildProc) { |
| switch (GetChildMode()) { |
| case ChildMode::kNoVersion: |
| // Return successful process exit without printing anything. |
| return 0; |
| |
| case ChildMode::kProcessError: |
| // Return a bad exit code without printing anything. |
| break; |
| |
| case ChildMode::kWithMonkey: |
| // Print something unexpected and report success. |
| printf("monkey, monkey, monkey"); |
| return 0; |
| |
| case ChildMode::kWithVersion: |
| // Print the current version and report success. |
| printf("%s\n", version_info::GetVersionNumber().c_str()); |
| return 0; |
| } |
| return 1; |
| } |
| |
| // A multi process test that exercises the Linux implementation of |
| // GetInstalledVersion. |
| class GetInstalledVersionLinuxTest : public ::testing::Test { |
| protected: |
| GetInstalledVersionLinuxTest() |
| : original_command_line_(*base::CommandLine::ForCurrentProcess()) {} |
| ~GetInstalledVersionLinuxTest() override { |
| *base::CommandLine::ForCurrentProcess() = original_command_line_; |
| } |
| |
| // Adds switches to the current process command line so that when |
| // GetInstalledVersion relaunches the current process, it has the proper |
| // child proc switch to lead to GetProductVersionInChildProc above and the |
| // mode switch to tell the child how to behave. |
| void AddChildCommandLineSwitches(ChildMode child_mode) { |
| auto* command_line = base::CommandLine::ForCurrentProcess(); |
| command_line->AppendSwitchASCII(switches::kTestChildProcess, |
| "GetProductVersionInChildProc"); |
| command_line->AppendSwitchASCII( |
| kChildModeSwitch, base::NumberToString(static_cast<int>(child_mode))); |
| } |
| |
| private: |
| // The original process command line; saved during construction and restored |
| // during destruction. |
| const base::CommandLine original_command_line_; |
| }; |
| |
| // Tests that an empty instance is returned when the child process reports |
| // nothing. |
| TEST_F(GetInstalledVersionLinuxTest, NoVersion) { |
| AddChildCommandLineSwitches(ChildMode::kNoVersion); |
| InstalledAndCriticalVersion versions = GetInstalledVersion(); |
| EXPECT_FALSE(versions.installed_version.IsValid()); |
| EXPECT_FALSE(versions.critical_version.has_value()); |
| } |
| |
| // Tests that an empty instance is returned when the child process exits with an |
| // error. |
| TEST_F(GetInstalledVersionLinuxTest, ProcessError) { |
| AddChildCommandLineSwitches(ChildMode::kProcessError); |
| InstalledAndCriticalVersion versions = GetInstalledVersion(); |
| ASSERT_FALSE(versions.installed_version.IsValid()); |
| EXPECT_FALSE(versions.critical_version.has_value()); |
| } |
| |
| // Tests that an empty instance is returned when the child process reports a |
| // monkey. |
| TEST_F(GetInstalledVersionLinuxTest, WithMonkey) { |
| AddChildCommandLineSwitches(ChildMode::kWithMonkey); |
| InstalledAndCriticalVersion versions = GetInstalledVersion(); |
| ASSERT_FALSE(versions.installed_version.IsValid()); |
| EXPECT_FALSE(versions.critical_version.has_value()); |
| } |
| |
| // Tests that the expected instance is returned when the child process reports a |
| // valid version. |
| TEST_F(GetInstalledVersionLinuxTest, WithVersion) { |
| AddChildCommandLineSwitches(ChildMode::kWithVersion); |
| InstalledAndCriticalVersion versions = GetInstalledVersion(); |
| ASSERT_TRUE(versions.installed_version.IsValid()); |
| EXPECT_EQ(versions.installed_version, version_info::GetVersion()); |
| EXPECT_FALSE(versions.critical_version.has_value()); |
| } |