| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/updater/util/util.h" |
| |
| #include <cstdint> |
| #include <optional> |
| #include <sstream> |
| #include <string> |
| |
| #include "base/command_line.h" |
| #include "base/files/file_enumerator.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/functional/bind.h" |
| #include "base/functional/callback.h" |
| #include "base/path_service.h" |
| #include "base/run_loop.h" |
| #include "base/sequence_checker.h" |
| #include "base/strings/strcat.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/task/thread_pool.h" |
| #include "base/test/bind.h" |
| #include "base/test/scoped_command_line.h" |
| #include "base/test/task_environment.h" |
| #include "base/version.h" |
| #include "build/build_config.h" |
| #include "chrome/updater/constants.h" |
| #include "chrome/updater/tag.h" |
| #include "chrome/updater/test/test_scope.h" |
| #include "chrome/updater/test/unit_test_util.h" |
| #include "chrome/updater/updater_branding.h" |
| #include "chrome/updater/updater_scope.h" |
| #include "chrome/updater/updater_version.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace updater { |
| |
| struct UtilTagArgsTestCase { |
| const std::string tag_switch; |
| }; |
| |
| class UtilTagArgsTest : public ::testing::TestWithParam<UtilTagArgsTestCase> {}; |
| |
| INSTANTIATE_TEST_SUITE_P(UtilTagArgsTestCases, |
| UtilTagArgsTest, |
| ::testing::ValuesIn(std::vector<UtilTagArgsTestCase>{ |
| {kInstallSwitch}, |
| {kHandoffSwitch}, |
| })); |
| |
| TEST_P(UtilTagArgsTest, AppArgsAndAP) { |
| base::test::ScopedCommandLine original_command_line; |
| { |
| base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| command_line->AppendSwitchUTF8(GetParam().tag_switch, |
| "appguid=8a69f345-c564-463c-aff1-" |
| "a69d9e530f96&appname=TestApp&ap=TestAP"); |
| |
| // Test GetAppArgs. |
| EXPECT_EQ(GetAppArgs("NonExistentAppId"), std::nullopt); |
| std::optional<tagging::AppArgs> app_args = |
| GetAppArgs("8a69f345-c564-463c-aff1-a69d9e530f96"); |
| ASSERT_NE(app_args, std::nullopt); |
| EXPECT_EQ(app_args->app_id, "8a69f345-c564-463c-aff1-a69d9e530f96"); |
| EXPECT_EQ(app_args->app_name, "TestApp"); |
| } |
| } |
| |
| TEST_P(UtilTagArgsTest, GetTagArgsForCommandLine) { |
| base::CommandLine command_line(base::FilePath(FILE_PATH_LITERAL("my.exe"))); |
| command_line.AppendSwitchUTF8(GetParam().tag_switch, |
| "appguid={8a69}&appname=Chrome"); |
| command_line.AppendSwitchUTF8(kAppArgsSwitch, |
| "&appguid={8a69}&installerdata=%7B%22homepage%" |
| "22%3A%22http%3A%2F%2Fwww.google.com%"); |
| command_line.AppendSwitch(kSilentSwitch); |
| command_line.AppendSwitchUTF8(kSessionIdSwitch, "{123-456}"); |
| |
| TagParsingResult result = GetTagArgsForCommandLine(command_line); |
| EXPECT_EQ(result.error, tagging::ErrorCode::kSuccess); |
| EXPECT_EQ(result.tag_args->apps.size(), size_t{1}); |
| EXPECT_EQ(result.tag_args->apps[0].app_id, "{8a69}"); |
| EXPECT_EQ(result.tag_args->apps[0].app_name, "Chrome"); |
| EXPECT_EQ(result.tag_args->apps[0].encoded_installer_data, |
| "%7B%22homepage%22%3A%22http%3A%2F%2Fwww.google.com%"); |
| } |
| |
| TEST(Util, WriteInstallerDataToTempFile) { |
| base::FilePath directory; |
| ASSERT_TRUE(base::PathService::Get(base::DIR_MODULE, &directory)); |
| |
| EXPECT_FALSE(WriteInstallerDataToTempFile(directory, "")); |
| |
| const std::string kInstallerData = |
| R"({"distribution":{"msi":true,"allow_downgrade":false}})"; |
| EXPECT_FALSE(WriteInstallerDataToTempFile( |
| directory.Append(FILE_PATH_LITERAL("NonExistentDirectory")), |
| kInstallerData)); |
| |
| const std::optional<base::FilePath> installer_data_file = |
| WriteInstallerDataToTempFile(directory, kInstallerData); |
| ASSERT_TRUE(installer_data_file); |
| |
| std::string contents; |
| EXPECT_TRUE(base::ReadFileToString(*installer_data_file, &contents)); |
| EXPECT_EQ(base::StrCat({kUTF8BOM, kInstallerData}), contents); |
| |
| EXPECT_TRUE(base::DeleteFile(*installer_data_file)); |
| } |
| |
| TEST(Util, GetCrashDatabasePath) { |
| std::optional<base::FilePath> crash_database_path( |
| GetCrashDatabasePath(GetUpdaterScopeForTesting())); |
| ASSERT_TRUE(crash_database_path); |
| EXPECT_EQ(crash_database_path->BaseName().value(), |
| FILE_PATH_LITERAL("Crashpad")); |
| } |
| |
| TEST(Util, GetCrxCacheDirectory) { |
| std::optional<base::FilePath> diff_cache_directory( |
| GetCrxCacheDirectory(GetUpdaterScopeForTesting())); |
| ASSERT_TRUE(diff_cache_directory); |
| EXPECT_EQ(diff_cache_directory->BaseName().value(), |
| FILE_PATH_LITERAL("crx_cache")); |
| } |
| |
| TEST(Util, StreamEnumValue) { |
| enum class TestEnum { |
| kValue1 = 0L, |
| kValue2 = 5L, |
| kValue3, |
| }; |
| |
| std::stringstream output; |
| output << "First: " << TestEnum::kValue1 << ", second: " << TestEnum::kValue2 |
| << ", third: " << TestEnum::kValue3; |
| EXPECT_EQ(output.str(), "First: 0, second: 5, third: 6"); |
| } |
| |
| TEST(Util, DeleteExcept) { |
| EXPECT_FALSE(DeleteExcept({})); |
| |
| base::ScopedTempDir temp_dir; |
| ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| |
| const base::FilePath except_executable(temp_dir.GetPath().Append( |
| FILE_PATH_LITERAL("except_executable.executable"))); |
| test::SetupMockUpdater(except_executable); |
| EXPECT_TRUE(DeleteExcept(except_executable)); |
| test::ExpectOnlyMockUpdater(except_executable); |
| } |
| |
| TEST(Util, CeilingDivide) { |
| EXPECT_EQ(CeilingDivide(0, 1), 0); |
| EXPECT_EQ(CeilingDivide(1, 2), 1); |
| EXPECT_EQ(CeilingDivide(1, 1), 1); |
| EXPECT_EQ(CeilingDivide(3, 2), 2); |
| EXPECT_EQ(CeilingDivide(5, 3), 2); |
| EXPECT_EQ(CeilingDivide(4, 2), 2); |
| |
| EXPECT_EQ(CeilingDivide(-1, 2), 0); |
| EXPECT_EQ(CeilingDivide(-1, 1), -1); |
| EXPECT_EQ(CeilingDivide(-3, 2), -1); |
| EXPECT_EQ(CeilingDivide(-5, 3), -1); |
| EXPECT_EQ(CeilingDivide(-2, 1), -2); |
| EXPECT_EQ(CeilingDivide(-4, 2), -2); |
| |
| EXPECT_EQ(CeilingDivide(1, -2), 0); |
| EXPECT_EQ(CeilingDivide(1, -1), -1); |
| EXPECT_EQ(CeilingDivide(3, -2), -1); |
| EXPECT_EQ(CeilingDivide(5, -3), -1); |
| EXPECT_EQ(CeilingDivide(2, -1), -2); |
| EXPECT_EQ(CeilingDivide(4, -2), -2); |
| |
| EXPECT_EQ(CeilingDivide(-0, -1), 0); |
| EXPECT_EQ(CeilingDivide(-1, -2), 1); |
| EXPECT_EQ(CeilingDivide(-1, -1), 1); |
| EXPECT_EQ(CeilingDivide(-3, -2), 2); |
| EXPECT_EQ(CeilingDivide(-5, -3), 2); |
| EXPECT_EQ(CeilingDivide(-4, -2), 2); |
| } |
| |
| TEST(Util, OptionalBaseInsertion) { |
| // Tests insertion in a gTest expectation. |
| std::optional<base::FilePath> file_path; |
| EXPECT_TRUE(true) << file_path; |
| |
| std::stringstream os; |
| os << file_path << std::endl; |
| EXPECT_EQ(os.str(), "std::nullopt\n"); |
| os.str(""); |
| file_path = std::make_optional<base::FilePath>(FILE_PATH_LITERAL("test")); |
| os << file_path << std::endl; |
| EXPECT_EQ(os.str(), "test\n"); |
| } |
| |
| TEST(WinUtil, GetDownloadProgress) { |
| EXPECT_EQ(GetDownloadProgress(0, 50), 0); |
| EXPECT_EQ(GetDownloadProgress(12, 50), 24); |
| EXPECT_EQ(GetDownloadProgress(25, 50), 50); |
| EXPECT_EQ(GetDownloadProgress(50, 50), 100); |
| EXPECT_EQ(GetDownloadProgress(50, 50), 100); |
| EXPECT_EQ(GetDownloadProgress(0, -1), -1); |
| EXPECT_EQ(GetDownloadProgress(-1, -1), -1); |
| EXPECT_EQ(GetDownloadProgress(50, 0), -1); |
| } |
| |
| TEST(Util, ToSignedIntegral) { |
| EXPECT_EQ(ToSignedIntegral(uint8_t{0}), 0); |
| EXPECT_EQ(ToSignedIntegral(uint8_t{0x7F}), 0x7F); |
| EXPECT_EQ(ToSignedIntegral(uint8_t{0x80}), -1); |
| EXPECT_EQ(ToSignedIntegral(uint32_t{0}), 0); |
| EXPECT_EQ(ToSignedIntegral(uint32_t{1357}), 1357); |
| EXPECT_EQ(ToSignedIntegral(uint32_t{0x7FFFFFFF}), 0x7FFFFFFF); |
| EXPECT_EQ(ToSignedIntegral(uint32_t{0x80000000}), -1); |
| EXPECT_EQ(ToSignedIntegral(uint32_t{0xFFFFFFFF}), -1); |
| EXPECT_EQ(ToSignedIntegral(uint64_t{0x7FFFFFFFFFFFFFFF}), 0x7FFFFFFFFFFFFFFF); |
| EXPECT_EQ(ToSignedIntegral(uint64_t{0x8000000000000000}), -1); |
| } |
| |
| #if BUILDFLAG(IS_WIN) |
| class UtilTaskNameTest : public ::testing::TestWithParam<std::string> { |
| protected: |
| base::Version version() const { return base::Version(GetParam()); } |
| }; |
| |
| INSTANTIATE_TEST_SUITE_P(UtilTaskNameTestCases, |
| UtilTaskNameTest, |
| ::testing::Values(kUpdaterVersion, |
| "1.2.3.4", |
| "199.28537.11717")); |
| |
| TEST_P(UtilTaskNameTest, GetTaskNamePrefix) { |
| EXPECT_EQ( |
| GetTaskNamePrefix(GetUpdaterScopeForTesting(), version()), |
| base::StrCat( |
| {base::UTF8ToWide(PRODUCT_FULLNAME_STRING), L"Task", |
| IsSystemInstall(GetUpdaterScopeForTesting()) ? L"System" : L"User", |
| base::UTF8ToWide(version().GetString())})); |
| } |
| |
| TEST_P(UtilTaskNameTest, GetTaskDisplayName) { |
| EXPECT_EQ( |
| GetTaskDisplayName(GetUpdaterScopeForTesting(), version()), |
| base::StrCat( |
| {base::UTF8ToWide(PRODUCT_FULLNAME_STRING), L" Task ", |
| IsSystemInstall(GetUpdaterScopeForTesting()) ? L"System " : L"User ", |
| base::UTF8ToWide(version().GetString())})); |
| } |
| #endif // BUILDFLAG(IS_WIN) |
| |
| } // namespace updater |