Home | History | Annotate | Download | only in util
      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 
     18 using base::win::RegKey;
     19 using installer::ProductState;
     20 using registry_util::RegistryOverrideManager;
     21 
     22 class 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 
     41 BrowserDistribution* ProductStateTest::dist_;
     42 std::wstring ProductStateTest::temp_key_path_;
     43 
     44 // static
     45 void 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
     59 void ProductStateTest::TearDownTestCase() {
     60   temp_key_path_.clear();
     61   dist_ = NULL;
     62 
     63   testing::Test::TearDownTestCase();
     64 }
     65 
     66 void 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 
     90 void 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 
    104 void ProductStateTest::MinimallyInstallProduct(const wchar_t* version) {
    105   EXPECT_EQ(ERROR_SUCCESS,
    106             clients_.WriteValue(google_update::kRegVersionField, version));
    107 }
    108 
    109 void 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 
    131 TEST_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.
    169 TEST_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.
    213 TEST_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.
    246 TEST_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.
    279 TEST_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.
    347 TEST_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.
    401 TEST_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