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 |