1 // Copyright (c) 2012 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.
8 #include "base/base_paths.h"
9 #include "base/command_line.h"
10 #include "base/files/file_util.h"
11 #include "base/path_service.h"
12 #include "base/strings/string_util.h"
13 #include "base/test/scoped_path_override.h"
14 #include "base/test/test_reg_util_win.h"
15 #include "base/win/registry.h"
16 #include "chrome/installer/util/google_update_constants.h"
17 #include "chrome/installer/util/install_util.h"
18 #include "chrome/installer/util/product_unittest.h"
19 #include "chrome/installer/util/work_item.h"
20 #include "testing/gmock/include/gmock/gmock.h"
22 using base::win::RegKey
;
23 using registry_util::RegistryOverrideManager
;
25 using ::testing::Return
;
26 using ::testing::StrEq
;
28 class MockRegistryValuePredicate
: public InstallUtil::RegistryValuePredicate
{
30 MOCK_CONST_METHOD1(Evaluate
, bool(const std::wstring
&));
33 class InstallUtilTest
: public TestWithTempDirAndDeleteTempOverrideKeys
{
37 TEST_F(InstallUtilTest
, MakeUninstallCommand
) {
38 base::CommandLine
command_line(base::CommandLine::NO_PROGRAM
);
40 std::pair
<std::wstring
, std::wstring
> params
[] = {
41 std::make_pair(std::wstring(L
""), std::wstring(L
"")),
42 std::make_pair(std::wstring(L
""), std::wstring(L
"--do-something --silly")),
43 std::make_pair(std::wstring(L
"spam.exe"), std::wstring(L
"")),
44 std::make_pair(std::wstring(L
"spam.exe"),
45 std::wstring(L
"--do-something --silly")),
47 for (int i
= 0; i
< arraysize(params
); ++i
) {
48 std::pair
<std::wstring
, std::wstring
>& param
= params
[i
];
49 InstallUtil::MakeUninstallCommand(param
.first
, param
.second
, &command_line
);
50 EXPECT_EQ(param
.first
, command_line
.GetProgram().value());
51 if (param
.second
.empty()) {
52 EXPECT_TRUE(command_line
.GetSwitches().empty());
54 EXPECT_EQ(2U, command_line
.GetSwitches().size());
55 EXPECT_TRUE(command_line
.HasSwitch("do-something"));
56 EXPECT_TRUE(command_line
.HasSwitch("silly"));
61 TEST_F(InstallUtilTest
, GetCurrentDate
) {
62 std::wstring
date(InstallUtil::GetCurrentDate());
63 EXPECT_EQ(8, date
.length());
64 if (date
.length() == 8) {
65 // For an invalid date value, SystemTimeToFileTime will fail.
66 // We use this to validate that we have a correct date string.
67 SYSTEMTIME systime
= {0};
69 // Just to make sure our assumption holds.
70 EXPECT_FALSE(SystemTimeToFileTime(&systime
, &ft
));
71 // Now fill in the values from our string.
72 systime
.wYear
= _wtoi(date
.substr(0, 4).c_str());
73 systime
.wMonth
= _wtoi(date
.substr(4, 2).c_str());
74 systime
.wDay
= _wtoi(date
.substr(6, 2).c_str());
75 // Check if they make sense.
76 EXPECT_TRUE(SystemTimeToFileTime(&systime
, &ft
));
80 TEST_F(InstallUtilTest
, UpdateInstallerStageAP
) {
81 const bool system_level
= false;
82 const HKEY root
= system_level
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
83 std::wstring
state_key_path(L
"PhonyClientState");
85 // Update the stage when there's no "ap" value.
87 RegistryOverrideManager override_manager
;
88 override_manager
.OverrideRegistry(root
);
89 RegKey(root
, state_key_path
.c_str(), KEY_SET_VALUE
);
90 InstallUtil::UpdateInstallerStage(system_level
, state_key_path
,
93 EXPECT_EQ(ERROR_SUCCESS
,
94 RegKey(root
, state_key_path
.c_str(), KEY_QUERY_VALUE
)
95 .ReadValue(google_update::kRegApField
, &value
));
96 EXPECT_EQ(L
"-stage:building", value
);
99 // Update the stage when there is an "ap" value.
101 RegistryOverrideManager override_manager
;
102 override_manager
.OverrideRegistry(root
);
103 RegKey(root
, state_key_path
.c_str(), KEY_SET_VALUE
)
104 .WriteValue(google_update::kRegApField
, L
"2.0-dev");
105 InstallUtil::UpdateInstallerStage(system_level
, state_key_path
,
106 installer::BUILDING
);
108 EXPECT_EQ(ERROR_SUCCESS
,
109 RegKey(root
, state_key_path
.c_str(), KEY_QUERY_VALUE
)
110 .ReadValue(google_update::kRegApField
, &value
));
111 EXPECT_EQ(L
"2.0-dev-stage:building", value
);
116 RegistryOverrideManager override_manager
;
117 override_manager
.OverrideRegistry(root
);
118 RegKey(root
, state_key_path
.c_str(), KEY_SET_VALUE
)
119 .WriteValue(google_update::kRegApField
, L
"2.0-dev-stage:building");
120 InstallUtil::UpdateInstallerStage(system_level
, state_key_path
,
121 installer::NO_STAGE
);
123 EXPECT_EQ(ERROR_SUCCESS
,
124 RegKey(root
, state_key_path
.c_str(), KEY_QUERY_VALUE
)
125 .ReadValue(google_update::kRegApField
, &value
));
126 EXPECT_EQ(L
"2.0-dev", value
);
130 TEST_F(InstallUtilTest
, UpdateInstallerStage
) {
131 const bool system_level
= false;
132 const HKEY root
= system_level
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
133 std::wstring
state_key_path(L
"PhonyClientState");
135 // Update the stage when there's no "InstallerExtraCode1" value.
137 RegistryOverrideManager override_manager
;
138 override_manager
.OverrideRegistry(root
);
139 RegKey(root
, state_key_path
.c_str(), KEY_SET_VALUE
)
140 .DeleteValue(installer::kInstallerExtraCode1
);
141 InstallUtil::UpdateInstallerStage(system_level
, state_key_path
,
142 installer::BUILDING
);
144 EXPECT_EQ(ERROR_SUCCESS
,
145 RegKey(root
, state_key_path
.c_str(), KEY_QUERY_VALUE
)
146 .ReadValueDW(installer::kInstallerExtraCode1
, &value
));
147 EXPECT_EQ(static_cast<DWORD
>(installer::BUILDING
), value
);
150 // Update the stage when there is an "InstallerExtraCode1" value.
152 RegistryOverrideManager override_manager
;
153 override_manager
.OverrideRegistry(root
);
154 RegKey(root
, state_key_path
.c_str(), KEY_SET_VALUE
)
155 .WriteValue(installer::kInstallerExtraCode1
,
156 static_cast<DWORD
>(installer::UNPACKING
));
157 InstallUtil::UpdateInstallerStage(system_level
, state_key_path
,
158 installer::BUILDING
);
160 EXPECT_EQ(ERROR_SUCCESS
,
161 RegKey(root
, state_key_path
.c_str(), KEY_QUERY_VALUE
)
162 .ReadValueDW(installer::kInstallerExtraCode1
, &value
));
163 EXPECT_EQ(static_cast<DWORD
>(installer::BUILDING
), value
);
168 RegistryOverrideManager override_manager
;
169 override_manager
.OverrideRegistry(root
);
170 RegKey(root
, state_key_path
.c_str(), KEY_SET_VALUE
)
171 .WriteValue(installer::kInstallerExtraCode1
, static_cast<DWORD
>(5));
172 InstallUtil::UpdateInstallerStage(system_level
, state_key_path
,
173 installer::NO_STAGE
);
175 EXPECT_EQ(ERROR_FILE_NOT_FOUND
,
176 RegKey(root
, state_key_path
.c_str(), KEY_QUERY_VALUE
)
177 .ReadValueDW(installer::kInstallerExtraCode1
, &value
));
181 TEST_F(InstallUtilTest
, DeleteRegistryKeyIf
) {
182 const HKEY root
= HKEY_CURRENT_USER
;
183 std::wstring
parent_key_path(L
"SomeKey\\ToDelete");
184 std::wstring
child_key_path(parent_key_path
);
185 child_key_path
.append(L
"\\ChildKey\\WithAValue");
186 const wchar_t value_name
[] = L
"some_value_name";
187 const wchar_t value
[] = L
"hi mom";
190 RegistryOverrideManager override_manager
;
191 override_manager
.OverrideRegistry(root
);
192 // Nothing to delete if the keys aren't even there.
194 MockRegistryValuePredicate pred
;
196 EXPECT_CALL(pred
, Evaluate(_
)).Times(0);
197 ASSERT_FALSE(RegKey(root
, parent_key_path
.c_str(),
198 KEY_QUERY_VALUE
).Valid());
199 EXPECT_EQ(InstallUtil::NOT_FOUND
,
200 InstallUtil::DeleteRegistryKeyIf(root
, parent_key_path
,
202 WorkItem::kWow64Default
,
204 EXPECT_FALSE(RegKey(root
, parent_key_path
.c_str(),
205 KEY_QUERY_VALUE
).Valid());
208 // Parent exists, but not child: no delete.
210 MockRegistryValuePredicate pred
;
212 EXPECT_CALL(pred
, Evaluate(_
)).Times(0);
213 ASSERT_TRUE(RegKey(root
, parent_key_path
.c_str(), KEY_SET_VALUE
).Valid());
214 EXPECT_EQ(InstallUtil::NOT_FOUND
,
215 InstallUtil::DeleteRegistryKeyIf(root
, parent_key_path
,
217 WorkItem::kWow64Default
,
219 EXPECT_TRUE(RegKey(root
, parent_key_path
.c_str(),
220 KEY_QUERY_VALUE
).Valid());
223 // Child exists, but no value: no delete.
225 MockRegistryValuePredicate pred
;
227 EXPECT_CALL(pred
, Evaluate(_
)).Times(0);
228 ASSERT_TRUE(RegKey(root
, child_key_path
.c_str(), KEY_SET_VALUE
).Valid());
229 EXPECT_EQ(InstallUtil::NOT_FOUND
,
230 InstallUtil::DeleteRegistryKeyIf(root
, parent_key_path
,
232 WorkItem::kWow64Default
,
234 EXPECT_TRUE(RegKey(root
, parent_key_path
.c_str(),
235 KEY_QUERY_VALUE
).Valid());
238 // Value exists, but doesn't match: no delete.
240 MockRegistryValuePredicate pred
;
242 EXPECT_CALL(pred
, Evaluate(StrEq(L
"foosball!"))).WillOnce(Return(false));
243 ASSERT_EQ(ERROR_SUCCESS
,
244 RegKey(root
, child_key_path
.c_str(),
245 KEY_SET_VALUE
).WriteValue(value_name
, L
"foosball!"));
246 EXPECT_EQ(InstallUtil::NOT_FOUND
,
247 InstallUtil::DeleteRegistryKeyIf(root
, parent_key_path
,
249 WorkItem::kWow64Default
,
251 EXPECT_TRUE(RegKey(root
, parent_key_path
.c_str(),
252 KEY_QUERY_VALUE
).Valid());
255 // Value exists, and matches: delete.
257 MockRegistryValuePredicate pred
;
259 EXPECT_CALL(pred
, Evaluate(StrEq(value
))).WillOnce(Return(true));
260 ASSERT_EQ(ERROR_SUCCESS
,
261 RegKey(root
, child_key_path
.c_str(),
262 KEY_SET_VALUE
).WriteValue(value_name
, value
));
263 EXPECT_EQ(InstallUtil::DELETED
,
264 InstallUtil::DeleteRegistryKeyIf(root
, parent_key_path
,
266 WorkItem::kWow64Default
,
268 EXPECT_FALSE(RegKey(root
, parent_key_path
.c_str(),
269 KEY_QUERY_VALUE
).Valid());
272 // Default value exists and matches: delete.
274 MockRegistryValuePredicate pred
;
276 EXPECT_CALL(pred
, Evaluate(StrEq(value
))).WillOnce(Return(true));
277 ASSERT_EQ(ERROR_SUCCESS
,
278 RegKey(root
, child_key_path
.c_str(),
279 KEY_SET_VALUE
).WriteValue(NULL
, value
));
280 EXPECT_EQ(InstallUtil::DELETED
,
281 InstallUtil::DeleteRegistryKeyIf(root
, parent_key_path
,
283 WorkItem::kWow64Default
,
285 EXPECT_FALSE(RegKey(root
, parent_key_path
.c_str(),
286 KEY_QUERY_VALUE
).Valid());
291 TEST_F(InstallUtilTest
, DeleteRegistryValueIf
) {
292 const HKEY root
= HKEY_CURRENT_USER
;
293 std::wstring
key_path(L
"SomeKey\\ToDelete");
294 const wchar_t value_name
[] = L
"some_value_name";
295 const wchar_t value
[] = L
"hi mom";
298 RegistryOverrideManager override_manager
;
299 override_manager
.OverrideRegistry(root
);
300 // Nothing to delete if the key isn't even there.
302 MockRegistryValuePredicate pred
;
304 EXPECT_CALL(pred
, Evaluate(_
)).Times(0);
305 ASSERT_FALSE(RegKey(root
, key_path
.c_str(), KEY_QUERY_VALUE
).Valid());
306 EXPECT_EQ(InstallUtil::NOT_FOUND
,
307 InstallUtil::DeleteRegistryValueIf(root
, key_path
.c_str(),
308 WorkItem::kWow64Default
,
310 EXPECT_FALSE(RegKey(root
, key_path
.c_str(), KEY_QUERY_VALUE
).Valid());
313 // Key exists, but no value: no delete.
315 MockRegistryValuePredicate pred
;
317 EXPECT_CALL(pred
, Evaluate(_
)).Times(0);
318 ASSERT_TRUE(RegKey(root
, key_path
.c_str(), KEY_SET_VALUE
).Valid());
319 EXPECT_EQ(InstallUtil::NOT_FOUND
,
320 InstallUtil::DeleteRegistryValueIf(root
, key_path
.c_str(),
321 WorkItem::kWow64Default
,
323 EXPECT_TRUE(RegKey(root
, key_path
.c_str(), KEY_QUERY_VALUE
).Valid());
326 // Value exists, but doesn't match: no delete.
328 MockRegistryValuePredicate pred
;
330 EXPECT_CALL(pred
, Evaluate(StrEq(L
"foosball!"))).WillOnce(Return(false));
331 ASSERT_EQ(ERROR_SUCCESS
,
332 RegKey(root
, key_path
.c_str(),
333 KEY_SET_VALUE
).WriteValue(value_name
, L
"foosball!"));
334 EXPECT_EQ(InstallUtil::NOT_FOUND
,
335 InstallUtil::DeleteRegistryValueIf(root
, key_path
.c_str(),
336 WorkItem::kWow64Default
,
338 EXPECT_TRUE(RegKey(root
, key_path
.c_str(), KEY_QUERY_VALUE
).Valid());
339 EXPECT_TRUE(RegKey(root
, key_path
.c_str(),
340 KEY_QUERY_VALUE
).HasValue(value_name
));
343 // Value exists, and matches: delete.
345 MockRegistryValuePredicate pred
;
347 EXPECT_CALL(pred
, Evaluate(StrEq(value
))).WillOnce(Return(true));
348 ASSERT_EQ(ERROR_SUCCESS
,
349 RegKey(root
, key_path
.c_str(),
350 KEY_SET_VALUE
).WriteValue(value_name
, value
));
351 EXPECT_EQ(InstallUtil::DELETED
,
352 InstallUtil::DeleteRegistryValueIf(root
, key_path
.c_str(),
353 WorkItem::kWow64Default
,
355 EXPECT_TRUE(RegKey(root
, key_path
.c_str(), KEY_QUERY_VALUE
).Valid());
356 EXPECT_FALSE(RegKey(root
, key_path
.c_str(),
357 KEY_QUERY_VALUE
).HasValue(value_name
));
362 RegistryOverrideManager override_manager
;
363 override_manager
.OverrideRegistry(root
);
364 // Default value matches: delete using empty string.
366 MockRegistryValuePredicate pred
;
368 EXPECT_CALL(pred
, Evaluate(StrEq(value
))).WillOnce(Return(true));
369 ASSERT_EQ(ERROR_SUCCESS
,
370 RegKey(root
, key_path
.c_str(),
371 KEY_SET_VALUE
).WriteValue(L
"", value
));
372 EXPECT_EQ(InstallUtil::DELETED
,
373 InstallUtil::DeleteRegistryValueIf(root
, key_path
.c_str(),
374 WorkItem::kWow64Default
, L
"",
376 EXPECT_TRUE(RegKey(root
, key_path
.c_str(), KEY_QUERY_VALUE
).Valid());
377 EXPECT_FALSE(RegKey(root
, key_path
.c_str(),
378 KEY_QUERY_VALUE
).HasValue(L
""));
383 RegistryOverrideManager override_manager
;
384 override_manager
.OverrideRegistry(root
);
385 // Default value matches: delete using NULL.
387 MockRegistryValuePredicate pred
;
389 EXPECT_CALL(pred
, Evaluate(StrEq(value
))).WillOnce(Return(true));
390 ASSERT_EQ(ERROR_SUCCESS
,
391 RegKey(root
, key_path
.c_str(),
392 KEY_SET_VALUE
).WriteValue(L
"", value
));
393 EXPECT_EQ(InstallUtil::DELETED
,
394 InstallUtil::DeleteRegistryValueIf(root
, key_path
.c_str(),
395 WorkItem::kWow64Default
,
397 EXPECT_TRUE(RegKey(root
, key_path
.c_str(), KEY_QUERY_VALUE
).Valid());
398 EXPECT_FALSE(RegKey(root
, key_path
.c_str(),
399 KEY_QUERY_VALUE
).HasValue(L
""));
404 TEST_F(InstallUtilTest
, ValueEquals
) {
405 InstallUtil::ValueEquals
pred(L
"howdy");
407 EXPECT_FALSE(pred
.Evaluate(L
""));
408 EXPECT_FALSE(pred
.Evaluate(L
"Howdy"));
409 EXPECT_FALSE(pred
.Evaluate(L
"howdy!"));
410 EXPECT_FALSE(pred
.Evaluate(L
"!howdy"));
411 EXPECT_TRUE(pred
.Evaluate(L
"howdy"));
414 TEST_F(InstallUtilTest
, ProgramCompare
) {
415 base::FilePath
some_long_dir(
416 test_dir_
.path().Append(L
"Some Long Directory Name"));
417 base::FilePath
expect(some_long_dir
.Append(L
"file.txt"));
418 base::FilePath
expect_upcase(some_long_dir
.Append(L
"FILE.txt"));
419 base::FilePath
other(some_long_dir
.Append(L
"otherfile.txt"));
421 // Tests where the expected file doesn't exist.
423 // Paths don't match.
424 EXPECT_FALSE(InstallUtil::ProgramCompare(expect
).Evaluate(
425 L
"\"" + other
.value() + L
"\""));
426 // Paths match exactly.
427 EXPECT_TRUE(InstallUtil::ProgramCompare(expect
).Evaluate(
428 L
"\"" + expect
.value() + L
"\""));
429 // Paths differ by case.
430 EXPECT_TRUE(InstallUtil::ProgramCompare(expect
).Evaluate(
431 L
"\"" + expect_upcase
.value() + L
"\""));
433 // Tests where the expected file exists.
434 static const char data
[] = "data";
435 ASSERT_TRUE(base::CreateDirectory(some_long_dir
));
436 ASSERT_NE(-1, base::WriteFile(expect
, data
, arraysize(data
) - 1));
437 // Paths don't match.
438 EXPECT_FALSE(InstallUtil::ProgramCompare(expect
).Evaluate(
439 L
"\"" + other
.value() + L
"\""));
440 // Paths match exactly.
441 EXPECT_TRUE(InstallUtil::ProgramCompare(expect
).Evaluate(
442 L
"\"" + expect
.value() + L
"\""));
443 // Paths differ by case.
444 EXPECT_TRUE(InstallUtil::ProgramCompare(expect
).Evaluate(
445 L
"\"" + expect_upcase
.value() + L
"\""));
447 // Test where strings don't match, but the same file is indicated.
448 std::wstring short_expect
;
449 DWORD short_len
= GetShortPathName(expect
.value().c_str(),
450 WriteInto(&short_expect
, MAX_PATH
),
452 ASSERT_NE(static_cast<DWORD
>(0), short_len
);
453 ASSERT_GT(static_cast<DWORD
>(MAX_PATH
), short_len
);
454 short_expect
.resize(short_len
);
455 ASSERT_FALSE(base::FilePath::CompareEqualIgnoreCase(expect
.value(),
457 EXPECT_TRUE(InstallUtil::ProgramCompare(expect
).Evaluate(
458 L
"\"" + short_expect
+ L
"\""));
461 // Win64 Chrome is always installed in the 32-bit Program Files directory. Test
462 // that IsPerUserInstall returns false for an arbitrary path with
463 // DIR_PROGRAM_FILESX86 as a suffix but not DIR_PROGRAM_FILES when the two are
465 TEST_F(InstallUtilTest
, IsPerUserInstall
) {
467 const int kChromeProgramFilesKey
= base::DIR_PROGRAM_FILESX86
;
469 const int kChromeProgramFilesKey
= base::DIR_PROGRAM_FILES
;
471 base::ScopedPathOverride
program_files_override(kChromeProgramFilesKey
);
472 base::FilePath some_exe
;
473 ASSERT_TRUE(PathService::Get(kChromeProgramFilesKey
, &some_exe
));
474 some_exe
= some_exe
.AppendASCII("Company")
475 .AppendASCII("Product")
476 .AppendASCII("product.exe");
477 EXPECT_FALSE(InstallUtil::IsPerUserInstall(some_exe
));
480 const int kOtherProgramFilesKey
= base::DIR_PROGRAM_FILES
;
481 base::ScopedPathOverride
other_program_files_override(kOtherProgramFilesKey
);
482 ASSERT_TRUE(PathService::Get(kOtherProgramFilesKey
, &some_exe
));
483 some_exe
= some_exe
.AppendASCII("Company")
484 .AppendASCII("Product")
485 .AppendASCII("product.exe");
486 EXPECT_TRUE(InstallUtil::IsPerUserInstall(some_exe
));
487 #endif // defined(_WIN64)