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