product_state_unittest.cc revision f2477e01787aa58f445919b809d89e252beef54f
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
18using base::win::RegKey;
19using installer::ProductState;
20using registry_util::RegistryOverrideManager;
21
22class 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  bool system_install_;
35  HKEY overridden_;
36  registry_util::RegistryOverrideManager registry_override_manager_;
37  RegKey clients_;
38  RegKey client_state_;
39};
40
41BrowserDistribution* ProductStateTest::dist_;
42
43// static
44void ProductStateTest::SetUpTestCase() {
45  testing::Test::SetUpTestCase();
46
47  // We'll use Chrome as our test subject.
48  dist_ = BrowserDistribution::GetSpecificDistribution(
49      BrowserDistribution::CHROME_BROWSER);
50}
51
52// static
53void ProductStateTest::TearDownTestCase() {
54  dist_ = NULL;
55
56  testing::Test::TearDownTestCase();
57}
58
59void ProductStateTest::SetUp() {
60  testing::Test::SetUp();
61
62  // Create/open the keys for the product we'll test.
63  system_install_ = true;
64  overridden_ = (system_install_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER);
65
66  // Override for test purposes.  We don't use ScopedRegistryKeyOverride
67  // directly because it doesn't suit itself to our use here.
68  RegKey temp_key;
69
70  registry_override_manager_.OverrideRegistry(overridden_, L"ProductStateTest");
71
72  EXPECT_EQ(ERROR_SUCCESS,
73            clients_.Create(overridden_, dist_->GetVersionKey().c_str(),
74                            KEY_ALL_ACCESS));
75  EXPECT_EQ(ERROR_SUCCESS,
76            client_state_.Create(overridden_, dist_->GetStateKey().c_str(),
77                                 KEY_ALL_ACCESS));
78}
79
80void ProductStateTest::TearDown() {
81  // Done with the keys.
82  client_state_.Close();
83  clients_.Close();
84  overridden_ = NULL;
85  system_install_ = false;
86
87  testing::Test::TearDown();
88}
89
90void ProductStateTest::MinimallyInstallProduct(const wchar_t* version) {
91  EXPECT_EQ(ERROR_SUCCESS,
92            clients_.WriteValue(google_update::kRegVersionField, version));
93}
94
95void ProductStateTest::ApplyUninstallCommand(const wchar_t* exe_path,
96                                             const wchar_t* args) {
97  if (exe_path == NULL) {
98    LONG result = client_state_.DeleteValue(installer::kUninstallStringField);
99    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
100  } else {
101    EXPECT_EQ(ERROR_SUCCESS,
102              client_state_.WriteValue(installer::kUninstallStringField,
103                                       exe_path));
104  }
105
106  if (args == NULL) {
107    LONG result =
108        client_state_.DeleteValue(installer::kUninstallArgumentsField);
109    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
110  } else {
111    EXPECT_EQ(ERROR_SUCCESS,
112              client_state_.WriteValue(installer::kUninstallArgumentsField,
113                                       args));
114  }
115}
116
117TEST_F(ProductStateTest, InitializeInstalled) {
118  // Not installed.
119  {
120    ProductState state;
121    LONG result = clients_.DeleteValue(google_update::kRegVersionField);
122    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
123    EXPECT_FALSE(state.Initialize(system_install_, dist_));
124  }
125
126  // Empty version.
127  {
128    ProductState state;
129    LONG result = clients_.WriteValue(google_update::kRegVersionField, L"");
130    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
131    EXPECT_FALSE(state.Initialize(system_install_, dist_));
132  }
133
134  // Bogus version.
135  {
136    ProductState state;
137    LONG result = clients_.WriteValue(google_update::kRegVersionField,
138                                      L"goofy");
139    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
140    EXPECT_FALSE(state.Initialize(system_install_, dist_));
141  }
142
143  // Valid "pv" value.
144  {
145    ProductState state;
146    LONG result = clients_.WriteValue(google_update::kRegVersionField,
147                                      L"10.0.47.0");
148    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
149    EXPECT_TRUE(state.Initialize(system_install_, dist_));
150    EXPECT_EQ("10.0.47.0", state.version().GetString());
151  }
152}
153
154// Test extraction of the "opv" value from the Clients key.
155TEST_F(ProductStateTest, InitializeOldVersion) {
156  MinimallyInstallProduct(L"10.0.1.1");
157
158  // No "opv" value.
159  {
160    ProductState state;
161    LONG result = clients_.DeleteValue(google_update::kRegOldVersionField);
162    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
163    EXPECT_TRUE(state.Initialize(system_install_, dist_));
164    EXPECT_TRUE(state.old_version() == NULL);
165  }
166
167  // Empty "opv" value.
168  {
169    ProductState state;
170    LONG result = clients_.WriteValue(google_update::kRegOldVersionField, L"");
171    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
172    EXPECT_TRUE(state.Initialize(system_install_, dist_));
173    EXPECT_TRUE(state.old_version() == NULL);
174  }
175
176  // Bogus "opv" value.
177  {
178    ProductState state;
179    LONG result = clients_.WriteValue(google_update::kRegOldVersionField,
180                                      L"coming home");
181    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
182    EXPECT_TRUE(state.Initialize(system_install_, dist_));
183    EXPECT_TRUE(state.old_version() == NULL);
184  }
185
186  // Valid "opv" value.
187  {
188    ProductState state;
189    LONG result = clients_.WriteValue(google_update::kRegOldVersionField,
190                                      L"10.0.47.0");
191    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
192    EXPECT_TRUE(state.Initialize(system_install_, dist_));
193    EXPECT_TRUE(state.old_version() != NULL);
194    EXPECT_EQ("10.0.47.0", state.old_version()->GetString());
195  }
196}
197
198// Test extraction of the "cmd" value from the Clients key.
199TEST_F(ProductStateTest, InitializeRenameCmd) {
200  MinimallyInstallProduct(L"10.0.1.1");
201
202  // No "cmd" value.
203  {
204    ProductState state;
205    LONG result = clients_.DeleteValue(google_update::kRegRenameCmdField);
206    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
207    EXPECT_TRUE(state.Initialize(system_install_, dist_));
208    EXPECT_TRUE(state.rename_cmd().empty());
209  }
210
211  // Empty "cmd" value.
212  {
213    ProductState state;
214    LONG result = clients_.WriteValue(google_update::kRegRenameCmdField, L"");
215    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
216    EXPECT_TRUE(state.Initialize(system_install_, dist_));
217    EXPECT_TRUE(state.rename_cmd().empty());
218  }
219
220  // Valid "cmd" value.
221  {
222    ProductState state;
223    LONG result = clients_.WriteValue(google_update::kRegRenameCmdField,
224                                      L"spam.exe --spamalot");
225    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
226    EXPECT_TRUE(state.Initialize(system_install_, dist_));
227    EXPECT_EQ(L"spam.exe --spamalot", state.rename_cmd());
228  }
229}
230
231// Test extraction of the "ap" value from the ClientState key.
232TEST_F(ProductStateTest, InitializeChannelInfo) {
233  MinimallyInstallProduct(L"10.0.1.1");
234
235  // No "ap" value.
236  {
237    ProductState state;
238    LONG result = client_state_.DeleteValue(google_update::kRegApField);
239    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
240    EXPECT_TRUE(state.Initialize(system_install_, dist_));
241    EXPECT_TRUE(state.channel().value().empty());
242  }
243
244  // Empty "ap" value.
245  {
246    ProductState state;
247    LONG result = client_state_.WriteValue(google_update::kRegApField, L"");
248    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
249    EXPECT_TRUE(state.Initialize(system_install_, dist_));
250    EXPECT_TRUE(state.channel().value().empty());
251  }
252
253  // Valid "ap" value.
254  {
255    ProductState state;
256    LONG result = client_state_.WriteValue(google_update::kRegApField, L"spam");
257    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
258    EXPECT_TRUE(state.Initialize(system_install_, dist_));
259    EXPECT_EQ(L"spam", state.channel().value());
260  }
261}
262
263// Test extraction of the uninstall command and arguments from the ClientState
264// key.
265TEST_F(ProductStateTest, InitializeUninstallCommand) {
266  MinimallyInstallProduct(L"10.0.1.1");
267
268  // No uninstall command.
269  {
270    ProductState state;
271    ApplyUninstallCommand(NULL, NULL);
272    EXPECT_TRUE(state.Initialize(system_install_, dist_));
273    EXPECT_TRUE(state.GetSetupPath().empty());
274    EXPECT_TRUE(state.uninstall_command().GetCommandLineString().empty());
275    EXPECT_TRUE(state.uninstall_command().GetSwitches().empty());
276  }
277
278  // Empty values.
279  {
280    ProductState state;
281    ApplyUninstallCommand(L"", L"");
282    EXPECT_TRUE(state.Initialize(system_install_, dist_));
283    EXPECT_TRUE(state.GetSetupPath().empty());
284    EXPECT_TRUE(state.uninstall_command().GetCommandLineString().empty());
285    EXPECT_TRUE(state.uninstall_command().GetSwitches().empty());
286  }
287
288  // Uninstall command without exe.
289  {
290    ProductState state;
291    ApplyUninstallCommand(NULL, L"--uninstall");
292    EXPECT_TRUE(state.Initialize(system_install_, dist_));
293    EXPECT_TRUE(state.GetSetupPath().empty());
294    EXPECT_EQ(L" --uninstall",
295              state.uninstall_command().GetCommandLineString());
296    EXPECT_EQ(1U, state.uninstall_command().GetSwitches().size());
297  }
298
299  // Uninstall command without args.
300  {
301    ProductState state;
302    ApplyUninstallCommand(L"setup.exe", NULL);
303    EXPECT_TRUE(state.Initialize(system_install_, dist_));
304    EXPECT_EQ(L"setup.exe", state.GetSetupPath().value());
305    EXPECT_EQ(L"setup.exe", state.uninstall_command().GetCommandLineString());
306    EXPECT_TRUE(state.uninstall_command().GetSwitches().empty());
307  }
308
309  // Uninstall command with exe that requires quoting.
310  {
311    ProductState state;
312    ApplyUninstallCommand(L"set up.exe", NULL);
313    EXPECT_TRUE(state.Initialize(system_install_, dist_));
314    EXPECT_EQ(L"set up.exe", state.GetSetupPath().value());
315    EXPECT_EQ(L"\"set up.exe\"",
316              state.uninstall_command().GetCommandLineString());
317    EXPECT_TRUE(state.uninstall_command().GetSwitches().empty());
318  }
319
320  // Uninstall command with both exe and args.
321  {
322    ProductState state;
323    ApplyUninstallCommand(L"setup.exe", L"--uninstall");
324    EXPECT_TRUE(state.Initialize(system_install_, dist_));
325    EXPECT_EQ(L"setup.exe", state.GetSetupPath().value());
326    EXPECT_EQ(L"setup.exe --uninstall",
327              state.uninstall_command().GetCommandLineString());
328    EXPECT_EQ(1U, state.uninstall_command().GetSwitches().size());
329  }
330}
331
332// Test extraction of the msi marker from the ClientState key.
333TEST_F(ProductStateTest, InitializeMsi) {
334  MinimallyInstallProduct(L"10.0.1.1");
335
336  // No msi marker.
337  {
338    ProductState state;
339    LONG result = client_state_.DeleteValue(google_update::kRegMSIField);
340    EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
341    EXPECT_TRUE(state.Initialize(system_install_, dist_));
342    EXPECT_FALSE(state.is_msi());
343  }
344
345  // Msi marker set to zero.
346  {
347    ProductState state;
348    EXPECT_EQ(ERROR_SUCCESS,
349              client_state_.WriteValue(google_update::kRegMSIField,
350                                       static_cast<DWORD>(0)));
351    EXPECT_TRUE(state.Initialize(system_install_, dist_));
352    EXPECT_FALSE(state.is_msi());
353  }
354
355  // Msi marker set to one.
356  {
357    ProductState state;
358    EXPECT_EQ(ERROR_SUCCESS,
359              client_state_.WriteValue(google_update::kRegMSIField,
360                                       static_cast<DWORD>(1)));
361    EXPECT_TRUE(state.Initialize(system_install_, dist_));
362    EXPECT_TRUE(state.is_msi());
363  }
364
365  // Msi marker set to a bogus DWORD.
366  {
367    ProductState state;
368    EXPECT_EQ(ERROR_SUCCESS,
369              client_state_.WriteValue(google_update::kRegMSIField,
370                                       static_cast<DWORD>(47)));
371    EXPECT_TRUE(state.Initialize(system_install_, dist_));
372    EXPECT_TRUE(state.is_msi());
373  }
374
375  // Msi marker set to a bogus string.
376  {
377    ProductState state;
378    EXPECT_EQ(ERROR_SUCCESS,
379              client_state_.WriteValue(google_update::kRegMSIField,
380                                       L"bogus!"));
381    EXPECT_TRUE(state.Initialize(system_install_, dist_));
382    EXPECT_FALSE(state.is_msi());
383  }
384}
385
386// Test detection of multi-install.
387TEST_F(ProductStateTest, InitializeMultiInstall) {
388  MinimallyInstallProduct(L"10.0.1.1");
389
390  // No uninstall command means single install.
391  {
392    ProductState state;
393    ApplyUninstallCommand(NULL, NULL);
394    EXPECT_TRUE(state.Initialize(system_install_, dist_));
395    EXPECT_FALSE(state.is_multi_install());
396  }
397
398  // Uninstall command without --multi-install is single install.
399  {
400    ProductState state;
401    ApplyUninstallCommand(L"setup.exe", L"--uninstall");
402    EXPECT_TRUE(state.Initialize(system_install_, dist_));
403    EXPECT_FALSE(state.is_multi_install());
404  }
405
406  // Uninstall command with --multi-install is multi install.
407  {
408    ProductState state;
409    ApplyUninstallCommand(L"setup.exe",
410                          L"--uninstall --chrome --multi-install");
411    EXPECT_TRUE(state.Initialize(system_install_, dist_));
412    EXPECT_TRUE(state.is_multi_install());
413  }
414}
415