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 |