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. 4 5 #include <string> 6 #include <utility> 7 8 #include "base/command_line.h" 9 #include "base/file_util.h" 10 #include "base/strings/string_util.h" 11 #include "base/test/test_reg_util_win.h" 12 #include "base/win/registry.h" 13 #include "chrome/installer/util/google_update_constants.h" 14 #include "chrome/installer/util/install_util.h" 15 #include "chrome/installer/util/product_unittest.h" 16 #include "testing/gmock/include/gmock/gmock.h" 17 18 using base::win::RegKey; 19 using registry_util::RegistryOverrideManager; 20 using ::testing::_; 21 using ::testing::Return; 22 using ::testing::StrEq; 23 24 class MockRegistryValuePredicate : public InstallUtil::RegistryValuePredicate { 25 public: 26 MOCK_CONST_METHOD1(Evaluate, bool(const std::wstring&)); 27 }; 28 29 class InstallUtilTest : public TestWithTempDirAndDeleteTempOverrideKeys { 30 protected: 31 }; 32 33 TEST_F(InstallUtilTest, MakeUninstallCommand) { 34 CommandLine command_line(CommandLine::NO_PROGRAM); 35 36 std::pair<std::wstring, std::wstring> params[] = { 37 std::make_pair(std::wstring(L""), std::wstring(L"")), 38 std::make_pair(std::wstring(L""), std::wstring(L"--do-something --silly")), 39 std::make_pair(std::wstring(L"spam.exe"), std::wstring(L"")), 40 std::make_pair(std::wstring(L"spam.exe"), 41 std::wstring(L"--do-something --silly")), 42 }; 43 for (int i = 0; i < arraysize(params); ++i) { 44 std::pair<std::wstring, std::wstring>& param = params[i]; 45 InstallUtil::MakeUninstallCommand(param.first, param.second, &command_line); 46 EXPECT_EQ(param.first, command_line.GetProgram().value()); 47 if (param.second.empty()) { 48 EXPECT_TRUE(command_line.GetSwitches().empty()); 49 } else { 50 EXPECT_EQ(2U, command_line.GetSwitches().size()); 51 EXPECT_TRUE(command_line.HasSwitch("do-something")); 52 EXPECT_TRUE(command_line.HasSwitch("silly")); 53 } 54 } 55 } 56 57 TEST_F(InstallUtilTest, GetCurrentDate) { 58 std::wstring date(InstallUtil::GetCurrentDate()); 59 EXPECT_EQ(8, date.length()); 60 if (date.length() == 8) { 61 // For an invalid date value, SystemTimeToFileTime will fail. 62 // We use this to validate that we have a correct date string. 63 SYSTEMTIME systime = {0}; 64 FILETIME ft = {0}; 65 // Just to make sure our assumption holds. 66 EXPECT_FALSE(SystemTimeToFileTime(&systime, &ft)); 67 // Now fill in the values from our string. 68 systime.wYear = _wtoi(date.substr(0, 4).c_str()); 69 systime.wMonth = _wtoi(date.substr(4, 2).c_str()); 70 systime.wDay = _wtoi(date.substr(6, 2).c_str()); 71 // Check if they make sense. 72 EXPECT_TRUE(SystemTimeToFileTime(&systime, &ft)); 73 } 74 } 75 76 TEST_F(InstallUtilTest, UpdateInstallerStageAP) { 77 const bool system_level = false; 78 const HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 79 std::wstring state_key_path(L"PhonyClientState"); 80 81 // Update the stage when there's no "ap" value. 82 { 83 RegistryOverrideManager override_manager; 84 override_manager.OverrideRegistry(root, L"root_inst_res"); 85 RegKey(root, state_key_path.c_str(), KEY_SET_VALUE); 86 InstallUtil::UpdateInstallerStage(system_level, state_key_path, 87 installer::BUILDING); 88 std::wstring value; 89 EXPECT_EQ(ERROR_SUCCESS, 90 RegKey(root, state_key_path.c_str(), KEY_QUERY_VALUE) 91 .ReadValue(google_update::kRegApField, &value)); 92 EXPECT_EQ(L"-stage:building", value); 93 } 94 95 // Update the stage when there is an "ap" value. 96 { 97 RegistryOverrideManager override_manager; 98 override_manager.OverrideRegistry(root, L"root_inst_res"); 99 RegKey(root, state_key_path.c_str(), KEY_SET_VALUE) 100 .WriteValue(google_update::kRegApField, L"2.0-dev"); 101 InstallUtil::UpdateInstallerStage(system_level, state_key_path, 102 installer::BUILDING); 103 std::wstring value; 104 EXPECT_EQ(ERROR_SUCCESS, 105 RegKey(root, state_key_path.c_str(), KEY_QUERY_VALUE) 106 .ReadValue(google_update::kRegApField, &value)); 107 EXPECT_EQ(L"2.0-dev-stage:building", value); 108 } 109 110 // Clear the stage. 111 { 112 RegistryOverrideManager override_manager; 113 override_manager.OverrideRegistry(root, L"root_inst_res"); 114 RegKey(root, state_key_path.c_str(), KEY_SET_VALUE) 115 .WriteValue(google_update::kRegApField, L"2.0-dev-stage:building"); 116 InstallUtil::UpdateInstallerStage(system_level, state_key_path, 117 installer::NO_STAGE); 118 std::wstring value; 119 EXPECT_EQ(ERROR_SUCCESS, 120 RegKey(root, state_key_path.c_str(), KEY_QUERY_VALUE) 121 .ReadValue(google_update::kRegApField, &value)); 122 EXPECT_EQ(L"2.0-dev", value); 123 } 124 } 125 126 TEST_F(InstallUtilTest, UpdateInstallerStage) { 127 const bool system_level = false; 128 const HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 129 std::wstring state_key_path(L"PhonyClientState"); 130 131 // Update the stage when there's no "InstallerExtraCode1" value. 132 { 133 RegistryOverrideManager override_manager; 134 override_manager.OverrideRegistry(root, L"root_inst_res"); 135 RegKey(root, state_key_path.c_str(), KEY_SET_VALUE) 136 .DeleteValue(installer::kInstallerExtraCode1); 137 InstallUtil::UpdateInstallerStage(system_level, state_key_path, 138 installer::BUILDING); 139 DWORD value; 140 EXPECT_EQ(ERROR_SUCCESS, 141 RegKey(root, state_key_path.c_str(), KEY_QUERY_VALUE) 142 .ReadValueDW(installer::kInstallerExtraCode1, &value)); 143 EXPECT_EQ(static_cast<DWORD>(installer::BUILDING), value); 144 } 145 146 // Update the stage when there is an "InstallerExtraCode1" value. 147 { 148 RegistryOverrideManager override_manager; 149 override_manager.OverrideRegistry(root, L"root_inst_res"); 150 RegKey(root, state_key_path.c_str(), KEY_SET_VALUE) 151 .WriteValue(installer::kInstallerExtraCode1, 152 static_cast<DWORD>(installer::UNPACKING)); 153 InstallUtil::UpdateInstallerStage(system_level, state_key_path, 154 installer::BUILDING); 155 DWORD value; 156 EXPECT_EQ(ERROR_SUCCESS, 157 RegKey(root, state_key_path.c_str(), KEY_QUERY_VALUE) 158 .ReadValueDW(installer::kInstallerExtraCode1, &value)); 159 EXPECT_EQ(static_cast<DWORD>(installer::BUILDING), value); 160 } 161 162 // Clear the stage. 163 { 164 RegistryOverrideManager override_manager; 165 override_manager.OverrideRegistry(root, L"root_inst_res"); 166 RegKey(root, state_key_path.c_str(), KEY_SET_VALUE) 167 .WriteValue(installer::kInstallerExtraCode1, static_cast<DWORD>(5)); 168 InstallUtil::UpdateInstallerStage(system_level, state_key_path, 169 installer::NO_STAGE); 170 DWORD value; 171 EXPECT_EQ(ERROR_FILE_NOT_FOUND, 172 RegKey(root, state_key_path.c_str(), KEY_QUERY_VALUE) 173 .ReadValueDW(installer::kInstallerExtraCode1, &value)); 174 } 175 } 176 177 TEST_F(InstallUtilTest, DeleteRegistryKeyIf) { 178 const HKEY root = HKEY_CURRENT_USER; 179 std::wstring parent_key_path(L"SomeKey\\ToDelete"); 180 std::wstring child_key_path(parent_key_path); 181 child_key_path.append(L"\\ChildKey\\WithAValue"); 182 const wchar_t value_name[] = L"some_value_name"; 183 const wchar_t value[] = L"hi mom"; 184 185 { 186 RegistryOverrideManager override_manager; 187 override_manager.OverrideRegistry(root, L"root_key"); 188 // Nothing to delete if the keys aren't even there. 189 { 190 MockRegistryValuePredicate pred; 191 192 EXPECT_CALL(pred, Evaluate(_)).Times(0); 193 ASSERT_FALSE(RegKey(root, parent_key_path.c_str(), 194 KEY_QUERY_VALUE).Valid()); 195 EXPECT_EQ(InstallUtil::NOT_FOUND, 196 InstallUtil::DeleteRegistryKeyIf(root, parent_key_path, 197 child_key_path, value_name, 198 pred)); 199 EXPECT_FALSE(RegKey(root, parent_key_path.c_str(), 200 KEY_QUERY_VALUE).Valid()); 201 } 202 203 // Parent exists, but not child: no delete. 204 { 205 MockRegistryValuePredicate pred; 206 207 EXPECT_CALL(pred, Evaluate(_)).Times(0); 208 ASSERT_TRUE(RegKey(root, parent_key_path.c_str(), KEY_SET_VALUE).Valid()); 209 EXPECT_EQ(InstallUtil::NOT_FOUND, 210 InstallUtil::DeleteRegistryKeyIf(root, parent_key_path, 211 child_key_path, value_name, 212 pred)); 213 EXPECT_TRUE(RegKey(root, parent_key_path.c_str(), 214 KEY_QUERY_VALUE).Valid()); 215 } 216 217 // Child exists, but no value: no delete. 218 { 219 MockRegistryValuePredicate pred; 220 221 EXPECT_CALL(pred, Evaluate(_)).Times(0); 222 ASSERT_TRUE(RegKey(root, child_key_path.c_str(), KEY_SET_VALUE).Valid()); 223 EXPECT_EQ(InstallUtil::NOT_FOUND, 224 InstallUtil::DeleteRegistryKeyIf(root, parent_key_path, 225 child_key_path, value_name, 226 pred)); 227 EXPECT_TRUE(RegKey(root, parent_key_path.c_str(), 228 KEY_QUERY_VALUE).Valid()); 229 } 230 231 // Value exists, but doesn't match: no delete. 232 { 233 MockRegistryValuePredicate pred; 234 235 EXPECT_CALL(pred, Evaluate(StrEq(L"foosball!"))).WillOnce(Return(false)); 236 ASSERT_EQ(ERROR_SUCCESS, 237 RegKey(root, child_key_path.c_str(), 238 KEY_SET_VALUE).WriteValue(value_name, L"foosball!")); 239 EXPECT_EQ(InstallUtil::NOT_FOUND, 240 InstallUtil::DeleteRegistryKeyIf(root, parent_key_path, 241 child_key_path, value_name, 242 pred)); 243 EXPECT_TRUE(RegKey(root, parent_key_path.c_str(), 244 KEY_QUERY_VALUE).Valid()); 245 } 246 247 // Value exists, and matches: delete. 248 { 249 MockRegistryValuePredicate pred; 250 251 EXPECT_CALL(pred, Evaluate(StrEq(value))).WillOnce(Return(true)); 252 ASSERT_EQ(ERROR_SUCCESS, 253 RegKey(root, child_key_path.c_str(), 254 KEY_SET_VALUE).WriteValue(value_name, value)); 255 EXPECT_EQ(InstallUtil::DELETED, 256 InstallUtil::DeleteRegistryKeyIf(root, parent_key_path, 257 child_key_path, value_name, 258 pred)); 259 EXPECT_FALSE(RegKey(root, parent_key_path.c_str(), 260 KEY_QUERY_VALUE).Valid()); 261 } 262 263 // Default value exists and matches: delete. 264 { 265 MockRegistryValuePredicate pred; 266 267 EXPECT_CALL(pred, Evaluate(StrEq(value))).WillOnce(Return(true)); 268 ASSERT_EQ(ERROR_SUCCESS, 269 RegKey(root, child_key_path.c_str(), 270 KEY_SET_VALUE).WriteValue(NULL, value)); 271 EXPECT_EQ(InstallUtil::DELETED, 272 InstallUtil::DeleteRegistryKeyIf(root, parent_key_path, 273 child_key_path, NULL, 274 pred)); 275 EXPECT_FALSE(RegKey(root, parent_key_path.c_str(), 276 KEY_QUERY_VALUE).Valid()); 277 } 278 } 279 } 280 281 TEST_F(InstallUtilTest, DeleteRegistryValueIf) { 282 const HKEY root = HKEY_CURRENT_USER; 283 std::wstring key_path(L"SomeKey\\ToDelete"); 284 const wchar_t value_name[] = L"some_value_name"; 285 const wchar_t value[] = L"hi mom"; 286 287 { 288 RegistryOverrideManager override_manager; 289 override_manager.OverrideRegistry(root, L"root_key"); 290 // Nothing to delete if the key isn't even there. 291 { 292 MockRegistryValuePredicate pred; 293 294 EXPECT_CALL(pred, Evaluate(_)).Times(0); 295 ASSERT_FALSE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid()); 296 EXPECT_EQ(InstallUtil::NOT_FOUND, 297 InstallUtil::DeleteRegistryValueIf(root, key_path.c_str(), 298 value_name, pred)); 299 EXPECT_FALSE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid()); 300 } 301 302 // Key exists, but no value: no delete. 303 { 304 MockRegistryValuePredicate pred; 305 306 EXPECT_CALL(pred, Evaluate(_)).Times(0); 307 ASSERT_TRUE(RegKey(root, key_path.c_str(), KEY_SET_VALUE).Valid()); 308 EXPECT_EQ(InstallUtil::NOT_FOUND, 309 InstallUtil::DeleteRegistryValueIf(root, key_path.c_str(), 310 value_name, pred)); 311 EXPECT_TRUE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid()); 312 } 313 314 // Value exists, but doesn't match: no delete. 315 { 316 MockRegistryValuePredicate pred; 317 318 EXPECT_CALL(pred, Evaluate(StrEq(L"foosball!"))).WillOnce(Return(false)); 319 ASSERT_EQ(ERROR_SUCCESS, 320 RegKey(root, key_path.c_str(), 321 KEY_SET_VALUE).WriteValue(value_name, L"foosball!")); 322 EXPECT_EQ(InstallUtil::NOT_FOUND, 323 InstallUtil::DeleteRegistryValueIf(root, key_path.c_str(), 324 value_name, pred)); 325 EXPECT_TRUE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid()); 326 EXPECT_TRUE(RegKey(root, key_path.c_str(), 327 KEY_QUERY_VALUE).HasValue(value_name)); 328 } 329 330 // Value exists, and matches: delete. 331 { 332 MockRegistryValuePredicate pred; 333 334 EXPECT_CALL(pred, Evaluate(StrEq(value))).WillOnce(Return(true)); 335 ASSERT_EQ(ERROR_SUCCESS, 336 RegKey(root, key_path.c_str(), 337 KEY_SET_VALUE).WriteValue(value_name, value)); 338 EXPECT_EQ(InstallUtil::DELETED, 339 InstallUtil::DeleteRegistryValueIf(root, key_path.c_str(), 340 value_name, pred)); 341 EXPECT_TRUE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid()); 342 EXPECT_FALSE(RegKey(root, key_path.c_str(), 343 KEY_QUERY_VALUE).HasValue(value_name)); 344 } 345 } 346 347 { 348 RegistryOverrideManager override_manager; 349 override_manager.OverrideRegistry(root, L"root_key"); 350 // Default value matches: delete using empty string. 351 { 352 MockRegistryValuePredicate pred; 353 354 EXPECT_CALL(pred, Evaluate(StrEq(value))).WillOnce(Return(true)); 355 ASSERT_EQ(ERROR_SUCCESS, 356 RegKey(root, key_path.c_str(), 357 KEY_SET_VALUE).WriteValue(L"", value)); 358 EXPECT_EQ(InstallUtil::DELETED, 359 InstallUtil::DeleteRegistryValueIf(root, key_path.c_str(), L"", 360 pred)); 361 EXPECT_TRUE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid()); 362 EXPECT_FALSE(RegKey(root, key_path.c_str(), 363 KEY_QUERY_VALUE).HasValue(L"")); 364 } 365 } 366 367 { 368 RegistryOverrideManager override_manager; 369 override_manager.OverrideRegistry(root, L"root_key"); 370 // Default value matches: delete using NULL. 371 { 372 MockRegistryValuePredicate pred; 373 374 EXPECT_CALL(pred, Evaluate(StrEq(value))).WillOnce(Return(true)); 375 ASSERT_EQ(ERROR_SUCCESS, 376 RegKey(root, key_path.c_str(), 377 KEY_SET_VALUE).WriteValue(L"", value)); 378 EXPECT_EQ(InstallUtil::DELETED, 379 InstallUtil::DeleteRegistryValueIf(root, key_path.c_str(), 380 NULL, pred)); 381 EXPECT_TRUE(RegKey(root, key_path.c_str(), KEY_QUERY_VALUE).Valid()); 382 EXPECT_FALSE(RegKey(root, key_path.c_str(), 383 KEY_QUERY_VALUE).HasValue(L"")); 384 } 385 } 386 } 387 388 TEST_F(InstallUtilTest, ValueEquals) { 389 InstallUtil::ValueEquals pred(L"howdy"); 390 391 EXPECT_FALSE(pred.Evaluate(L"")); 392 EXPECT_FALSE(pred.Evaluate(L"Howdy")); 393 EXPECT_FALSE(pred.Evaluate(L"howdy!")); 394 EXPECT_FALSE(pred.Evaluate(L"!howdy")); 395 EXPECT_TRUE(pred.Evaluate(L"howdy")); 396 } 397 398 TEST_F(InstallUtilTest, ProgramCompare) { 399 base::FilePath some_long_dir( 400 test_dir_.path().Append(L"Some Long Directory Name")); 401 base::FilePath expect(some_long_dir.Append(L"file.txt")); 402 base::FilePath expect_upcase(some_long_dir.Append(L"FILE.txt")); 403 base::FilePath other(some_long_dir.Append(L"otherfile.txt")); 404 405 // Tests where the expected file doesn't exist. 406 407 // Paths don't match. 408 EXPECT_FALSE(InstallUtil::ProgramCompare(expect).Evaluate( 409 L"\"" + other.value() + L"\"")); 410 // Paths match exactly. 411 EXPECT_TRUE(InstallUtil::ProgramCompare(expect).Evaluate( 412 L"\"" + expect.value() + L"\"")); 413 // Paths differ by case. 414 EXPECT_TRUE(InstallUtil::ProgramCompare(expect).Evaluate( 415 L"\"" + expect_upcase.value() + L"\"")); 416 417 // Tests where the expected file exists. 418 static const char data[] = "data"; 419 ASSERT_TRUE(base::CreateDirectory(some_long_dir)); 420 ASSERT_NE(-1, file_util::WriteFile(expect, data, arraysize(data) - 1)); 421 // Paths don't match. 422 EXPECT_FALSE(InstallUtil::ProgramCompare(expect).Evaluate( 423 L"\"" + other.value() + L"\"")); 424 // Paths match exactly. 425 EXPECT_TRUE(InstallUtil::ProgramCompare(expect).Evaluate( 426 L"\"" + expect.value() + L"\"")); 427 // Paths differ by case. 428 EXPECT_TRUE(InstallUtil::ProgramCompare(expect).Evaluate( 429 L"\"" + expect_upcase.value() + L"\"")); 430 431 // Test where strings don't match, but the same file is indicated. 432 std::wstring short_expect; 433 DWORD short_len = GetShortPathName(expect.value().c_str(), 434 WriteInto(&short_expect, MAX_PATH), 435 MAX_PATH); 436 ASSERT_NE(static_cast<DWORD>(0), short_len); 437 ASSERT_GT(static_cast<DWORD>(MAX_PATH), short_len); 438 short_expect.resize(short_len); 439 ASSERT_FALSE(base::FilePath::CompareEqualIgnoreCase(expect.value(), 440 short_expect)); 441 EXPECT_TRUE(InstallUtil::ProgramCompare(expect).Evaluate( 442 L"\"" + short_expect + L"\"")); 443 } 444