install_util_unittest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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
19using base::win::RegKey;
20using registry_util::RegistryOverrideManager;
21using ::testing::_;
22using ::testing::Return;
23using ::testing::StrEq;
24
25class MockRegistryValuePredicate : public InstallUtil::RegistryValuePredicate {
26 public:
27  MOCK_CONST_METHOD1(Evaluate, bool(const std::wstring&));
28};
29
30class InstallUtilTest : public TestWithTempDirAndDeleteTempOverrideKeys {
31 protected:
32};
33
34TEST_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
58TEST_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
77TEST_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
127TEST_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
178TEST_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
288TEST_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
401TEST_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
411TEST_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