Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7497)

Unified Diff: chrome/install_static/product_install_details_unittest.cc

Issue 2422643002: Windows install_static refactor. (Closed)
Patch Set: sync to position 431863 Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/install_static/product_install_details_unittest.cc
diff --git a/chrome/install_static/product_install_details_unittest.cc b/chrome/install_static/product_install_details_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c0d1f82ce01f3aced8a92e667ff6dbf13f7b0bcf
--- /dev/null
+++ b/chrome/install_static/product_install_details_unittest.cc
@@ -0,0 +1,354 @@
+// Copyright 2016 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/install_static/product_install_details.h"
+
+#include "base/base_paths.h"
+#include "base/files/file_path.h"
+#include "base/i18n/case_conversion.h"
+#include "base/macros.h"
+#include "base/path_service.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/test_reg_util_win.h"
+#include "base/win/registry.h"
+#include "base/win/windows_version.h"
+#include "chrome/install_static/install_constants.h"
+#include "chrome/install_static/install_modes.h"
+#include "chrome_elf/nt_registry/nt_registry.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::Eq;
+using ::testing::StrEq;
+
+namespace install_static {
+
+namespace {
+
+TEST(ProductInstallDetailsTest, IsPathParentOf) {
+ std::wstring path = L"C:\\Program Files\\Company\\Product\\Application\\foo";
+ static constexpr const wchar_t* kFalseExpectations[] = {
+ L"",
+ L"\\",
+ L"\\\\",
+ L"C:\\Program File",
+ L"C:\\Program Filesz",
+ };
+ for (const wchar_t* false_expectation : kFalseExpectations) {
+ EXPECT_FALSE(IsPathParentOf(
+ false_expectation, std::wstring::traits_type::length(false_expectation),
+ path));
+ }
+
+ static constexpr const wchar_t* kTrueExpectations[] = {
+ L"C:\\Program Files",
+ L"C:\\PROGRAM FILES",
+ L"C:\\Program Files\\",
+ L"C:\\Program Files\\\\\\",
+ };
+ for (const wchar_t* true_expectation : kTrueExpectations) {
+ EXPECT_TRUE(IsPathParentOf(
+ true_expectation, std::wstring::traits_type::length(true_expectation),
+ path));
+ }
+}
+
+TEST(ProductInstallDetailsTest, PathIsInProgramFiles) {
+ static constexpr const wchar_t* kInvalidPaths[] = {
+ L"",
+ L"hello",
+ L"C:\\Program File",
+ L"C:\\Program Filesz",
+ L"C:\\foo\\Program Files",
+ L"C:\\foo\\Program Files\\",
+ L"C:\\foo\\Program Files (x86)",
+ L"C:\\foo\\Program Files (x86)\\",
+ };
+ for (const wchar_t* invalid : kInvalidPaths)
+ EXPECT_FALSE(PathIsInProgramFiles(invalid)) << invalid;
+
+ // 32-bit on 32-bit: only check C:\Program Files.
+ // 32-bit and 64-bit on 64-bit: check both.
+ const bool is_x64 = base::win::OSInfo::GetInstance()->architecture() !=
+ base::win::OSInfo::X86_ARCHITECTURE;
+ std::vector<int> program_files_keys;
+ program_files_keys.push_back(base::DIR_PROGRAM_FILESX86);
+ if (is_x64)
+ program_files_keys.push_back(base::DIR_PROGRAM_FILES6432);
+ std::vector<std::wstring> program_files_paths;
+ for (int key : program_files_keys) {
+ base::FilePath path;
+ ASSERT_TRUE(base::PathService::Get(key, &path));
+ program_files_paths.push_back(path.value());
+ }
+
+ static constexpr const wchar_t* kValidFormats[] = {
+ L"%ls",
+ L"%ls\\",
+ L"%ls\\spam",
+ };
+ for (const wchar_t* valid : kValidFormats) {
+ for (const std::wstring& program_files_path : program_files_paths) {
+ std::wstring path = base::StringPrintf(valid, program_files_path.c_str());
+ EXPECT_TRUE(PathIsInProgramFiles(path)) << path;
+
+ path = base::StringPrintf(
+ valid, base::i18n::ToLower(program_files_path).c_str());
+ EXPECT_TRUE(PathIsInProgramFiles(path)) << path;
+ }
+ }
+}
+
+TEST(ProductInstallDetailsTest, GetInstallSuffix) {
+ std::wstring suffix;
+ const std::pair<const wchar_t*, const wchar_t*> kData[] = {
+ {L"%ls\\Application", L""},
+ {L"%ls\\Application\\", L""},
+ {L"\\%ls\\Application", L""},
+ {L"\\%ls\\Application\\", L""},
+ {L"C:\\foo\\%ls\\Application\\foo.exe", L""},
+ {L"%ls Blorf\\Application", L" Blorf"},
+ {L"%ls Blorf\\Application\\", L" Blorf"},
+ {L"\\%ls Blorf\\Application", L" Blorf"},
+ {L"\\%ls Blorf\\Application\\", L" Blorf"},
+ {L"C:\\foo\\%ls Blorf\\Application\\foo.exe", L" Blorf"},
+ };
+ for (const auto& data : kData) {
+ const std::wstring path = base::StringPrintf(data.first, kProductPathName);
+ EXPECT_EQ(std::wstring(data.second), GetInstallSuffix(path)) << path;
+ }
+}
+
+struct TestData {
+ const wchar_t* path;
+ InstallConstantIndex index;
+ bool system_level;
+ const wchar_t* channel;
+};
+
+#if defined(GOOGLE_CHROME_BUILD)
+constexpr TestData kTestData[] = {
+ {
+ L"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
+ STABLE_INDEX, true, L"",
+ },
+ {
+ L"C:\\Users\\user\\AppData\\Local\\Google\\Chrome\\Application"
+ L"\\chrome.exe",
+ STABLE_INDEX, false, L"",
+ },
+ {
+ L"C:\\Users\\user\\AppData\\Local\\Google\\Chrome SxS\\Application"
+ L"\\chrome.exe",
+ CANARY_INDEX, false, L"canary",
+ },
+ {
+ L"C:\\Users\\user\\AppData\\Local\\Google\\CHROME SXS\\application"
+ L"\\chrome.exe",
+ CANARY_INDEX, false, L"canary",
+ },
+};
+#else // GOOGLE_CHROME_BUILD
+constexpr TestData kTestData[] = {
+ {
+ L"C:\\Program Files (x86)\\Chromium\\Application\\chrome.exe",
+ CHROMIUM_INDEX, true, L"",
+ },
+ {
+ L"C:\\Users\\user\\AppData\\Local\\Chromium\\Application\\chrome.exe",
+ CHROMIUM_INDEX, false, L"",
+ },
+};
+#endif // !GOOGLE_CHROME_BUILD
+
+} // namespace
+
+// Test that MakeProductDetails properly sniffs out an install's details.
+class MakeProductDetailsTest : public testing::TestWithParam<TestData> {
+ protected:
+ MakeProductDetailsTest()
+ : test_data_(GetParam()),
+ root_key_(test_data_.system_level ? HKEY_LOCAL_MACHINE
+ : HKEY_CURRENT_USER),
+ nt_root_key_(test_data_.system_level ? nt::HKLM : nt::HKCU) {
+ base::string16 path;
+ override_manager_.OverrideRegistry(root_key_, &path);
+ nt::SetTestingOverride(nt_root_key_, path);
+ }
+
+ ~MakeProductDetailsTest() {
+ nt::SetTestingOverride(nt_root_key_, base::string16());
+ }
+
+ const TestData& test_data() const { return test_data_; }
+
+ void SetUninstallArguments(const wchar_t* value) {
+ ASSERT_THAT(
+ base::win::RegKey(root_key_, GetClientStateKeyPath(false).c_str(),
+ KEY_WOW64_32KEY | KEY_SET_VALUE)
+ .WriteValue(L"UninstallArguments", value),
+ Eq(ERROR_SUCCESS));
+ }
+
+ void SetAp(const wchar_t* value, bool binaries) {
+ ASSERT_TRUE(!binaries ||
+ kInstallModes[test_data().index].supports_multi_install);
+ ASSERT_THAT(
+ base::win::RegKey(root_key_, GetClientStateKeyPath(binaries).c_str(),
+ KEY_WOW64_32KEY | KEY_SET_VALUE)
+ .WriteValue(L"ap", value),
+ Eq(ERROR_SUCCESS));
+ }
+
+ private:
+ // Returns the registry path for the product's ClientState key.
+ std::wstring GetClientStateKeyPath(bool binaries) {
+ EXPECT_TRUE(!binaries ||
+ kInstallModes[test_data().index].supports_multi_install);
+ std::wstring result(L"Software\\");
+ if (kUseGoogleUpdateIntegration) {
+ result.append(L"Google\\Update\\ClientState\\");
+ if (binaries)
+ result.append(kBinariesAppGuid);
+ else
+ result.append(kInstallModes[test_data().index].app_guid);
+ } else if (binaries) {
+ result.append(kBinariesPathName);
+ } else {
+ result.append(kProductPathName);
+ }
+ return result;
+ }
+
+ registry_util::RegistryOverrideManager override_manager_;
+ const TestData& test_data_;
+ HKEY root_key_;
+ nt::ROOT_KEY nt_root_key_;
+
+ DISALLOW_COPY_AND_ASSIGN(MakeProductDetailsTest);
+};
+
+// Test that the install mode is sniffed properly based on the path.
+TEST_P(MakeProductDetailsTest, Index) {
+ std::unique_ptr<PrimaryInstallDetails> details(
+ MakeProductDetails(test_data().path));
+ EXPECT_THAT(details->install_mode_index(), Eq(test_data().index));
+}
+
+// Test that user/system level is sniffed properly based on the path.
+TEST_P(MakeProductDetailsTest, SystemLevel) {
+ std::unique_ptr<PrimaryInstallDetails> details(
+ MakeProductDetails(test_data().path));
+ EXPECT_THAT(details->system_level(), Eq(test_data().system_level));
+}
+
+// Test that the default channel is sniffed properly based on the path.
+TEST_P(MakeProductDetailsTest, DefaultChannel) {
+ std::unique_ptr<PrimaryInstallDetails> details(
+ MakeProductDetails(test_data().path));
+ EXPECT_THAT(details->channel(), StrEq(test_data().channel));
+}
+
+// Test that multi-install is properly parsed out of the registry.
+TEST_P(MakeProductDetailsTest, MultiInstall) {
+ {
+ std::unique_ptr<PrimaryInstallDetails> details(
+ MakeProductDetails(test_data().path));
+ EXPECT_FALSE(details->multi_install());
+ }
+
+ {
+ SetUninstallArguments(L"--uninstall");
+ std::unique_ptr<PrimaryInstallDetails> details(
+ MakeProductDetails(test_data().path));
+ EXPECT_FALSE(details->multi_install());
+ }
+
+ if (!kInstallModes[test_data().index].supports_multi_install)
+ return;
+
+ {
+ SetUninstallArguments(L"--uninstall --multi-install --chrome");
+ std::unique_ptr<PrimaryInstallDetails> details(
+ MakeProductDetails(test_data().path));
+ EXPECT_TRUE(details->multi_install());
+ }
+}
+
+// Test that the channel name is properly parsed out of additional parameters.
+TEST_P(MakeProductDetailsTest, AdditionalParametersChannels) {
+ const std::pair<const wchar_t*, const wchar_t*> kApChannels[] = {
+ // stable
+ {L"", L""},
+ {L"-full", L""},
+ {L"x64-stable", L""},
+ {L"x64-stable-full", L""},
+ {L"baz-x64-stable", L""},
+ {L"foo-1.1-beta", L""},
+ {L"2.0-beta", L""},
+ {L"bar-2.0-dev", L""},
+ {L"1.0-dev", L""},
+ {L"fuzzy", L""},
+ {L"foo", L""},
+ {L"-multi-chrome", L""},
+ {L"x64-stable-multi-chrome", L""},
+ {L"-stage:ensemble_patching-multi-chrome-full", L""},
+ {L"-multi-chrome-full", L""},
+ // beta
+ {L"1.1-beta", L"beta"},
+ {L"1.1-beta-full", L"beta"},
+ {L"x64-beta", L"beta"},
+ {L"x64-beta-full", L"beta"},
+ {L"1.1-bar", L"beta"},
+ {L"1n1-foobar", L"beta"},
+ {L"x64-Beta", L"beta"},
+ {L"bar-x64-beta", L"beta"},
+ // dev
+ {L"2.0-dev", L"dev"},
+ {L"2.0-dev-full", L"dev"},
+ {L"x64-dev", L"dev"},
+ {L"x64-dev-full", L"dev"},
+ {L"2.0-DEV", L"dev"},
+ {L"2.0-dev-eloper", L"dev"},
+ {L"2.0-doom", L"dev"},
+ {L"250-doom", L"dev"},
+ };
+
+ for (const auto& ap_and_channel : kApChannels) {
+ SetAp(ap_and_channel.first, false);
+ std::unique_ptr<PrimaryInstallDetails> details(
+ MakeProductDetails(test_data().path));
+ if (kInstallModes[test_data().index].channel_strategy ==
+ ChannelStrategy::ADDITIONAL_PARAMETERS) {
+ EXPECT_THAT(details->channel(), StrEq(ap_and_channel.second));
+ } else {
+ // "ap" is ignored for this mode.
+ EXPECT_THAT(details->channel(), StrEq(test_data().channel));
+ }
+ }
+
+ if (!kInstallModes[test_data().index].supports_multi_install)
+ return;
+
+ // For multi-install modes, "ap" is pulled from the binaries' key.
+ for (const auto& ap_and_channel : kApChannels) {
+ SetAp(ap_and_channel.first, true);
+ SetUninstallArguments(L"--uninstall --multi-install --chrome");
+ std::unique_ptr<PrimaryInstallDetails> details(
+ MakeProductDetails(test_data().path));
+ if (kInstallModes[test_data().index].channel_strategy ==
+ ChannelStrategy::ADDITIONAL_PARAMETERS) {
+ EXPECT_THAT(details->channel(), StrEq(ap_and_channel.second));
+ } else {
+ // "ap" is ignored for this mode.
+ EXPECT_THAT(details->channel(), StrEq(test_data().channel));
+ }
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(All,
+ MakeProductDetailsTest,
+ testing::ValuesIn(kTestData));
+
+} // namespace install_static

Powered by Google App Engine
This is Rietveld 408576698