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