blob: f5a3b6f1afe2944e07e0777f2c5de5f27f431987 [file]
// 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());
}