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