| Index: chrome/installer/setup/user_experiment_unittest.cc
|
| diff --git a/chrome/installer/setup/user_experiment_unittest.cc b/chrome/installer/setup/user_experiment_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a5b81c30b494bc8a410fa7a9b2570a883ce9eac4
|
| --- /dev/null
|
| +++ b/chrome/installer/setup/user_experiment_unittest.cc
|
| @@ -0,0 +1,194 @@
|
| +// Copyright 2017 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/setup/user_experiment.h"
|
| +
|
| +#include "base/macros.h"
|
| +#include "base/test/test_reg_util_win.h"
|
| +#include "base/win/registry.h"
|
| +#include "chrome/common/chrome_version.h"
|
| +#include "chrome/install_static/install_details.h"
|
| +#include "chrome/install_static/install_modes.h"
|
| +#include "chrome/install_static/install_util.h"
|
| +#include "chrome/install_static/test/scoped_install_details.h"
|
| +#include "chrome/installer/util/experiment_metrics.h"
|
| +#include "chrome/installer/util/experiment_storage.h"
|
| +#include "chrome/installer/util/google_update_constants.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace installer {
|
| +
|
| +class UserExperimentTest : public ::testing::TestWithParam<bool> {
|
| + protected:
|
| + UserExperimentTest()
|
| + : system_level_(GetParam()),
|
| + root_(system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER),
|
| + install_details_(system_level_) {}
|
| +
|
| + void SetUp() override {
|
| + ASSERT_NO_FATAL_FAILURE(registry_override_manager_.OverrideRegistry(root_));
|
| +
|
| + // Create the ClientState key.
|
| + base::win::RegKey key;
|
| + ASSERT_EQ(key.Create(root_,
|
| + install_static::InstallDetails::Get()
|
| + .GetClientStateKeyPath()
|
| + .c_str(),
|
| + KEY_WOW64_64KEY | KEY_SET_VALUE),
|
| + ERROR_SUCCESS);
|
| + }
|
| +
|
| + void SetProductVersion(const base::char16* version) {
|
| + SetClientsValue(google_update::kRegVersionField, version);
|
| + }
|
| +
|
| + void SetOldProductVersion(const base::char16* version) {
|
| + SetClientsValue(google_update::kRegOldVersionField, version);
|
| + }
|
| +
|
| + private:
|
| + void SetClientsValue(const base::char16* value_name,
|
| + const base::char16* value_data) {
|
| + base::win::RegKey key(
|
| + root_,
|
| + install_static::GetClientsKeyPath(install_static::GetAppGuid()).c_str(),
|
| + KEY_WOW64_64KEY | KEY_SET_VALUE);
|
| + ASSERT_TRUE(key.Valid());
|
| + ASSERT_EQ(key.WriteValue(value_name, value_data), ERROR_SUCCESS);
|
| + }
|
| +
|
| + const bool system_level_;
|
| + const HKEY root_;
|
| + registry_util::RegistryOverrideManager registry_override_manager_;
|
| + install_static::ScopedInstallDetails install_details_;
|
| + DISALLOW_COPY_AND_ASSIGN(UserExperimentTest);
|
| +};
|
| +
|
| +TEST_P(UserExperimentTest, WriteInitialStateNoData) {
|
| + ExperimentStorage storage;
|
| +
|
| + // A first call should write the desired state.
|
| + WriteInitialState(&storage, ExperimentMetrics::kWaitingForUserLogon);
|
| +
|
| + ExperimentMetrics metrics = ExperimentMetrics();
|
| + EXPECT_TRUE(storage.AcquireLock()->LoadMetrics(&metrics));
|
| + EXPECT_EQ(metrics.state, ExperimentMetrics::kWaitingForUserLogon);
|
| +
|
| + // A subsequent should update it state.
|
| + WriteInitialState(&storage, ExperimentMetrics::kSingletonWaitTimeout);
|
| +
|
| + metrics = ExperimentMetrics();
|
| + EXPECT_TRUE(storage.AcquireLock()->LoadMetrics(&metrics));
|
| + EXPECT_EQ(metrics.state, ExperimentMetrics::kSingletonWaitTimeout);
|
| +}
|
| +
|
| +// Nothing should be written if the experiment is underway.
|
| +TEST_P(UserExperimentTest, WriteInitialStateInExperiment) {
|
| + ExperimentStorage storage;
|
| +
|
| + {
|
| + ExperimentMetrics metrics = ExperimentMetrics();
|
| + metrics.state = ExperimentMetrics::kGroupAssigned;
|
| + storage.AcquireLock()->StoreMetrics(metrics);
|
| + }
|
| +
|
| + WriteInitialState(&storage, ExperimentMetrics::kSingletonWaitTimeout);
|
| +
|
| + ExperimentMetrics metrics = ExperimentMetrics();
|
| + EXPECT_TRUE(storage.AcquireLock()->LoadMetrics(&metrics));
|
| + EXPECT_EQ(metrics.state, ExperimentMetrics::kGroupAssigned);
|
| +}
|
| +
|
| +TEST_P(UserExperimentTest, IsDomainJoined) {
|
| + // Just make sure it doesn't crash or leak.
|
| + IsDomainJoined();
|
| +}
|
| +
|
| +TEST_P(UserExperimentTest, IsSelectedForStudyFirstCall) {
|
| + ExperimentStorage storage;
|
| + auto lock = storage.AcquireLock();
|
| +
|
| + // The first call will pick a study.
|
| + bool is_selected =
|
| + IsSelectedForStudy(lock.get(), ExperimentStorage::kStudyOne);
|
| +
|
| + // A value must have been written.
|
| + ExperimentStorage::Study participation = ExperimentStorage::kNoStudySelected;
|
| + ASSERT_TRUE(lock->ReadParticipation(&participation));
|
| + EXPECT_GE(participation, ExperimentStorage::kStudyOne);
|
| + EXPECT_LE(participation, ExperimentStorage::kStudyTwo);
|
| +
|
| + // is_selected should be set based on the value that was written.
|
| + if (participation == ExperimentStorage::kStudyOne)
|
| + EXPECT_TRUE(is_selected);
|
| + else
|
| + EXPECT_FALSE(is_selected);
|
| +}
|
| +
|
| +// A user selected into study one participates in both studies.
|
| +TEST_P(UserExperimentTest, IsSelectedForStudyOne) {
|
| + ExperimentStorage storage;
|
| + auto lock = storage.AcquireLock();
|
| +
|
| + ASSERT_TRUE(lock->WriteParticipation(ExperimentStorage::kStudyOne));
|
| +
|
| + EXPECT_TRUE(IsSelectedForStudy(lock.get(), ExperimentStorage::kStudyOne));
|
| + EXPECT_TRUE(IsSelectedForStudy(lock.get(), ExperimentStorage::kStudyTwo));
|
| +}
|
| +
|
| +// A user selected into study two only participates in that study.
|
| +TEST_P(UserExperimentTest, IsSelectedForStudyTwo) {
|
| + ExperimentStorage storage;
|
| + auto lock = storage.AcquireLock();
|
| +
|
| + ASSERT_TRUE(lock->WriteParticipation(ExperimentStorage::kStudyTwo));
|
| +
|
| + EXPECT_FALSE(IsSelectedForStudy(lock.get(), ExperimentStorage::kStudyOne));
|
| + EXPECT_TRUE(IsSelectedForStudy(lock.get(), ExperimentStorage::kStudyTwo));
|
| +}
|
| +
|
| +// Ensure that group selection is within bounds.
|
| +TEST_P(UserExperimentTest, PickGroupStudyOne) {
|
| + int group = PickGroup(ExperimentStorage::kStudyOne);
|
| + EXPECT_GE(group, 0);
|
| + EXPECT_LT(group, ExperimentMetrics::kNumGroups);
|
| +}
|
| +
|
| +// Ensure that group selection is within bounds.
|
| +TEST_P(UserExperimentTest, PickGroupStudyTwo) {
|
| + int group = PickGroup(ExperimentStorage::kStudyTwo);
|
| + EXPECT_GE(group, 0);
|
| + EXPECT_LT(group, ExperimentMetrics::kNumGroups);
|
| +}
|
| +
|
| +// When there's nothing in the registry, default to false.
|
| +TEST_P(UserExperimentTest, IsUpdateRenamePendingNoRegistration) {
|
| + EXPECT_FALSE(IsUpdateRenamePending());
|
| +}
|
| +
|
| +// No update is pending if "pv" matches the current version.
|
| +TEST_P(UserExperimentTest, IsUpdateRenamePendingNo) {
|
| + ASSERT_NO_FATAL_FAILURE(SetProductVersion(TEXT(CHROME_VERSION_STRING)));
|
| + EXPECT_FALSE(IsUpdateRenamePending());
|
| +}
|
| +
|
| +// An update is pending if an old version needs to be restarted to be the
|
| +// current.
|
| +TEST_P(UserExperimentTest, IsUpdateRenamePendingYes) {
|
| + static constexpr base::char16 kSillyOldVersion[] = L"47.0.1.0";
|
| + ASSERT_STRNE(kSillyOldVersion, TEXT(CHROME_VERSION_STRING));
|
| +
|
| + ASSERT_NO_FATAL_FAILURE(SetProductVersion(TEXT(CHROME_VERSION_STRING)));
|
| + ASSERT_NO_FATAL_FAILURE(SetOldProductVersion(kSillyOldVersion));
|
| + EXPECT_TRUE(IsUpdateRenamePending());
|
| +}
|
| +
|
| +INSTANTIATE_TEST_CASE_P(UserLevel,
|
| + UserExperimentTest,
|
| + ::testing::Values(false));
|
| +INSTANTIATE_TEST_CASE_P(SystemLevel,
|
| + UserExperimentTest,
|
| + ::testing::Values(true));
|
| +
|
| +} // namespace installer
|
|
|