Home | History | Annotate | Download | only in util
      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