OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/installer/setup/user_experiment.h" |
| 6 |
| 7 #include "base/macros.h" |
| 8 #include "base/test/test_reg_util_win.h" |
| 9 #include "base/win/registry.h" |
| 10 #include "chrome/common/chrome_version.h" |
| 11 #include "chrome/install_static/install_details.h" |
| 12 #include "chrome/install_static/install_modes.h" |
| 13 #include "chrome/install_static/install_util.h" |
| 14 #include "chrome/install_static/test/scoped_install_details.h" |
| 15 #include "chrome/installer/util/experiment_metrics.h" |
| 16 #include "chrome/installer/util/experiment_storage.h" |
| 17 #include "chrome/installer/util/google_update_constants.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" |
| 19 |
| 20 namespace installer { |
| 21 |
| 22 class UserExperimentTest : public ::testing::TestWithParam<bool> { |
| 23 protected: |
| 24 UserExperimentTest() |
| 25 : system_level_(GetParam()), |
| 26 root_(system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER), |
| 27 install_details_(system_level_) {} |
| 28 |
| 29 void SetUp() override { |
| 30 ASSERT_NO_FATAL_FAILURE(registry_override_manager_.OverrideRegistry(root_)); |
| 31 |
| 32 // Create the ClientState key. |
| 33 base::win::RegKey key; |
| 34 ASSERT_EQ(key.Create(root_, |
| 35 install_static::InstallDetails::Get() |
| 36 .GetClientStateKeyPath() |
| 37 .c_str(), |
| 38 KEY_WOW64_64KEY | KEY_SET_VALUE), |
| 39 ERROR_SUCCESS); |
| 40 } |
| 41 |
| 42 void SetProductVersion(const base::char16* version) { |
| 43 SetClientsValue(google_update::kRegVersionField, version); |
| 44 } |
| 45 |
| 46 void SetOldProductVersion(const base::char16* version) { |
| 47 SetClientsValue(google_update::kRegOldVersionField, version); |
| 48 } |
| 49 |
| 50 private: |
| 51 void SetClientsValue(const base::char16* value_name, |
| 52 const base::char16* value_data) { |
| 53 base::win::RegKey key( |
| 54 root_, |
| 55 install_static::GetClientsKeyPath(install_static::GetAppGuid()).c_str(), |
| 56 KEY_WOW64_64KEY | KEY_SET_VALUE); |
| 57 ASSERT_TRUE(key.Valid()); |
| 58 ASSERT_EQ(key.WriteValue(value_name, value_data), ERROR_SUCCESS); |
| 59 } |
| 60 |
| 61 const bool system_level_; |
| 62 const HKEY root_; |
| 63 registry_util::RegistryOverrideManager registry_override_manager_; |
| 64 install_static::ScopedInstallDetails install_details_; |
| 65 DISALLOW_COPY_AND_ASSIGN(UserExperimentTest); |
| 66 }; |
| 67 |
| 68 TEST_P(UserExperimentTest, WriteInitialStateNoData) { |
| 69 ExperimentStorage storage; |
| 70 |
| 71 // A first call should write the desired state. |
| 72 WriteInitialState(&storage, ExperimentMetrics::kWaitingForUserLogon); |
| 73 |
| 74 ExperimentMetrics metrics = ExperimentMetrics(); |
| 75 EXPECT_TRUE(storage.AcquireLock()->LoadMetrics(&metrics)); |
| 76 EXPECT_EQ(metrics.state, ExperimentMetrics::kWaitingForUserLogon); |
| 77 |
| 78 // A subsequent should update it state. |
| 79 WriteInitialState(&storage, ExperimentMetrics::kSingletonWaitTimeout); |
| 80 |
| 81 metrics = ExperimentMetrics(); |
| 82 EXPECT_TRUE(storage.AcquireLock()->LoadMetrics(&metrics)); |
| 83 EXPECT_EQ(metrics.state, ExperimentMetrics::kSingletonWaitTimeout); |
| 84 } |
| 85 |
| 86 // Nothing should be written if the experiment is underway. |
| 87 TEST_P(UserExperimentTest, WriteInitialStateInExperiment) { |
| 88 ExperimentStorage storage; |
| 89 |
| 90 { |
| 91 ExperimentMetrics metrics = ExperimentMetrics(); |
| 92 metrics.state = ExperimentMetrics::kGroupAssigned; |
| 93 storage.AcquireLock()->StoreMetrics(metrics); |
| 94 } |
| 95 |
| 96 WriteInitialState(&storage, ExperimentMetrics::kSingletonWaitTimeout); |
| 97 |
| 98 ExperimentMetrics metrics = ExperimentMetrics(); |
| 99 EXPECT_TRUE(storage.AcquireLock()->LoadMetrics(&metrics)); |
| 100 EXPECT_EQ(metrics.state, ExperimentMetrics::kGroupAssigned); |
| 101 } |
| 102 |
| 103 TEST_P(UserExperimentTest, IsDomainJoined) { |
| 104 // Just make sure it doesn't crash or leak. |
| 105 IsDomainJoined(); |
| 106 } |
| 107 |
| 108 TEST_P(UserExperimentTest, IsSelectedForStudyFirstCall) { |
| 109 ExperimentStorage storage; |
| 110 auto lock = storage.AcquireLock(); |
| 111 |
| 112 // The first call will pick a study. |
| 113 bool is_selected = |
| 114 IsSelectedForStudy(lock.get(), ExperimentStorage::kStudyOne); |
| 115 |
| 116 // A value must have been written. |
| 117 ExperimentStorage::Study participation = ExperimentStorage::kNoStudySelected; |
| 118 ASSERT_TRUE(lock->ReadParticipation(&participation)); |
| 119 EXPECT_GE(participation, ExperimentStorage::kStudyOne); |
| 120 EXPECT_LE(participation, ExperimentStorage::kStudyTwo); |
| 121 |
| 122 // is_selected should be set based on the value that was written. |
| 123 if (participation == ExperimentStorage::kStudyOne) |
| 124 EXPECT_TRUE(is_selected); |
| 125 else |
| 126 EXPECT_FALSE(is_selected); |
| 127 } |
| 128 |
| 129 // A user selected into study one participates in both studies. |
| 130 TEST_P(UserExperimentTest, IsSelectedForStudyOne) { |
| 131 ExperimentStorage storage; |
| 132 auto lock = storage.AcquireLock(); |
| 133 |
| 134 ASSERT_TRUE(lock->WriteParticipation(ExperimentStorage::kStudyOne)); |
| 135 |
| 136 EXPECT_TRUE(IsSelectedForStudy(lock.get(), ExperimentStorage::kStudyOne)); |
| 137 EXPECT_TRUE(IsSelectedForStudy(lock.get(), ExperimentStorage::kStudyTwo)); |
| 138 } |
| 139 |
| 140 // A user selected into study two only participates in that study. |
| 141 TEST_P(UserExperimentTest, IsSelectedForStudyTwo) { |
| 142 ExperimentStorage storage; |
| 143 auto lock = storage.AcquireLock(); |
| 144 |
| 145 ASSERT_TRUE(lock->WriteParticipation(ExperimentStorage::kStudyTwo)); |
| 146 |
| 147 EXPECT_FALSE(IsSelectedForStudy(lock.get(), ExperimentStorage::kStudyOne)); |
| 148 EXPECT_TRUE(IsSelectedForStudy(lock.get(), ExperimentStorage::kStudyTwo)); |
| 149 } |
| 150 |
| 151 // Ensure that group selection is within bounds. |
| 152 TEST_P(UserExperimentTest, PickGroupStudyOne) { |
| 153 int group = PickGroup(ExperimentStorage::kStudyOne); |
| 154 EXPECT_GE(group, 0); |
| 155 EXPECT_LT(group, ExperimentMetrics::kNumGroups); |
| 156 } |
| 157 |
| 158 // Ensure that group selection is within bounds. |
| 159 TEST_P(UserExperimentTest, PickGroupStudyTwo) { |
| 160 int group = PickGroup(ExperimentStorage::kStudyTwo); |
| 161 EXPECT_GE(group, 0); |
| 162 EXPECT_LT(group, ExperimentMetrics::kNumGroups); |
| 163 } |
| 164 |
| 165 // When there's nothing in the registry, default to false. |
| 166 TEST_P(UserExperimentTest, IsUpdateRenamePendingNoRegistration) { |
| 167 EXPECT_FALSE(IsUpdateRenamePending()); |
| 168 } |
| 169 |
| 170 // No update is pending if "pv" matches the current version. |
| 171 TEST_P(UserExperimentTest, IsUpdateRenamePendingNo) { |
| 172 ASSERT_NO_FATAL_FAILURE(SetProductVersion(TEXT(CHROME_VERSION_STRING))); |
| 173 EXPECT_FALSE(IsUpdateRenamePending()); |
| 174 } |
| 175 |
| 176 // An update is pending if an old version needs to be restarted to be the |
| 177 // current. |
| 178 TEST_P(UserExperimentTest, IsUpdateRenamePendingYes) { |
| 179 static constexpr base::char16 kSillyOldVersion[] = L"47.0.1.0"; |
| 180 ASSERT_STRNE(kSillyOldVersion, TEXT(CHROME_VERSION_STRING)); |
| 181 |
| 182 ASSERT_NO_FATAL_FAILURE(SetProductVersion(TEXT(CHROME_VERSION_STRING))); |
| 183 ASSERT_NO_FATAL_FAILURE(SetOldProductVersion(kSillyOldVersion)); |
| 184 EXPECT_TRUE(IsUpdateRenamePending()); |
| 185 } |
| 186 |
| 187 INSTANTIATE_TEST_CASE_P(UserLevel, |
| 188 UserExperimentTest, |
| 189 ::testing::Values(false)); |
| 190 INSTANTIATE_TEST_CASE_P(SystemLevel, |
| 191 UserExperimentTest, |
| 192 ::testing::Values(true)); |
| 193 |
| 194 } // namespace installer |
OLD | NEW |