product_state_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2011 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 <windows.h> 6 7#include "base/utf_string_conversions.h" 8#include "base/test/test_reg_util_win.h" 9#include "base/version.h" 10#include "base/win/registry.h" 11#include "chrome/installer/util/browser_distribution.h" 12#include "chrome/installer/util/google_update_constants.h" 13#include "chrome/installer/util/installation_state.h" 14#include "chrome/installer/util/product_unittest.h" 15#include "chrome/installer/util/util_constants.h" 16#include "testing/gtest/include/gtest/gtest.h" 17 18using base::win::RegKey; 19using installer::ProductState; 20using registry_util::RegistryOverrideManager; 21 22class ProductStateTest : public testing::Test { 23 protected: 24 static void SetUpTestCase(); 25 static void TearDownTestCase(); 26 27 virtual void SetUp(); 28 virtual void TearDown(); 29 30 void ApplyUninstallCommand(const wchar_t* exe_path, const wchar_t* args); 31 void MinimallyInstallProduct(const wchar_t* version); 32 33 static BrowserDistribution* dist_; 34 static std::wstring temp_key_path_; 35 bool system_install_; 36 HKEY overridden_; 37 RegKey clients_; 38 RegKey client_state_; 39}; 40 41BrowserDistribution* ProductStateTest::dist_; 42std::wstring ProductStateTest::temp_key_path_; 43 44// static 45void ProductStateTest::SetUpTestCase() { 46 testing::Test::SetUpTestCase(); 47 48 // We'll use Chrome as our test subject. 49 dist_ = BrowserDistribution::GetSpecificDistribution( 50 BrowserDistribution::CHROME_BROWSER); 51 52 // And we'll play in HKCU here: 53 temp_key_path_.assign(RegistryOverrideManager::kTempTestKeyPath) 54 .append(1, L'\\') 55 .append(L"ProductStateTest"); 56} 57 58// static 59void ProductStateTest::TearDownTestCase() { 60 temp_key_path_.clear(); 61 dist_ = NULL; 62 63 testing::Test::TearDownTestCase(); 64} 65 66void ProductStateTest::SetUp() { 67 testing::Test::SetUp(); 68 69 // Create/open the keys for the product we'll test. 70 system_install_ = true; 71 overridden_ = (system_install_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER); 72 73 // Override for test purposes. We don't use ScopedRegistryKeyOverride 74 // directly because it doesn't suit itself to our use here. 75 RegKey temp_key; 76 EXPECT_EQ(ERROR_SUCCESS, 77 temp_key.Create(HKEY_CURRENT_USER, temp_key_path_.c_str(), 78 KEY_ALL_ACCESS)); 79 EXPECT_EQ(ERROR_SUCCESS, 80 ::RegOverridePredefKey(overridden_, temp_key.Handle())); 81 82 EXPECT_EQ(ERROR_SUCCESS, 83 clients_.Create(overridden_, dist_->GetVersionKey().c_str(), 84 KEY_ALL_ACCESS)); 85 EXPECT_EQ(ERROR_SUCCESS, 86 client_state_.Create(overridden_, dist_->GetStateKey().c_str(), 87 KEY_ALL_ACCESS)); 88} 89 90void ProductStateTest::TearDown() { 91 // Done with the keys. 92 client_state_.Close(); 93 clients_.Close(); 94 EXPECT_EQ(ERROR_SUCCESS, ::RegOverridePredefKey(overridden_, NULL)); 95 overridden_ = NULL; 96 system_install_ = false; 97 98 // Shotgun approach to clearing out data we may have written. 99 RegistryOverrideManager::DeleteAllTempKeys(); 100 101 testing::Test::TearDown(); 102} 103 104void ProductStateTest::MinimallyInstallProduct(const wchar_t* version) { 105 EXPECT_EQ(ERROR_SUCCESS, 106 clients_.WriteValue(google_update::kRegVersionField, version)); 107} 108 109void ProductStateTest::ApplyUninstallCommand(const wchar_t* exe_path, 110 const wchar_t* args) { 111 if (exe_path == NULL) { 112 LONG result = client_state_.DeleteValue(installer::kUninstallStringField); 113 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 114 } else { 115 EXPECT_EQ(ERROR_SUCCESS, 116 client_state_.WriteValue(installer::kUninstallStringField, 117 exe_path)); 118 } 119 120 if (args == NULL) { 121 LONG result = 122 client_state_.DeleteValue(installer::kUninstallArgumentsField); 123 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 124 } else { 125 EXPECT_EQ(ERROR_SUCCESS, 126 client_state_.WriteValue(installer::kUninstallArgumentsField, 127 args)); 128 } 129} 130 131TEST_F(ProductStateTest, InitializeInstalled) { 132 // Not installed. 133 { 134 ProductState state; 135 LONG result = clients_.DeleteValue(google_update::kRegVersionField); 136 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 137 EXPECT_FALSE(state.Initialize(system_install_, dist_)); 138 } 139 140 // Empty version. 141 { 142 ProductState state; 143 LONG result = clients_.WriteValue(google_update::kRegVersionField, L""); 144 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 145 EXPECT_FALSE(state.Initialize(system_install_, dist_)); 146 } 147 148 // Bogus version. 149 { 150 ProductState state; 151 LONG result = clients_.WriteValue(google_update::kRegVersionField, 152 L"goofy"); 153 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 154 EXPECT_FALSE(state.Initialize(system_install_, dist_)); 155 } 156 157 // Valid "pv" value. 158 { 159 ProductState state; 160 LONG result = clients_.WriteValue(google_update::kRegVersionField, 161 L"10.0.47.0"); 162 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 163 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 164 EXPECT_EQ("10.0.47.0", state.version().GetString()); 165 } 166} 167 168// Test extraction of the "opv" value from the Clients key. 169TEST_F(ProductStateTest, InitializeOldVersion) { 170 MinimallyInstallProduct(L"10.0.1.1"); 171 172 // No "opv" value. 173 { 174 ProductState state; 175 LONG result = clients_.DeleteValue(google_update::kRegOldVersionField); 176 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 177 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 178 EXPECT_TRUE(state.old_version() == NULL); 179 } 180 181 // Empty "opv" value. 182 { 183 ProductState state; 184 LONG result = clients_.WriteValue(google_update::kRegOldVersionField, L""); 185 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 186 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 187 EXPECT_TRUE(state.old_version() == NULL); 188 } 189 190 // Bogus "opv" value. 191 { 192 ProductState state; 193 LONG result = clients_.WriteValue(google_update::kRegOldVersionField, 194 L"coming home"); 195 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 196 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 197 EXPECT_TRUE(state.old_version() == NULL); 198 } 199 200 // Valid "opv" value. 201 { 202 ProductState state; 203 LONG result = clients_.WriteValue(google_update::kRegOldVersionField, 204 L"10.0.47.0"); 205 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 206 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 207 EXPECT_TRUE(state.old_version() != NULL); 208 EXPECT_EQ("10.0.47.0", state.old_version()->GetString()); 209 } 210} 211 212// Test extraction of the "cmd" value from the Clients key. 213TEST_F(ProductStateTest, InitializeRenameCmd) { 214 MinimallyInstallProduct(L"10.0.1.1"); 215 216 // No "cmd" value. 217 { 218 ProductState state; 219 LONG result = clients_.DeleteValue(google_update::kRegRenameCmdField); 220 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 221 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 222 EXPECT_TRUE(state.rename_cmd().empty()); 223 } 224 225 // Empty "cmd" value. 226 { 227 ProductState state; 228 LONG result = clients_.WriteValue(google_update::kRegRenameCmdField, L""); 229 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 230 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 231 EXPECT_TRUE(state.rename_cmd().empty()); 232 } 233 234 // Valid "cmd" value. 235 { 236 ProductState state; 237 LONG result = clients_.WriteValue(google_update::kRegRenameCmdField, 238 L"spam.exe --spamalot"); 239 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 240 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 241 EXPECT_EQ(L"spam.exe --spamalot", state.rename_cmd()); 242 } 243} 244 245// Test extraction of the "ap" value from the ClientState key. 246TEST_F(ProductStateTest, InitializeChannelInfo) { 247 MinimallyInstallProduct(L"10.0.1.1"); 248 249 // No "ap" value. 250 { 251 ProductState state; 252 LONG result = client_state_.DeleteValue(google_update::kRegApField); 253 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 254 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 255 EXPECT_TRUE(state.channel().value().empty()); 256 } 257 258 // Empty "ap" value. 259 { 260 ProductState state; 261 LONG result = client_state_.WriteValue(google_update::kRegApField, L""); 262 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 263 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 264 EXPECT_TRUE(state.channel().value().empty()); 265 } 266 267 // Valid "ap" value. 268 { 269 ProductState state; 270 LONG result = client_state_.WriteValue(google_update::kRegApField, L"spam"); 271 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 272 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 273 EXPECT_EQ(L"spam", state.channel().value()); 274 } 275} 276 277// Test extraction of the uninstall command and arguments from the ClientState 278// key. 279TEST_F(ProductStateTest, InitializeUninstallCommand) { 280 MinimallyInstallProduct(L"10.0.1.1"); 281 282 // No uninstall command. 283 { 284 ProductState state; 285 ApplyUninstallCommand(NULL, NULL); 286 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 287 EXPECT_TRUE(state.GetSetupPath().empty()); 288 EXPECT_TRUE(state.uninstall_command().GetCommandLineString().empty()); 289 EXPECT_TRUE(state.uninstall_command().GetSwitches().empty()); 290 } 291 292 // Empty values. 293 { 294 ProductState state; 295 ApplyUninstallCommand(L"", L""); 296 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 297 EXPECT_TRUE(state.GetSetupPath().empty()); 298 EXPECT_TRUE(state.uninstall_command().GetCommandLineString().empty()); 299 EXPECT_TRUE(state.uninstall_command().GetSwitches().empty()); 300 } 301 302 // Uninstall command without exe. 303 { 304 ProductState state; 305 ApplyUninstallCommand(NULL, L"--uninstall"); 306 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 307 EXPECT_TRUE(state.GetSetupPath().empty()); 308 EXPECT_EQ(L" --uninstall", 309 state.uninstall_command().GetCommandLineString()); 310 EXPECT_EQ(1U, state.uninstall_command().GetSwitches().size()); 311 } 312 313 // Uninstall command without args. 314 { 315 ProductState state; 316 ApplyUninstallCommand(L"setup.exe", NULL); 317 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 318 EXPECT_EQ(L"setup.exe", state.GetSetupPath().value()); 319 EXPECT_EQ(L"setup.exe", state.uninstall_command().GetCommandLineString()); 320 EXPECT_TRUE(state.uninstall_command().GetSwitches().empty()); 321 } 322 323 // Uninstall command with exe that requires quoting. 324 { 325 ProductState state; 326 ApplyUninstallCommand(L"set up.exe", NULL); 327 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 328 EXPECT_EQ(L"set up.exe", state.GetSetupPath().value()); 329 EXPECT_EQ(L"\"set up.exe\"", 330 state.uninstall_command().GetCommandLineString()); 331 EXPECT_TRUE(state.uninstall_command().GetSwitches().empty()); 332 } 333 334 // Uninstall command with both exe and args. 335 { 336 ProductState state; 337 ApplyUninstallCommand(L"setup.exe", L"--uninstall"); 338 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 339 EXPECT_EQ(L"setup.exe", state.GetSetupPath().value()); 340 EXPECT_EQ(L"setup.exe --uninstall", 341 state.uninstall_command().GetCommandLineString()); 342 EXPECT_EQ(1U, state.uninstall_command().GetSwitches().size()); 343 } 344} 345 346// Test extraction of the msi marker from the ClientState key. 347TEST_F(ProductStateTest, InitializeMsi) { 348 MinimallyInstallProduct(L"10.0.1.1"); 349 350 // No msi marker. 351 { 352 ProductState state; 353 LONG result = client_state_.DeleteValue(google_update::kRegMSIField); 354 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); 355 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 356 EXPECT_FALSE(state.is_msi()); 357 } 358 359 // Msi marker set to zero. 360 { 361 ProductState state; 362 EXPECT_EQ(ERROR_SUCCESS, 363 client_state_.WriteValue(google_update::kRegMSIField, 364 static_cast<DWORD>(0))); 365 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 366 EXPECT_FALSE(state.is_msi()); 367 } 368 369 // Msi marker set to one. 370 { 371 ProductState state; 372 EXPECT_EQ(ERROR_SUCCESS, 373 client_state_.WriteValue(google_update::kRegMSIField, 374 static_cast<DWORD>(1))); 375 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 376 EXPECT_TRUE(state.is_msi()); 377 } 378 379 // Msi marker set to a bogus DWORD. 380 { 381 ProductState state; 382 EXPECT_EQ(ERROR_SUCCESS, 383 client_state_.WriteValue(google_update::kRegMSIField, 384 static_cast<DWORD>(47))); 385 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 386 EXPECT_TRUE(state.is_msi()); 387 } 388 389 // Msi marker set to a bogus string. 390 { 391 ProductState state; 392 EXPECT_EQ(ERROR_SUCCESS, 393 client_state_.WriteValue(google_update::kRegMSIField, 394 L"bogus!")); 395 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 396 EXPECT_FALSE(state.is_msi()); 397 } 398} 399 400// Test detection of multi-install. 401TEST_F(ProductStateTest, InitializeMultiInstall) { 402 MinimallyInstallProduct(L"10.0.1.1"); 403 404 // No uninstall command means single install. 405 { 406 ProductState state; 407 ApplyUninstallCommand(NULL, NULL); 408 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 409 EXPECT_FALSE(state.is_multi_install()); 410 } 411 412 // Uninstall command without --multi-install is single install. 413 { 414 ProductState state; 415 ApplyUninstallCommand(L"setup.exe", L"--uninstall"); 416 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 417 EXPECT_FALSE(state.is_multi_install()); 418 } 419 420 // Uninstall command with --multi-install is multi install. 421 { 422 ProductState state; 423 ApplyUninstallCommand(L"setup.exe", 424 L"--uninstall --chrome --multi-install"); 425 EXPECT_TRUE(state.Initialize(system_install_, dist_)); 426 EXPECT_TRUE(state.is_multi_install()); 427 } 428} 429