Chromium Code Reviews| Index: chrome/installer/util/beacons_unittest.cc |
| diff --git a/chrome/installer/util/beacons_unittest.cc b/chrome/installer/util/beacons_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7b2ab7a4fd4ed4a9cafcc0f658fdf7a9f02d245b |
| --- /dev/null |
| +++ b/chrome/installer/util/beacons_unittest.cc |
| @@ -0,0 +1,277 @@ |
| +// Copyright 2015 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/installer/util/beacons.h" |
| + |
| +#include "base/base_paths.h" |
| +#include "base/memory/scoped_vector.h" |
| +#include "base/path_service.h" |
| +#include "base/test/scoped_path_override.h" |
| +#include "base/test/test_reg_util_win.h" |
| +#include "base/test/test_timeouts.h" |
| +#include "base/threading/platform_thread.h" |
| +#include "base/win/registry.h" |
| +#include "base/win/win_util.h" |
| +#include "chrome/installer/util/browser_distribution.h" |
| +#include "chrome/installer/util/test_app_registration_data.h" |
| +#include "chrome/installer/util/util_constants.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +using ::testing::Bool; |
| +using ::testing::Combine; |
| +using ::testing::Values; |
| + |
| +namespace installer_util { |
| + |
| +// A test fixture that exercises a beacon. |
| +class BeaconTest |
| + : public ::testing::TestWithParam< |
| + ::testing::tuple<Beacon::BeaconType, Beacon::BeaconScope, bool>> { |
|
gab
2015/06/01 18:43:12
I think it makes sense to have
using Beacon::Beaco
grt (UTC plus 2)
2015/06/01 19:49:43
Done.
|
| + protected: |
| + static const base::char16 kBeaconName[]; |
| + |
| + BeaconTest() |
| + : beacon_type_(::testing::get<0>(GetParam())), |
| + beacon_scope_(::testing::get<1>(GetParam())), |
| + system_install_(::testing::get<2>(GetParam())), |
| + beacon_(kBeaconName, |
| + beacon_type_, |
| + beacon_scope_, |
| + system_install_, |
| + app_registration_data_) { |
| + // Override the registry so that tests can freely push state to it. |
| + registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER); |
| + registry_override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE); |
| + } |
| + |
| + TestAppRegistrationData app_registration_data_; |
| + Beacon::BeaconType beacon_type_; |
| + Beacon::BeaconScope beacon_scope_; |
| + bool system_install_; |
| + Beacon beacon_; |
| + |
| + private: |
| + registry_util::RegistryOverrideManager registry_override_manager_; |
| +}; |
| + |
| +// static |
| +const base::char16 BeaconTest::kBeaconName[] = L"TestBeacon"; |
| + |
| +// Nothing in the regsitry, so the beacon should not exist. |
| +TEST_P(BeaconTest, GetNonExistant) { |
| + ASSERT_TRUE(beacon_.Get().is_null()); |
| +} |
| + |
| +// Updating and then getting the beacon should return a value, and that it is |
| +// within range. |
| +TEST_P(BeaconTest, UpdateAndGet) { |
| + base::Time before(base::Time::Now()); |
| + beacon_.Update(); |
| + base::Time after(base::Time::Now()); |
| + base::Time beacon_time(beacon_.Get()); |
| + ASSERT_FALSE(beacon_time.is_null()); |
| + ASSERT_LE(before, beacon_time); |
| + ASSERT_GE(after, beacon_time); |
| +} |
| + |
| +// Tests that updating a first beacon only updates it the first time, but doing |
| +// so for a last beacon always updates. |
| +TEST_P(BeaconTest, UpdateTwice) { |
| + beacon_.Update(); |
| + base::Time beacon_time(beacon_.Get()); |
| + |
| + base::PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| + |
| + beacon_.Update(); |
| + if (beacon_type_ == Beacon::BeaconType::FIRST) { |
| + ASSERT_EQ(beacon_time, beacon_.Get()); |
| + } else { |
| + ASSERT_NE(beacon_time, beacon_.Get()); |
| + } |
| +} |
| + |
| +// Tests that the beacon is written into the proper location in the registry. |
| +TEST_P(BeaconTest, Location) { |
| + beacon_.Update(); |
| + HKEY right_root = system_install_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; |
| + HKEY wrong_root = system_install_ ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; |
| + base::string16 right_key; |
| + base::string16 wrong_key; |
| + base::string16 value_name; |
| + |
| + if (beacon_scope_ == Beacon::BeaconScope::PER_INSTALL || !system_install_) { |
| + value_name = kBeaconName; |
| + right_key = app_registration_data_.GetStateKey(); |
| + wrong_key = app_registration_data_.GetStateMediumKey(); |
| + } else { |
| + ASSERT_TRUE(base::win::GetUserSidString(&value_name)); |
| + right_key = |
| + app_registration_data_.GetStateMediumKey() + L"\\" + kBeaconName; |
| + wrong_key = app_registration_data_.GetStateKey(); |
| + } |
| + |
| + // Keys should not exist in the wrong root or in the right root but wrong key. |
| + ASSERT_FALSE(base::win::RegKey(wrong_root, right_key.c_str(), |
| + KEY_READ).Valid()) << right_key; |
| + ASSERT_FALSE(base::win::RegKey(wrong_root, wrong_key.c_str(), |
| + KEY_READ).Valid()) << wrong_key; |
| + ASSERT_FALSE(base::win::RegKey(right_root, wrong_key.c_str(), |
| + KEY_READ).Valid()) << wrong_key; |
| + // The right key should exist. |
| + base::win::RegKey key(right_root, right_key.c_str(), KEY_READ); |
| + ASSERT_TRUE(key.Valid()) << right_key; |
| + // And should have the value. |
| + ASSERT_TRUE(key.HasValue(value_name.c_str())) << value_name; |
| +} |
| + |
| +// Run the tests for all combinations of beacon type, scope, and install level. |
| +INSTANTIATE_TEST_CASE_P(BeaconTest, |
| + BeaconTest, |
| + Combine(Values(Beacon::BeaconType::FIRST, |
| + Beacon::BeaconType::LAST), |
| + Values(Beacon::BeaconScope::PER_USER, |
| + Beacon::BeaconScope::PER_INSTALL), |
| + Bool())); |
| + |
| +enum class DistributionVariant { |
| + SYSTEM_LEVEL, |
| + USER_LEVEL, |
| + SXS, |
| +}; |
| + |
| +class DefaultBrowserBeaconTest |
| + : public ::testing::TestWithParam<DistributionVariant> { |
| + protected: |
| + using Super = ::testing::TestWithParam<DistributionVariant>; |
| + |
| + DefaultBrowserBeaconTest() |
| + : system_install_(GetParam() == DistributionVariant::SYSTEM_LEVEL), |
| + chrome_sxs_(GetParam() == DistributionVariant::SXS), |
| + chrome_exe_(GetChromePathForParams()), |
| + distribution_(nullptr) {} |
| + |
| + void SetUp() override { |
| + Super::SetUp(); |
| + |
| + // Override FILE_EXE so that various InstallUtil functions will consider |
| + // this to be a user/system Chrome or Chrome SxS. |
| + path_overrides_.push_back(new base::ScopedPathOverride( |
| + base::FILE_EXE, chrome_exe_, true /* is_absolute */, |
| + false /* !create */)); |
| + |
| + // Override these paths with their own values so that they can be found |
| + // after the registry override manager is in place. Getting them would |
| + // otherwise fail since the underlying calls to the OS need to see the real |
| + // contents of the registry. |
| + static const int kPathKeys[] = { |
| + base::DIR_PROGRAM_FILES, |
| + base::DIR_PROGRAM_FILESX86, |
| + base::DIR_LOCAL_APP_DATA, |
| + }; |
| + for (int key : kPathKeys) { |
| + base::FilePath temp; |
| + PathService::Get(key, &temp); |
| + path_overrides_.push_back(new base::ScopedPathOverride(key, temp)); |
| + } |
| + |
| + // Override the registry so that tests can freely push state to it. |
| + registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER); |
| + registry_override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE); |
| + |
| + distribution_ = BrowserDistribution::GetDistribution(); |
| + } |
| + |
| + bool system_install_; |
| + bool chrome_sxs_; |
| + base::FilePath chrome_exe_; |
| + BrowserDistribution* distribution_; |
| + |
| + private: |
| + base::FilePath GetChromePathForParams() const { |
| + base::FilePath chrome_exe; |
| + int dir_key = base::DIR_LOCAL_APP_DATA; |
| + |
| + if (system_install_) { |
| +#if defined(_WIN64) |
| + static const int kSystemKey = base::DIR_PROGRAM_FILESX86; |
| +#else |
| + static const int kSystemKey = base::DIR_PROGRAM_FILES; |
| +#endif |
| + dir_key = kSystemKey; |
| + } |
| + PathService::Get(dir_key, &chrome_exe); |
| +#if defined(GOOGLE_CHROME_BUILD) |
| + chrome_exe = chrome_exe.Append(installer::kGoogleChromeInstallSubDir1); |
| + if (chrome_sxs_) { |
| + chrome_exe = chrome_exe.Append( |
| + base::string16(installer::kGoogleChromeInstallSubDir2) + |
| + installer::kSxSSuffix); |
| + } else { |
| + chrome_exe = chrome_exe.Append(installer::kGoogleChromeInstallSubDir2); |
| + } |
| +#else |
| + chrome_exe = chrome_exe.AppendASCII("Chromium"); |
| +#endif |
| + chrome_exe = chrome_exe.Append(installer::kInstallBinaryDir); |
| + return chrome_exe.Append(installer::kChromeExe); |
| + } |
| + |
| + ScopedVector<base::ScopedPathOverride> path_overrides_; |
| + registry_util::RegistryOverrideManager registry_override_manager_; |
| +}; |
| + |
| +// Tests that the default browser beacons work as expected. |
| +TEST_P(DefaultBrowserBeaconTest, All) { |
| + scoped_ptr<Beacon> last_was_default(MakeLastWasDefaultBeacon( |
| + system_install_, distribution_->GetAppRegistrationData())); |
| + scoped_ptr<Beacon> first_not_default(MakeFirstNotDefaultBeacon( |
| + system_install_, distribution_->GetAppRegistrationData())); |
| + |
| + ASSERT_TRUE(last_was_default->Get().is_null()); |
| + ASSERT_TRUE(first_not_default->Get().is_null()); |
| + |
| + // Chrome is not default. |
| + UpdateDefaultBrowserBeaconWithState(chrome_exe_, distribution_, |
| + ShellUtil::NOT_DEFAULT); |
| + ASSERT_TRUE(last_was_default->Get().is_null()); |
| + ASSERT_FALSE(first_not_default->Get().is_null()); |
| + |
| + // Then it is. |
| + UpdateDefaultBrowserBeaconWithState(chrome_exe_, distribution_, |
| + ShellUtil::IS_DEFAULT); |
| + ASSERT_FALSE(last_was_default->Get().is_null()); |
| + ASSERT_TRUE(first_not_default->Get().is_null()); |
| + |
| + // It still is. |
| + UpdateDefaultBrowserBeaconWithState(chrome_exe_, distribution_, |
| + ShellUtil::IS_DEFAULT); |
| + ASSERT_FALSE(last_was_default->Get().is_null()); |
| + ASSERT_TRUE(first_not_default->Get().is_null()); |
| + |
| + // Now it's not again. |
| + UpdateDefaultBrowserBeaconWithState(chrome_exe_, distribution_, |
| + ShellUtil::NOT_DEFAULT); |
| + ASSERT_FALSE(last_was_default->Get().is_null()); |
| + ASSERT_FALSE(first_not_default->Get().is_null()); |
| + |
| + // And it still isn't. |
| + UpdateDefaultBrowserBeaconWithState(chrome_exe_, distribution_, |
| + ShellUtil::NOT_DEFAULT); |
| + ASSERT_FALSE(last_was_default->Get().is_null()); |
| + ASSERT_FALSE(first_not_default->Get().is_null()); |
| +} |
| + |
| +INSTANTIATE_TEST_CASE_P(SystemLevelChrome, |
| + DefaultBrowserBeaconTest, |
| + Values(DistributionVariant::SYSTEM_LEVEL)); |
| +INSTANTIATE_TEST_CASE_P(UserLevelChrome, |
| + DefaultBrowserBeaconTest, |
| + Values(DistributionVariant::USER_LEVEL)); |
| +#if 0 && defined(GOOGLE_CHROME_BUILD) |
| +// Disabled for now since InstallUtil::IsChromeSxSProcess makes this impossible. |
| +INSTANTIATE_TEST_CASE_P(ChromeSxS, DefaultBrowserBeaconTest, |
| + Values(DistributionVariant::SXS)); |
| +#endif |
| + |
| +} // namespace installer_util |