Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 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/util/beacons.h" | |
| 6 | |
| 7 #include "base/base_paths.h" | |
| 8 #include "base/memory/scoped_vector.h" | |
| 9 #include "base/path_service.h" | |
| 10 #include "base/test/scoped_path_override.h" | |
| 11 #include "base/test/test_reg_util_win.h" | |
| 12 #include "base/win/registry.h" | |
| 13 #include "base/win/win_util.h" | |
| 14 #include "chrome/installer/util/browser_distribution.h" | |
| 15 #include "chrome/installer/util/test_app_registration_data.h" | |
| 16 #include "chrome/installer/util/util_constants.h" | |
| 17 #include "testing/gtest/include/gtest/gtest.h" | |
| 18 | |
| 19 using ::testing::Bool; | |
| 20 using ::testing::Combine; | |
| 21 using ::testing::Values; | |
| 22 | |
| 23 class TestBeacon : public Beacon { | |
|
gab
2015/05/26 18:54:35
So a TestBeacon is a Beacon with a public construc
grt (UTC plus 2)
2015/05/26 20:54:02
I've seen and used this from time to time. I find
gab
2015/05/29 13:37:36
Well at least friend puts the code owner of Beacon
grt (UTC plus 2)
2015/05/29 15:31:10
Rejiggered as discussed.
| |
| 24 public: | |
| 25 using BeaconType = Beacon::BeaconType; | |
| 26 using BeaconScope = Beacon::BeaconScope; | |
| 27 | |
| 28 TestBeacon(base::StringPiece16 name, | |
| 29 BeaconType type, | |
| 30 BeaconScope scope, | |
| 31 bool system_install, | |
| 32 const AppRegistrationData& registration_data) | |
| 33 : Beacon(name, type, scope, system_install, registration_data) {} | |
| 34 }; | |
| 35 | |
| 36 // A test fixture that exercises a test beacon. | |
| 37 class BeaconTest | |
| 38 : public ::testing::TestWithParam<::testing::tuple<TestBeacon::BeaconType, | |
| 39 TestBeacon::BeaconScope, | |
| 40 bool>> { | |
|
gab
2015/05/26 18:54:35
I think you can name the parameters here (doesn't
grt (UTC plus 2)
2015/05/26 20:54:02
Do you mean BeaconType, BeaconScope, and bool? Tho
gab
2015/05/29 13:37:37
Ah ok, I guess I was recalling something like base
| |
| 41 protected: | |
| 42 static const base::char16 kBeaconName[]; | |
| 43 | |
| 44 BeaconTest() | |
| 45 : beacon_type_(::testing::get<0>(GetParam())), | |
| 46 beacon_scope_(::testing::get<1>(GetParam())), | |
| 47 system_install_(::testing::get<2>(GetParam())), | |
| 48 beacon_(kBeaconName, | |
| 49 beacon_type_, | |
| 50 beacon_scope_, | |
| 51 system_install_, | |
| 52 app_registration_data_) { | |
| 53 // Override the registry so that tests can freely push state to it. | |
| 54 registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER); | |
| 55 registry_override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE); | |
| 56 } | |
| 57 | |
| 58 TestAppRegistrationData app_registration_data_; | |
| 59 TestBeacon::BeaconType beacon_type_; | |
| 60 TestBeacon::BeaconScope beacon_scope_; | |
| 61 bool system_install_; | |
| 62 TestBeacon beacon_; | |
| 63 registry_util::RegistryOverrideManager registry_override_manager_; | |
|
gab
2015/05/26 18:54:35
This member should be private IMO, no reason the t
grt (UTC plus 2)
2015/05/26 20:54:01
Done.
| |
| 64 }; | |
| 65 | |
| 66 // static | |
| 67 const base::char16 BeaconTest::kBeaconName[] = L"TestBeacon"; | |
| 68 | |
| 69 // Nothing in the regsitry, so the becon should not exist. | |
|
gab
2015/05/26 18:54:35
s/becon/beacon
grt (UTC plus 2)
2015/05/26 20:54:02
Done.
| |
| 70 TEST_P(BeaconTest, GetNonExistant) { | |
| 71 ASSERT_TRUE(beacon_.Get().is_null()); | |
| 72 } | |
| 73 | |
| 74 // Updating and then getting the beacon should return a value. | |
| 75 TEST_P(BeaconTest, UpdateAndGet) { | |
| 76 beacon_.Update(); | |
| 77 ASSERT_FALSE(beacon_.Get().is_null()); | |
| 78 } | |
| 79 | |
| 80 // Tests that updating a first beacon only updates it the first time, but doing | |
| 81 // so for a last beacon always updates. | |
| 82 TEST_P(BeaconTest, UpdateTwice) { | |
| 83 beacon_.Update(); | |
| 84 base::Time beacon_time(beacon_.Get()); | |
| 85 | |
| 86 beacon_.Update(); | |
|
gab
2015/05/26 18:54:35
Should there be some kind of sleep before this Upd
grt (UTC plus 2)
2015/05/26 20:54:01
Done.
| |
| 87 if (beacon_type_ == TestBeacon::BeaconType::FIRST) { | |
| 88 ASSERT_EQ(beacon_time, beacon_.Get()); | |
| 89 } else { | |
| 90 ASSERT_NE(beacon_time, beacon_.Get()); | |
| 91 } | |
| 92 } | |
| 93 | |
| 94 // Tests that the beacon is written into the proper location in the registry. | |
| 95 TEST_P(BeaconTest, Location) { | |
| 96 beacon_.Update(); | |
| 97 HKEY right_root = system_install_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | |
| 98 HKEY wrong_root = system_install_ ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; | |
| 99 base::string16 right_key; | |
| 100 base::string16 wrong_key; | |
| 101 base::string16 value_name; | |
| 102 | |
| 103 if (beacon_scope_ == TestBeacon::BeaconScope::PER_INSTALL || | |
| 104 !system_install_) { | |
| 105 value_name = kBeaconName; | |
| 106 right_key = app_registration_data_.GetStateKey(); | |
| 107 wrong_key = app_registration_data_.GetStateMediumKey(); | |
| 108 } else { | |
| 109 ASSERT_TRUE(base::win::GetUserSidString(&value_name)); | |
| 110 right_key = | |
| 111 app_registration_data_.GetStateMediumKey() + L"\\" + kBeaconName; | |
| 112 wrong_key = app_registration_data_.GetStateKey(); | |
| 113 } | |
| 114 | |
| 115 // Keys should not exist in the wrong root or in the right root but wrong key. | |
| 116 ASSERT_FALSE(base::win::RegKey(wrong_root, right_key.c_str(), | |
| 117 KEY_READ).Valid()) << right_key; | |
| 118 ASSERT_FALSE(base::win::RegKey(wrong_root, wrong_key.c_str(), | |
| 119 KEY_READ).Valid()) << wrong_key; | |
| 120 ASSERT_FALSE(base::win::RegKey(right_root, wrong_key.c_str(), | |
| 121 KEY_READ).Valid()) << wrong_key; | |
| 122 // The right key should exist. | |
| 123 base::win::RegKey key(right_root, right_key.c_str(), KEY_READ); | |
| 124 ASSERT_TRUE(key.Valid()) << right_key; | |
| 125 // And should have the value. | |
| 126 ASSERT_TRUE(key.HasValue(value_name.c_str())) << value_name; | |
|
gab
2015/05/26 18:54:35
Should also test that we can reconstruct a reasona
grt (UTC plus 2)
2015/05/26 20:54:01
Done in UpdateAndGet.
| |
| 127 } | |
| 128 | |
| 129 // Run the tests for all combinations of beacon type, scope, and install level. | |
| 130 INSTANTIATE_TEST_CASE_P(BeaconTest, | |
| 131 BeaconTest, | |
| 132 Combine(Values(TestBeacon::BeaconType::FIRST, | |
| 133 TestBeacon::BeaconType::LAST), | |
| 134 Values(TestBeacon::BeaconScope::PER_USER, | |
| 135 TestBeacon::BeaconScope::PER_INSTALL), | |
| 136 Bool())); | |
| 137 | |
| 138 enum class DistributionVariant { | |
| 139 SYSTEM_LEVEL_CHROME, | |
| 140 USER_LEVEL_CHROME, | |
| 141 CHROME_SXS, | |
|
gab
2015/05/26 18:54:35
I'd remove CHROME from all of these (since enum cl
grt (UTC plus 2)
2015/05/26 20:54:01
Done.
| |
| 142 }; | |
| 143 | |
| 144 class DefaultBrowserBeaconTest | |
| 145 : public ::testing::TestWithParam<DistributionVariant> { | |
| 146 protected: | |
| 147 using Super = ::testing::TestWithParam<DistributionVariant>; | |
| 148 | |
| 149 DefaultBrowserBeaconTest() | |
| 150 : system_install_(GetParam() == DistributionVariant::SYSTEM_LEVEL_CHROME), | |
| 151 chrome_sxs_(GetParam() == DistributionVariant::CHROME_SXS), | |
|
gab
2015/05/26 18:54:35
Curious, why is Chrome SxS different than regular
grt (UTC plus 2)
2015/05/26 20:54:01
It should be the same, yes.
| |
| 152 chrome_exe_(GetChromePath()), | |
| 153 distribution_(nullptr) {} | |
| 154 | |
| 155 void SetUp() override { | |
| 156 Super::SetUp(); | |
| 157 | |
| 158 // Override FILE_EXE so that various InstallUtil functions will consider | |
| 159 // this to be a user/system Chrome or Chrome SxS. | |
| 160 path_overrides_.push_back(new base::ScopedPathOverride( | |
| 161 base::FILE_EXE, chrome_exe_, true /* is_absolute */, | |
| 162 false /* !create */)); | |
| 163 | |
| 164 // Override these paths with their own values so that they can be found | |
| 165 // after the registry override manager is in place. Getting them would | |
| 166 // otherwise fail since the underlying calls to the OS need to see the real | |
| 167 // contents of the registry. | |
| 168 static const int kPathKeys[] = { | |
| 169 base::DIR_PROGRAM_FILES, | |
| 170 base::DIR_PROGRAM_FILESX86, | |
| 171 base::DIR_LOCAL_APP_DATA, | |
| 172 }; | |
| 173 for (int key : kPathKeys) { | |
| 174 base::FilePath temp; | |
| 175 PathService::Get(key, &temp); | |
| 176 path_overrides_.push_back(new base::ScopedPathOverride(key, temp)); | |
| 177 } | |
| 178 | |
| 179 // Override the registry so that tests can freely push state to it. | |
| 180 registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER); | |
| 181 registry_override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE); | |
| 182 | |
| 183 distribution_ = BrowserDistribution::GetDistribution(); | |
| 184 } | |
| 185 | |
| 186 base::FilePath GetChromePath() const { | |
|
gab
2015/05/26 18:54:35
Move to private section.
And I'd call this GetChr
grt (UTC plus 2)
2015/05/26 20:54:01
Done.
| |
| 187 base::FilePath chrome_exe; | |
| 188 int dir_key = base::DIR_LOCAL_APP_DATA; | |
| 189 | |
| 190 if (system_install_) { | |
| 191 #if defined(_WIN64) | |
| 192 static const int kSystemKey = base::DIR_PROGRAM_FILESX86; | |
| 193 #else | |
| 194 static const int kSystemKey = base::DIR_PROGRAM_FILES; | |
| 195 #endif | |
| 196 dir_key = kSystemKey; | |
| 197 } | |
| 198 PathService::Get(dir_key, &chrome_exe); | |
| 199 #if defined(GOOGLE_CHROME_BUILD) | |
| 200 chrome_exe = chrome_exe.Append(installer::kGoogleChromeInstallSubDir1); | |
| 201 if (chrome_sxs_) { | |
| 202 chrome_exe = chrome_exe.Append( | |
| 203 base::string16(installer::kGoogleChromeInstallSubDir2) + | |
| 204 installer::kSxSSuffix); | |
| 205 } else { | |
| 206 chrome_exe = chrome_exe.Append(installer::kGoogleChromeInstallSubDir2); | |
| 207 } | |
| 208 #else | |
| 209 chrome_exe = chrome_exe.AppendASCII("Chromium"); | |
| 210 #endif | |
| 211 chrome_exe = chrome_exe.Append(installer::kInstallBinaryDir); | |
| 212 return chrome_exe.Append(installer::kChromeExe); | |
| 213 } | |
| 214 | |
| 215 bool system_install_; | |
| 216 bool chrome_sxs_; | |
| 217 base::FilePath chrome_exe_; | |
| 218 ScopedVector<base::ScopedPathOverride> path_overrides_; | |
| 219 registry_util::RegistryOverrideManager registry_override_manager_; | |
|
gab
2015/05/26 18:54:35
Move these two member to private:
grt (UTC plus 2)
2015/05/26 20:54:02
Done.
| |
| 220 BrowserDistribution* distribution_; | |
| 221 }; | |
| 222 | |
| 223 // Tests that the default browser beacons work as expected. | |
| 224 TEST_P(DefaultBrowserBeaconTest, Test) { | |
|
gab
2015/05/26 18:54:35
s/Test/All ? (feels weird to have a test named "Te
grt (UTC plus 2)
2015/05/26 20:54:02
"All" is more descriptive? Done.
gab
2015/05/29 13:37:36
I find so, i.e. it tests "everything" rather than
grt (UTC plus 2)
2015/05/29 15:31:10
I'm okay with "All".
| |
| 225 scoped_ptr<Beacon> last_was_default(Beacon::LastWasDefault( | |
| 226 system_install_, distribution_->GetAppRegistrationData())); | |
| 227 scoped_ptr<Beacon> first_not_default(Beacon::FirstNotDefault( | |
| 228 system_install_, distribution_->GetAppRegistrationData())); | |
| 229 | |
| 230 ASSERT_TRUE(last_was_default->Get().is_null()); | |
| 231 ASSERT_TRUE(first_not_default->Get().is_null()); | |
| 232 | |
| 233 // Chrome is not default. | |
| 234 UpdateDefaultBrowserBeacon(chrome_exe_, distribution_, | |
| 235 ShellUtil::NOT_DEFAULT); | |
| 236 ASSERT_TRUE(last_was_default->Get().is_null()); | |
| 237 ASSERT_FALSE(first_not_default->Get().is_null()); | |
| 238 | |
| 239 // Then it is. | |
| 240 UpdateDefaultBrowserBeacon(chrome_exe_, distribution_, ShellUtil::IS_DEFAULT); | |
| 241 ASSERT_FALSE(last_was_default->Get().is_null()); | |
| 242 ASSERT_TRUE(first_not_default->Get().is_null()); | |
| 243 | |
| 244 // It still is. | |
| 245 UpdateDefaultBrowserBeacon(chrome_exe_, distribution_, ShellUtil::IS_DEFAULT); | |
| 246 ASSERT_FALSE(last_was_default->Get().is_null()); | |
| 247 ASSERT_TRUE(first_not_default->Get().is_null()); | |
| 248 | |
| 249 // Now it's not again. | |
| 250 UpdateDefaultBrowserBeacon(chrome_exe_, distribution_, | |
| 251 ShellUtil::NOT_DEFAULT); | |
| 252 ASSERT_FALSE(last_was_default->Get().is_null()); | |
| 253 ASSERT_FALSE(first_not_default->Get().is_null()); | |
| 254 | |
| 255 // And it still isn't. | |
| 256 UpdateDefaultBrowserBeacon(chrome_exe_, distribution_, | |
| 257 ShellUtil::NOT_DEFAULT); | |
| 258 ASSERT_FALSE(last_was_default->Get().is_null()); | |
| 259 ASSERT_FALSE(first_not_default->Get().is_null()); | |
|
gab
2015/05/26 18:54:35
Shouldn't this test also check that the timestamps
grt (UTC plus 2)
2015/05/26 20:54:01
BeaconTest::UpdateAndGet and UpdateTwice cover eve
| |
| 260 } | |
| 261 | |
| 262 INSTANTIATE_TEST_CASE_P(SystemLevelChrome, | |
| 263 DefaultBrowserBeaconTest, | |
| 264 Values(DistributionVariant::SYSTEM_LEVEL_CHROME)); | |
| 265 INSTANTIATE_TEST_CASE_P(UserLevelChrome, | |
|
gab
2015/05/26 18:54:35
Oh cool, didn't know we could split various parame
grt (UTC plus 2)
2015/05/26 20:54:01
Acknowledged.
| |
| 266 DefaultBrowserBeaconTest, | |
| 267 Values(DistributionVariant::USER_LEVEL_CHROME)); | |
| 268 #if 0 && defined(GOOGLE_CHROME_BUILD) | |
| 269 // Disabled for now since InstallUtil::IsChromeSxSProcess makes this impossible. | |
|
gab
2015/05/26 18:54:35
Why? Can't we override DIR_EXE to fake this? i.e.
grt (UTC plus 2)
2015/05/26 20:54:01
That was what I hoped, except that it doesn't work
| |
| 270 INSTANTIATE_TEST_CASE_P(ChromeSxS, DefaultBrowserBeaconTest, | |
| 271 Values(DistributionVariant::CHROME_SXS)); | |
| 272 #endif | |
| OLD | NEW |