install_util_unittest.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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
18using base::win::RegKey;
19using registry_util::RegistryOverrideManager;
20using ::testing::_;
21using ::testing::Return;
22using ::testing::StrEq;
23
24class MockRegistryValuePredicate : public InstallUtil::RegistryValuePredicate {
25 public:
26  MOCK_CONST_METHOD1(Evaluate, bool(const std::wstring&));
27};
28
29class InstallUtilTest : public TestWithTempDirAndDeleteTempOverrideKeys {
30 protected:
31};
32
33TEST_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
57TEST_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
76TEST_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
126TEST_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
177TEST_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
281TEST_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
388TEST_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
398TEST_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(file_util::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