OLD | NEW |
| (Empty) |
1 // Copyright 2007-2010 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 #include <atlpath.h> | |
17 #include <atlstr.h> | |
18 #include "base/scoped_ptr.h" | |
19 #include "omaha/base/app_util.h" | |
20 #include "omaha/base/error.h" | |
21 #include "omaha/base/file.h" | |
22 #include "omaha/base/path.h" | |
23 #include "omaha/base/reg_key.h" | |
24 #include "omaha/base/scoped_ptr_address.h" | |
25 #include "omaha/base/shell.h" | |
26 #include "omaha/base/synchronized.h" | |
27 #include "omaha/base/system.h" | |
28 #include "omaha/base/timer.h" | |
29 #include "omaha/base/utils.h" | |
30 #include "omaha/base/vistautil.h" | |
31 #include "omaha/common/const_goopdate.h" | |
32 #include "omaha/common/goopdate_utils.h" | |
33 #include "omaha/common/install_manifest.h" | |
34 #include "omaha/common/ping_event.h" | |
35 #include "omaha/goopdate/app_bundle_state_initialized.h" | |
36 #include "omaha/goopdate/app_state_waiting_to_install.h" | |
37 #include "omaha/goopdate/app_unittest_base.h" | |
38 #include "omaha/goopdate/installer_wrapper.h" | |
39 #include "omaha/goopdate/install_manager.h" | |
40 #include "omaha/testing/unit_test.h" | |
41 | |
42 using ::testing::_; | |
43 using ::testing::Return; | |
44 | |
45 namespace omaha { | |
46 | |
47 // TODO(omaha): there is a problem with this unit test. The model is built | |
48 // bottom up. This makes it impossible to set the references to parents. Will | |
49 // have to fix the code, eventually using Builder DP to create a bunch of | |
50 // models containing bundles, apps, and such. | |
51 | |
52 namespace { | |
53 | |
54 const TCHAR kAppId[] = _T("{B18BC01B-E0BD-4BF0-A33E-1133055E5FDE}"); | |
55 const GUID kAppGuid = {0xB18BC01B, 0xE0BD, 0x4BF0, | |
56 {0xA3, 0x3E, 0x11, 0x33, 0x05, 0x5E, 0x5F, 0xDE}}; | |
57 const TCHAR kApp2Id[] = _T("{85794B39-42E5-457c-B567-4A0F2A0FB272}"); | |
58 | |
59 const TCHAR kFullAppClientsKeyPath[] = | |
60 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
61 _T("\\Clients\\{B18BC01B-E0BD-4BF0-A33E-1133055E5FDE}"); | |
62 const TCHAR kFullAppClientStateKeyPath[] = | |
63 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
64 _T("\\ClientState\\{B18BC01B-E0BD-4BF0-A33E-1133055E5FDE}"); | |
65 const TCHAR kFullFooAppClientKeyPath[] = | |
66 _T("HKLM\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
67 _T("\\Clients\\{D6B08267-B440-4C85-9F79-E195E80D9937}"); | |
68 const TCHAR kFullFooAppClientStateKeyPath[] = | |
69 _T("HKLM\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
70 _T("\\ClientState\\{D6B08267-B440-4C85-9F79-E195E80D9937}"); | |
71 | |
72 const TCHAR kFullApp2ClientsKeyPath[] = | |
73 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
74 _T("\\Clients\\{85794B39-42E5-457c-B567-4A0F2A0FB272}"); | |
75 | |
76 const TCHAR kSetupFooV1RelativeLocation[] = | |
77 _T("unittest_support\\test_foo_v1.0.101.0.msi"); | |
78 const TCHAR kFooId[] = _T("{D6B08267-B440-4C85-9F79-E195E80D9937}"); | |
79 const TCHAR kFooVersion[] = _T("1.0.101.0"); | |
80 const TCHAR kFooInstallerBarPropertyArg[] = _T("PROPBAR=7"); | |
81 const TCHAR kFooInstallerBarValueName[] = _T("propbar"); | |
82 | |
83 // Values related to using cmd.exe as an "installer". | |
84 const TCHAR kCmdExecutable[] = _T("cmd.exe"); | |
85 const TCHAR kExecuteCommandAndTerminateSwitch[] = _T("/c %s"); | |
86 const TCHAR kExecuteTwoCommandsFormat[] = _T("\"%s & %s\""); | |
87 | |
88 const TCHAR kMsiInstallerBusyErrorMessage[] = | |
89 _T("Installation failed because the Windows Installer is busy. Please ") | |
90 _T("wait for any installers to finish, close all installer windows, and ") | |
91 _T("try installing again. If this problem persists, you may need ") | |
92 _T("to reboot your computer."); | |
93 | |
94 const TCHAR kMsiLogFormat[] = _T("%s.log"); | |
95 | |
96 // brand, InstallTime, and LastCheckSuccess are automatically populated. | |
97 const int kNumAutoPopulatedValues = 3; | |
98 | |
99 } // namespace | |
100 | |
101 // Values and functions in installer_wrapper_unittest.cc. | |
102 extern const TCHAR kRegExecutable[]; | |
103 extern const TCHAR kSetInstallerResultTypeMsiErrorRegCmdArgs[]; | |
104 extern const TCHAR kMsiInstallerBusyExitCodeCmd[]; | |
105 extern const TCHAR kError1619MessagePrefix[]; | |
106 extern const int kError1619MessagePrefixLength; | |
107 void VerifyStringIsMsiPackageOpenFailedString(const CString& str); | |
108 void UninstallTestMsi(const CString& installer_path); | |
109 void AdjustMsiTries(InstallerWrapper* installer_wrapper); | |
110 | |
111 // TODO(omaha3): Test the rest of InstallManager. | |
112 class InstallManagerTest : public testing::Test { | |
113 virtual void SetUp() {} | |
114 virtual void TearDown() {} | |
115 }; | |
116 | |
117 class InstallManagerInstallAppTest : public AppTestBaseWithRegistryOverride { | |
118 protected: | |
119 explicit InstallManagerInstallAppTest(bool is_machine) | |
120 : AppTestBaseWithRegistryOverride(is_machine, false) {} | |
121 | |
122 static void SetUpTestCase() { | |
123 CString system_path; | |
124 EXPECT_SUCCEEDED(Shell::GetSpecialFolder(CSIDL_SYSTEM, | |
125 false, | |
126 &system_path)); | |
127 EXPECT_FALSE(system_path.IsEmpty()); | |
128 cmd_exe_dir_ += system_path; | |
129 | |
130 CPath cmd_exe_path; | |
131 cmd_exe_path.Combine(system_path, kCmdExecutable); | |
132 EXPECT_TRUE(File::Exists(cmd_exe_path)); | |
133 | |
134 CPath reg_path; | |
135 reg_path.Combine(system_path, kRegExecutable); | |
136 set_installer_result_type_msi_error_cmd_.Format( | |
137 _T("%s %s"), | |
138 reg_path, kSetInstallerResultTypeMsiErrorRegCmdArgs); | |
139 } | |
140 | |
141 virtual void SetUp() { | |
142 AppTestBaseWithRegistryOverride::SetUp(); | |
143 | |
144 installer_wrapper_.reset(new InstallerWrapper(is_machine_)); | |
145 EXPECT_SUCCEEDED(installer_wrapper_->Initialize()); | |
146 | |
147 ASSERT_SUCCEEDED(app_bundle_->createApp(CComBSTR(kAppId), &app_)); | |
148 | |
149 SetAppStateWaitingToInstall(app_); | |
150 } | |
151 | |
152 HRESULT InstallApp(const CString& existing_version, | |
153 App* app, | |
154 const CString& dir) { | |
155 ASSERT1(app); | |
156 return InstallManager::InstallApp(is_machine_, | |
157 NULL, | |
158 existing_version, | |
159 app->model()->lock(), | |
160 installer_wrapper_.get(), | |
161 app, | |
162 dir); | |
163 } | |
164 | |
165 void SetArgumentsInManifest(const CString& arguments, | |
166 const CString& expected_version, | |
167 App* app) { | |
168 ASSERT1(app); | |
169 | |
170 // TODO(omaha3): Consider using a mock object. | |
171 xml::InstallManifest* install_manifest = new xml::InstallManifest; | |
172 install_manifest->version = expected_version; | |
173 | |
174 xml::InstallAction install_event_action; | |
175 install_event_action.install_event = xml::InstallAction::kInstall; | |
176 install_event_action.needs_admin = is_machine_ ? NEEDS_ADMIN_YES : | |
177 NEEDS_ADMIN_NO; | |
178 // TODO(omaha3): Set install_event_action.program_to_run? | |
179 install_event_action.program_arguments = arguments; | |
180 | |
181 install_manifest->install_actions.push_back(install_event_action); | |
182 app->next_version()->set_install_manifest(install_manifest); | |
183 } | |
184 | |
185 void SetPostInstallActionInManifest(SuccessfulInstallAction success_action, | |
186 const CString& success_url, | |
187 bool terminate_all_browsers, | |
188 App* app) { | |
189 xml::InstallManifest* install_manifest = new xml::InstallManifest; | |
190 install_manifest->version = _T("1.2.3.4"); | |
191 | |
192 xml::InstallAction post_install_event_action; | |
193 post_install_event_action.install_event = xml::InstallAction::kPostInstall; | |
194 post_install_event_action.needs_admin = is_machine_ ? NEEDS_ADMIN_YES : | |
195 NEEDS_ADMIN_NO; | |
196 post_install_event_action.success_url = success_url; | |
197 post_install_event_action.terminate_all_browsers = terminate_all_browsers; | |
198 post_install_event_action.success_action = success_action; | |
199 install_manifest->install_actions.push_back(post_install_event_action); | |
200 app->next_version()->set_install_manifest(install_manifest); | |
201 } | |
202 | |
203 static void SetAppStateWaitingToInstall(App* app) { | |
204 SetAppStateForUnitTest(app, new fsm::AppStateWaitingToInstall); | |
205 } | |
206 | |
207 static HRESULT GetResultCode(const App* app) { | |
208 return app->error_context_.error_code; | |
209 } | |
210 | |
211 static CString GetCompletionMessage(const App* app) { | |
212 return app->completion_message_; | |
213 } | |
214 | |
215 static PingEvent::Results GetCompletionResult(const App* app) { | |
216 return app->completion_result_; | |
217 } | |
218 | |
219 static CString GetPostInstallLaunchCommandLine(const App* app) { | |
220 return app->post_install_launch_command_line_; | |
221 } | |
222 | |
223 static CString GetPostInstallUrl(const App* app) { | |
224 return app->post_install_url_; | |
225 } | |
226 | |
227 static PostInstallAction GetPostInstallAction(const App* app) { | |
228 return app->post_install_action_; | |
229 } | |
230 | |
231 static void PopulateSuccessfulInstallResultInfo( | |
232 const App* app, InstallerResultInfo* result_info) { | |
233 return InstallManager::PopulateSuccessfulInstallResultInfo( | |
234 app, result_info); | |
235 } | |
236 | |
237 scoped_ptr<InstallerWrapper> installer_wrapper_; | |
238 | |
239 App* app_; | |
240 | |
241 static CPath cmd_exe_dir_; | |
242 static CString set_installer_result_type_msi_error_cmd_; | |
243 }; | |
244 | |
245 CPath InstallManagerInstallAppTest::cmd_exe_dir_; | |
246 CString InstallManagerInstallAppTest::set_installer_result_type_msi_error_cmd_; | |
247 | |
248 class InstallManagerInstallAppMachineTest | |
249 : public InstallManagerInstallAppTest { | |
250 protected: | |
251 InstallManagerInstallAppMachineTest() | |
252 : InstallManagerInstallAppTest(true) { | |
253 } | |
254 }; | |
255 | |
256 class InstallManagerInstallAppUserTest : public InstallManagerInstallAppTest { | |
257 protected: | |
258 InstallManagerInstallAppUserTest() | |
259 : InstallManagerInstallAppTest(false) { | |
260 } | |
261 }; | |
262 | |
263 // | |
264 // Helper method tests | |
265 // | |
266 | |
267 // TODO(omaha3): We may replace these with the tests from | |
268 // installer_wrapper_unittest.cc if CheckApplicationRegistration() is moved to | |
269 // InstallManager. | |
270 #if 0 | |
271 TEST_F(InstallManagerInstallAppUserTest, | |
272 CheckApplicationRegistration_FailsWhenClientsKeyAbsent) { | |
273 AppData app_data(kAppGuid, is_machine_); | |
274 Job job(false, &ping_); | |
275 job.set_app_data(app_data); | |
276 | |
277 EXPECT_EQ(GOOPDATEINSTALL_E_INSTALLER_DID_NOT_WRITE_CLIENTS_KEY, | |
278 CheckApplicationRegistration(CString(), &job)); | |
279 | |
280 EXPECT_FALSE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
281 EXPECT_FALSE(RegKey::HasKey(kFullAppClientStateKeyPath)); | |
282 } | |
283 | |
284 TEST_F(InstallManagerInstallAppUserTest, | |
285 CheckApplicationRegistration_FailsWhenVersionValueAbsent) { | |
286 ASSERT_SUCCEEDED(RegKey::CreateKey(kFullAppClientsKeyPath)); | |
287 | |
288 AppData app_data(kAppGuid, is_machine_); | |
289 Job job(false, &ping_); | |
290 job.set_app_data(app_data); | |
291 | |
292 EXPECT_EQ(GOOPDATEINSTALL_E_INSTALLER_DID_NOT_WRITE_CLIENTS_KEY, | |
293 CheckApplicationRegistration(CString(), &job)); | |
294 | |
295 EXPECT_TRUE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
296 EXPECT_FALSE(RegKey::HasKey(kFullAppClientStateKeyPath)); | |
297 } | |
298 | |
299 TEST_F(InstallManagerInstallAppUserTest, | |
300 CheckApplicationRegistration_SucceedsWhenStateKeyAbsent) { | |
301 ASSERT_SUCCEEDED(RegKey::SetValue(kFullAppClientsKeyPath, | |
302 kRegValueProductVersion, | |
303 _T("0.9.68.4"))); | |
304 | |
305 AppData app_data(kAppGuid, is_machine_); | |
306 Job job(false, &ping_); | |
307 job.set_app_data(app_data); | |
308 | |
309 EXPECT_SUCCEEDED(CheckApplicationRegistration(CString(), &job)); | |
310 } | |
311 | |
312 TEST_F(InstallManagerInstallAppUserTest, | |
313 CheckApplicationRegistration_SucceedsWhenStateKeyPresent) { | |
314 const TCHAR* keys_to_create[] = {kFullAppClientsKeyPath, | |
315 kFullAppClientStateKeyPath}; | |
316 ASSERT_SUCCEEDED(RegKey::CreateKeys(keys_to_create, 2)); | |
317 ASSERT_TRUE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
318 ASSERT_TRUE(RegKey::HasKey(kFullAppClientStateKeyPath)); | |
319 ASSERT_SUCCEEDED(RegKey::SetValue(kFullAppClientsKeyPath, | |
320 kRegValueProductVersion, | |
321 _T("0.9.70.0"))); | |
322 | |
323 AppData app_data(kAppGuid, is_machine_); | |
324 Job job(false, &ping_); | |
325 job.set_app_data(app_data); | |
326 | |
327 // The install should succeed even if the version is the same. | |
328 EXPECT_SUCCEEDED(CheckApplicationRegistration(_T("0.9.70.0"), &job)); | |
329 } | |
330 | |
331 TEST_F(InstallManagerInstallAppUserTest, | |
332 CheckApplicationRegistration_UpdateSucceeds) { | |
333 const TCHAR* keys_to_create[] = {kFullAppClientsKeyPath, | |
334 kFullAppClientStateKeyPath}; | |
335 ASSERT_SUCCEEDED(RegKey::CreateKeys(keys_to_create, 2)); | |
336 ASSERT_TRUE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
337 ASSERT_TRUE(RegKey::HasKey(kFullAppClientStateKeyPath)); | |
338 ASSERT_SUCCEEDED(RegKey::SetValue(kFullAppClientsKeyPath, | |
339 kRegValueProductVersion, | |
340 _T("0.9.70.0"))); | |
341 | |
342 AppData app_data(kAppGuid, is_machine_); | |
343 Job job(true, &ping_); | |
344 job.set_app_data(app_data); | |
345 | |
346 EXPECT_SUCCEEDED(CheckApplicationRegistration(_T("0.9.70.1"), &job)); | |
347 } | |
348 | |
349 TEST_F(InstallManagerInstallAppUserTest, | |
350 CheckApplicationRegistration_UpdateFailsWhenVersionDoesNotChange) { | |
351 const TCHAR* keys_to_create[] = {kFullAppClientsKeyPath, | |
352 kFullAppClientStateKeyPath}; | |
353 ASSERT_SUCCEEDED(RegKey::CreateKeys(keys_to_create, | |
354 arraysize(keys_to_create))); | |
355 ASSERT_TRUE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
356 ASSERT_TRUE(RegKey::HasKey(kFullAppClientStateKeyPath)); | |
357 ASSERT_SUCCEEDED(RegKey::SetValue(kFullAppClientsKeyPath, | |
358 kRegValueProductVersion, | |
359 _T("0.9.70.0"))); | |
360 | |
361 AppData app_data(kAppGuid, is_machine_); | |
362 Job job(true, &ping_); | |
363 job.set_app_data(app_data); | |
364 | |
365 EXPECT_EQ(GOOPDATEINSTALL_E_INSTALLER_DID_NOT_CHANGE_VERSION, | |
366 CheckApplicationRegistration(_T("0.9.70.0"), &job)); | |
367 } | |
368 #endif | |
369 | |
370 // | |
371 // Negative Tests | |
372 // | |
373 | |
374 TEST_F(InstallManagerInstallAppUserTest, | |
375 InstallApp_InstallerWithoutFilenameExtension) { | |
376 app_->next_version()->AddPackage(_T("foo"), 100, _T("hash")); | |
377 | |
378 // TODO(omaha): We should be able to eliminate this. | |
379 SetArgumentsInManifest(CString(), _T("1.2.3.4"), app_); | |
380 | |
381 EXPECT_EQ(GOOPDATEINSTALL_E_FILENAME_INVALID, | |
382 InstallApp(_T(""), app_, _T("c:\\temp"))); | |
383 | |
384 EXPECT_EQ(STATE_ERROR, app_->state()); | |
385 EXPECT_EQ(PingEvent::EVENT_RESULT_ERROR, GetCompletionResult(app_)); | |
386 EXPECT_EQ(GOOPDATEINSTALL_E_FILENAME_INVALID, GetResultCode(app_)); | |
387 EXPECT_STREQ( | |
388 _T("The installer filename c:\\temp\\foo is invalid or unsupported."), | |
389 GetCompletionMessage(app_)); | |
390 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
391 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
392 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
393 } | |
394 | |
395 TEST_F(InstallManagerInstallAppUserTest, | |
396 InstallApp_UnsupportedInstallerFilenameExtension) { | |
397 app_->next_version()->AddPackage(_T("foo.bar"), 100, _T("hash")); | |
398 | |
399 // TODO(omaha): We should be able to eliminate this. | |
400 SetArgumentsInManifest(CString(), _T("1.2.3.4"), app_); | |
401 | |
402 EXPECT_EQ(GOOPDATEINSTALL_E_FILENAME_INVALID, | |
403 InstallApp(_T(""), app_, _T("c:\\temp"))); | |
404 | |
405 EXPECT_EQ(STATE_ERROR, app_->state()); | |
406 EXPECT_EQ(PingEvent::EVENT_RESULT_ERROR, GetCompletionResult(app_)); | |
407 EXPECT_EQ(GOOPDATEINSTALL_E_FILENAME_INVALID, GetResultCode(app_)); | |
408 EXPECT_STREQ( | |
409 _T("The installer filename c:\\temp\\foo.bar is invalid or unsupported."), | |
410 GetCompletionMessage(app_)); | |
411 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
412 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
413 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
414 } | |
415 | |
416 TEST_F(InstallManagerInstallAppUserTest, InstallApp_InstallerEmtpyFilename) { | |
417 // Package asserts that the filename and file path are not NULL. | |
418 ExpectAsserts expect_asserts; | |
419 | |
420 app_->next_version()->AddPackage(_T(""), 100, _T("hash")); | |
421 // This test does not call | |
422 // app_->next_version()->GetPackage(0)->set_local_file_path(). | |
423 | |
424 // TODO(omaha): We should be able to eliminate this. | |
425 SetArgumentsInManifest(CString(), _T("1.2.3.4"), app_); | |
426 | |
427 EXPECT_EQ(GOOPDATEINSTALL_E_FILENAME_INVALID, | |
428 InstallApp(_T(""), app_, NULL)); | |
429 | |
430 EXPECT_EQ(STATE_ERROR, app_->state()); | |
431 EXPECT_EQ(PingEvent::EVENT_RESULT_ERROR, GetCompletionResult(app_)); | |
432 EXPECT_EQ(GOOPDATEINSTALL_E_FILENAME_INVALID, GetResultCode(app_)); | |
433 EXPECT_STREQ(_T("The installer filename \\ is invalid or unsupported."), | |
434 GetCompletionMessage(app_)); | |
435 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
436 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
437 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
438 } | |
439 | |
440 TEST_F(InstallManagerInstallAppUserTest, InstallApp_NoPackage) { | |
441 // InstallApp asserts that there is at least one package. | |
442 ExpectAsserts expect_asserts; | |
443 | |
444 EXPECT_EQ(E_FAIL, InstallApp(_T(""), app_, NULL)); | |
445 | |
446 EXPECT_EQ(STATE_ERROR, app_->state()); | |
447 EXPECT_EQ(PingEvent::EVENT_RESULT_ERROR, GetCompletionResult(app_)); | |
448 EXPECT_EQ(E_FAIL, GetResultCode(app_)); | |
449 EXPECT_STREQ( | |
450 _T("Installation failed. Please try again."), | |
451 GetCompletionMessage(app_)); | |
452 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
453 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
454 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
455 } | |
456 | |
457 TEST_F(InstallManagerInstallAppUserTest, InstallApp_ExeFileDoesNotExist) { | |
458 app_->next_version()->AddPackage(_T("foo.exe"), 100, _T("hash")); | |
459 | |
460 // TODO(omaha): We should be able to eliminate this. | |
461 SetArgumentsInManifest(CString(), _T("1.2.3.4"), app_); | |
462 | |
463 EXPECT_EQ(GOOPDATEINSTALL_E_INSTALLER_FAILED_START, | |
464 InstallApp(_T(""), app_, _T("c:\\temp"))); | |
465 | |
466 EXPECT_EQ(STATE_ERROR, app_->state()); | |
467 EXPECT_EQ(PingEvent::EVENT_RESULT_ERROR, GetCompletionResult(app_)); | |
468 EXPECT_EQ(GOOPDATEINSTALL_E_INSTALLER_FAILED_START, GetResultCode(app_)); | |
469 EXPECT_STREQ(_T("The installer failed to start."), | |
470 GetCompletionMessage(app_)); | |
471 | |
472 EXPECT_FALSE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
473 EXPECT_FALSE(RegKey::HasKey(kFullAppClientStateKeyPath)); | |
474 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
475 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
476 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
477 } | |
478 | |
479 // | |
480 // EXE Installer Tests | |
481 // | |
482 | |
483 // TODO(omaha3): Add InstallApp_ExeInstallerWithoutArgumentsSucceeds using | |
484 // SaveArguments.exe. Do the same in InstallerWrapperUserTest. | |
485 | |
486 // TODO(omaha3): Add InstallApp tests that cause | |
487 // ReadInstallerRegistrationValues & CheckApplicationRegistration to fail. | |
488 | |
489 // This test uses cmd.exe as an installer that leaves the payload | |
490 // kPayloadFileName. | |
491 TEST_F(InstallManagerInstallAppUserTest, | |
492 InstallApp_ExeInstallerWithArgumentsSucceeds) { | |
493 const TCHAR kPayloadFileName[] = _T("exe_payload.txt"); | |
494 const TCHAR kCommandToExecute[] = _T("echo \"hi\" > %s"); | |
495 | |
496 CString full_command_to_execute; | |
497 full_command_to_execute.Format(kCommandToExecute, kPayloadFileName); | |
498 CString arguments; | |
499 arguments.Format(kExecuteCommandAndTerminateSwitch, full_command_to_execute); | |
500 | |
501 EXPECT_SUCCEEDED(File::Remove(kPayloadFileName)); | |
502 EXPECT_FALSE(File::Exists(kPayloadFileName)); | |
503 | |
504 // Create the Clients key since this isn't an actual installer. | |
505 EXPECT_SUCCEEDED(RegKey::CreateKey(kFullAppClientsKeyPath)); | |
506 EXPECT_TRUE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
507 EXPECT_SUCCEEDED(RegKey::SetValue(kFullAppClientsKeyPath, | |
508 kRegValueProductVersion, | |
509 _T("0.10.69.5"))); | |
510 | |
511 app_->next_version()->AddPackage(kCmdExecutable, 100, _T("hash")); | |
512 EXPECT_SUCCEEDED(app_->put_displayName(CComBSTR(_T("Exe App")))); | |
513 | |
514 SetArgumentsInManifest(arguments, _T("0.10.69.5"), app_); | |
515 | |
516 EXPECT_SUCCEEDED(InstallApp(_T(""), app_, cmd_exe_dir_)); | |
517 | |
518 EXPECT_EQ(STATE_INSTALL_COMPLETE, app_->state()); | |
519 EXPECT_EQ(PingEvent::EVENT_RESULT_SUCCESS, GetCompletionResult(app_)); | |
520 EXPECT_EQ(S_OK, GetResultCode(app_)); | |
521 EXPECT_STREQ(_T("Thanks for installing."), GetCompletionMessage(app_)); | |
522 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
523 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
524 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
525 | |
526 RegKey state_key; | |
527 EXPECT_SUCCEEDED(state_key.Open(kFullAppClientStateKeyPath)); | |
528 EXPECT_EQ(1 + kNumAutoPopulatedValues, state_key.GetValueCount()); | |
529 EXPECT_STREQ(_T("0.10.69.5"), GetSzValue(kFullAppClientStateKeyPath, | |
530 kRegValueProductVersion)); | |
531 | |
532 EXPECT_TRUE(File::Exists(kPayloadFileName)); | |
533 EXPECT_SUCCEEDED(File::Remove(kPayloadFileName)); | |
534 } | |
535 | |
536 TEST_F(InstallManagerInstallAppUserTest, | |
537 InstallApp_ExeInstallerReturnsNonZeroExitCode) { | |
538 const TCHAR kCommandToExecute[] = _T("exit 1"); | |
539 | |
540 CString arguments; | |
541 arguments.Format(kExecuteCommandAndTerminateSwitch, kCommandToExecute); | |
542 | |
543 // Create the Clients key since this isn't an actual installer. | |
544 ASSERT_SUCCEEDED(RegKey::CreateKey(kFullAppClientsKeyPath)); | |
545 ASSERT_TRUE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
546 ASSERT_SUCCEEDED(RegKey::SetValue(kFullAppClientsKeyPath, | |
547 kRegValueProductVersion, | |
548 _T("0.10.69.5"))); | |
549 | |
550 app_->next_version()->AddPackage(kCmdExecutable, 100, _T("hash")); | |
551 | |
552 SetArgumentsInManifest(arguments, _T("0.10.69.5"), app_); | |
553 | |
554 EXPECT_EQ(GOOPDATEINSTALL_E_INSTALLER_FAILED, | |
555 InstallApp(_T(""), app_, cmd_exe_dir_)); | |
556 | |
557 EXPECT_EQ(STATE_ERROR, app_->state()); | |
558 EXPECT_EQ(PingEvent::EVENT_RESULT_INSTALLER_ERROR_OTHER, | |
559 GetCompletionResult(app_)); | |
560 EXPECT_EQ(GOOPDATEINSTALL_E_INSTALLER_FAILED, GetResultCode(app_)); | |
561 EXPECT_STREQ(_T("The installer encountered error 1."), | |
562 GetCompletionMessage(app_)); | |
563 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
564 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
565 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
566 } | |
567 | |
568 TEST_F(InstallManagerInstallAppMachineTest, InstallApp_MsiInstallerSucceeds) { | |
569 if (!vista_util::IsUserAdmin()) { | |
570 std::wcout << _T("\tTest did not run because the user is not an admin.") | |
571 << std::endl; | |
572 return; | |
573 } | |
574 | |
575 const CString kIid = _T("{F7598FEE-4BA9-4755-A1FC-6EB0A6F3D126}"); | |
576 | |
577 // We can't fake the registry keys because we are interacting with a real | |
578 // installer. | |
579 RestoreRegistryHives(); | |
580 | |
581 AdjustMsiTries(installer_wrapper_.get()); | |
582 | |
583 CString installer_dir(app_util::GetCurrentModuleDirectory()); | |
584 | |
585 CString installer_full_path( | |
586 ConcatenatePath(installer_dir, kSetupFooV1RelativeLocation)); | |
587 ASSERT_TRUE(File::Exists(installer_full_path)); | |
588 | |
589 CString installer_log_full_path; | |
590 installer_log_full_path.Format(kMsiLogFormat, installer_full_path); | |
591 | |
592 ASSERT_SUCCEEDED(File::Remove(installer_log_full_path)); | |
593 ASSERT_FALSE(File::Exists(installer_log_full_path)); | |
594 | |
595 RegKey::DeleteKey(kFullFooAppClientKeyPath); | |
596 ASSERT_FALSE(RegKey::HasKey(kFullFooAppClientKeyPath)); | |
597 RegKey::DeleteKey(kFullFooAppClientStateKeyPath); | |
598 ASSERT_FALSE(RegKey::HasKey(kFullFooAppClientStateKeyPath)); | |
599 | |
600 // Accepting the EULA prevents "eulaaccepted" value from being written. | |
601 EXPECT_SUCCEEDED(app_->put_isEulaAccepted(VARIANT_TRUE)); | |
602 | |
603 // TODO(omaha): This should be just a filename. | |
604 app_->next_version()->AddPackage(kSetupFooV1RelativeLocation, | |
605 100, _T("hash")); | |
606 app_->set_app_guid(StringToGuid(kFooId)); | |
607 EXPECT_SUCCEEDED(app_->put_displayName(CComBSTR(_T("Foo")))); | |
608 EXPECT_SUCCEEDED(app_->put_iid(CComBSTR(kIid))); | |
609 | |
610 // TODO(omaha): We should be able to eliminate this. | |
611 SetArgumentsInManifest(CString(), kFooVersion, app_); | |
612 | |
613 EXPECT_SUCCEEDED(InstallApp(_T(""), app_, installer_dir)); | |
614 | |
615 EXPECT_EQ(STATE_INSTALL_COMPLETE, app_->state()); | |
616 EXPECT_EQ(PingEvent::EVENT_RESULT_SUCCESS, GetCompletionResult(app_)); | |
617 EXPECT_EQ(S_OK, GetResultCode(app_)); | |
618 EXPECT_STREQ(_T("Thanks for installing."), | |
619 GetCompletionMessage(app_)); | |
620 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
621 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
622 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
623 | |
624 EXPECT_TRUE(File::Exists(installer_log_full_path)); | |
625 | |
626 EXPECT_TRUE(RegKey::HasKey(kFullFooAppClientKeyPath)); | |
627 EXPECT_TRUE(RegKey::HasKey(kFullFooAppClientStateKeyPath)); | |
628 RegKey state_key; | |
629 EXPECT_SUCCEEDED(state_key.Open(kFullFooAppClientStateKeyPath)); | |
630 EXPECT_EQ(2 + kNumAutoPopulatedValues, state_key.GetValueCount()); | |
631 EXPECT_STREQ(kFooVersion, GetSzValue(kFullFooAppClientStateKeyPath, | |
632 kRegValueProductVersion)); | |
633 EXPECT_FALSE(RegKey::HasValue(kFullFooAppClientStateKeyPath, | |
634 kRegValueLanguage)); | |
635 EXPECT_STREQ(kIid, GetSzValue(kFullFooAppClientStateKeyPath, | |
636 kRegValueInstallationId)); | |
637 | |
638 // Verify the installer did not write a value that is to be written only in | |
639 // the presence of an MSI property that was not specified. | |
640 EXPECT_FALSE(RegKey::HasValue(kFullFooAppClientKeyPath, | |
641 kFooInstallerBarValueName)); | |
642 | |
643 UninstallTestMsi(installer_full_path); | |
644 | |
645 EXPECT_FALSE(RegKey::HasKey(kFullFooAppClientKeyPath)); | |
646 EXPECT_SUCCEEDED(RegKey::DeleteKey(kFullFooAppClientKeyPath)); | |
647 } | |
648 | |
649 TEST_F(InstallManagerInstallAppMachineTest, | |
650 InstallApp_MsiInstallerWithArgumentSucceeds) { | |
651 if (!vista_util::IsUserAdmin()) { | |
652 std::wcout << _T("\tTest did not run because the user is not an admin.") | |
653 << std::endl; | |
654 return; | |
655 } | |
656 | |
657 // We can't fake the registry keys because we are interacting with a real | |
658 // installer. | |
659 RestoreRegistryHives(); | |
660 | |
661 AdjustMsiTries(installer_wrapper_.get()); | |
662 | |
663 CString installer_dir(app_util::GetCurrentModuleDirectory()); | |
664 | |
665 CString installer_full_path( | |
666 ConcatenatePath(installer_dir, kSetupFooV1RelativeLocation)); | |
667 ASSERT_TRUE(File::Exists(installer_full_path)); | |
668 | |
669 CString installer_log_full_path; | |
670 installer_log_full_path.Format(kMsiLogFormat, installer_full_path); | |
671 | |
672 ASSERT_SUCCEEDED(File::Remove(installer_log_full_path)); | |
673 ASSERT_FALSE(File::Exists(installer_log_full_path)); | |
674 | |
675 RegKey::DeleteKey(kFullFooAppClientKeyPath); | |
676 ASSERT_FALSE(RegKey::HasKey(kFullFooAppClientKeyPath)); | |
677 RegKey::DeleteKey(kFullFooAppClientStateKeyPath); | |
678 ASSERT_FALSE(RegKey::HasKey(kFullFooAppClientStateKeyPath)); | |
679 | |
680 // Write an iid to verify it gets deleted below. | |
681 EXPECT_SUCCEEDED( | |
682 RegKey::SetValue(kFullFooAppClientStateKeyPath, | |
683 kRegValueInstallationId, | |
684 _T("{A30B6C0A-B491-473e-9D24-E1AC1BC1D42F}"))); | |
685 | |
686 // Accepting the EULA prevents "eulaaccepted" value from being written. | |
687 EXPECT_SUCCEEDED(app_->put_isEulaAccepted(VARIANT_TRUE)); | |
688 | |
689 // TODO(omaha): This should be just a filename. | |
690 app_->next_version()->AddPackage(kSetupFooV1RelativeLocation, | |
691 100, _T("hash")); | |
692 app_->set_app_guid(StringToGuid(kFooId)); | |
693 EXPECT_SUCCEEDED(app_->put_displayName(CComBSTR(_T("Foo")))); | |
694 | |
695 SetArgumentsInManifest(kFooInstallerBarPropertyArg, kFooVersion, app_); | |
696 | |
697 EXPECT_SUCCEEDED(InstallApp(_T(""), app_, installer_dir)); | |
698 | |
699 EXPECT_EQ(STATE_INSTALL_COMPLETE, app_->state()); | |
700 EXPECT_EQ(PingEvent::EVENT_RESULT_SUCCESS, GetCompletionResult(app_)); | |
701 EXPECT_EQ(S_OK, GetResultCode(app_)); | |
702 EXPECT_STREQ(_T("Thanks for installing."), | |
703 GetCompletionMessage(app_)); | |
704 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
705 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
706 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
707 | |
708 EXPECT_TRUE(File::Exists(installer_log_full_path)); | |
709 | |
710 EXPECT_TRUE(RegKey::HasKey(kFullFooAppClientKeyPath)); | |
711 EXPECT_TRUE(RegKey::HasKey(kFullFooAppClientStateKeyPath)); | |
712 RegKey state_key; | |
713 EXPECT_SUCCEEDED(state_key.Open(kFullFooAppClientStateKeyPath)); | |
714 EXPECT_EQ(1 + kNumAutoPopulatedValues, state_key.GetValueCount()); | |
715 EXPECT_STREQ(kFooVersion, GetSzValue(kFullFooAppClientStateKeyPath, | |
716 kRegValueProductVersion)); | |
717 EXPECT_FALSE(RegKey::HasValue(kFullFooAppClientStateKeyPath, | |
718 kRegValueLanguage)); | |
719 EXPECT_FALSE(RegKey::HasValue(kFullFooAppClientStateKeyPath, | |
720 kRegValueInstallationId)); | |
721 | |
722 EXPECT_TRUE(RegKey::HasValue(kFullFooAppClientKeyPath, | |
723 kFooInstallerBarValueName)); | |
724 DWORD barprop_value; | |
725 EXPECT_SUCCEEDED(RegKey::GetValue(kFullFooAppClientKeyPath, | |
726 kFooInstallerBarValueName, | |
727 &barprop_value)); | |
728 EXPECT_EQ(7, barprop_value); | |
729 | |
730 UninstallTestMsi(installer_full_path); | |
731 | |
732 EXPECT_FALSE(RegKey::HasKey(kFullFooAppClientKeyPath)); | |
733 EXPECT_SUCCEEDED(RegKey::DeleteKey(kFullFooAppClientKeyPath)); | |
734 } | |
735 | |
736 // The use of kGoogleUpdateAppId is the key to this test. | |
737 // Note that the version is not changed - this is the normal self-update case. | |
738 // Among other things, this test verifies that CheckApplicationRegistration() is | |
739 // not called for self-updates. | |
740 TEST_F(InstallManagerInstallAppUserTest, InstallApp_UpdateOmahaSucceeds) { | |
741 CString arguments; | |
742 arguments.Format(kExecuteCommandAndTerminateSwitch, _T("")); | |
743 | |
744 const CString kExistingVersion(_T("0.9.69.5")); | |
745 | |
746 app_->next_version()->AddPackage(kCmdExecutable, 100, _T("hash")); | |
747 app_->set_app_guid(StringToGuid(kGoogleUpdateAppId)); | |
748 | |
749 // TODO(omaha3): This isn't supported yet. | |
750 #if 0 | |
751 isupdate = true | |
752 #endif | |
753 | |
754 SetArgumentsInManifest(arguments, _T("1.2.9.8"), app_); | |
755 | |
756 // Because we don't actually run the Omaha installer, we need to make sure | |
757 // its Clients key and pv value exist to avoid an error. | |
758 ASSERT_SUCCEEDED(RegKey::CreateKey(USER_REG_CLIENTS_GOOPDATE)); | |
759 ASSERT_TRUE(RegKey::HasKey(USER_REG_CLIENTS_GOOPDATE)); | |
760 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
761 kRegValueProductVersion, | |
762 kExistingVersion)); | |
763 | |
764 EXPECT_SUCCEEDED(InstallApp(kExistingVersion, app_, cmd_exe_dir_)); | |
765 | |
766 EXPECT_EQ(STATE_INSTALL_COMPLETE, app_->state()); | |
767 EXPECT_EQ(PingEvent::EVENT_RESULT_SUCCESS, GetCompletionResult(app_)); | |
768 EXPECT_EQ(S_OK, GetResultCode(app_)); | |
769 EXPECT_STREQ(_T("Thanks for installing."), GetCompletionMessage(app_)); | |
770 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
771 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
772 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
773 | |
774 EXPECT_TRUE(RegKey::HasKey(USER_REG_CLIENTS_GOOPDATE)); | |
775 CString version; | |
776 EXPECT_SUCCEEDED(RegKey::GetValue(USER_REG_CLIENTS_GOOPDATE, | |
777 kRegValueProductVersion, | |
778 &version)); | |
779 EXPECT_STREQ(kExistingVersion, version); | |
780 } | |
781 | |
782 // The main purpose of this test is to ensure that self-updates don't fail if | |
783 // Omaha's Clients key doesn't exist for some reason. | |
784 // In other words, it tests that CheckApplicationRegistration() is not called. | |
785 TEST_F(InstallManagerInstallAppUserTest, | |
786 InstallApp_UpdateOmahaSucceedsWhenClientsKeyAbsent) { | |
787 CString arguments; | |
788 arguments.Format(kExecuteCommandAndTerminateSwitch, _T("")); | |
789 | |
790 const CString kExistingVersion(_T("0.9.69.5")); | |
791 | |
792 app_->next_version()->AddPackage(kCmdExecutable, 100, _T("hash")); | |
793 app_->set_app_guid(StringToGuid(kGoogleUpdateAppId)); | |
794 | |
795 // TODO(omaha3): This isn't supported yet. | |
796 #if 0 | |
797 isupdate = true | |
798 #endif | |
799 | |
800 SetArgumentsInManifest(arguments, _T("1.2.9.8"), app_); | |
801 | |
802 EXPECT_SUCCEEDED(InstallApp(kExistingVersion, app_, cmd_exe_dir_)); | |
803 | |
804 EXPECT_EQ(STATE_INSTALL_COMPLETE, app_->state()); | |
805 EXPECT_EQ(PingEvent::EVENT_RESULT_SUCCESS, GetCompletionResult(app_)); | |
806 EXPECT_EQ(S_OK, GetResultCode(app_)); | |
807 EXPECT_STREQ(_T("Thanks for installing."), GetCompletionMessage(app_)); | |
808 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
809 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
810 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
811 | |
812 EXPECT_FALSE(RegKey::HasKey(USER_REG_CLIENTS_GOOPDATE)); | |
813 } | |
814 | |
815 TEST_F(InstallManagerInstallAppUserTest, | |
816 InstallApp_InstallerDoesNotWriteClientsKey) { | |
817 CString arguments; | |
818 arguments.Format(kExecuteCommandAndTerminateSwitch, _T("")); | |
819 | |
820 app_->next_version()->AddPackage(kCmdExecutable, 100, _T("hash")); | |
821 EXPECT_SUCCEEDED(app_->put_displayName(CComBSTR(_T("Some App")))); | |
822 | |
823 SetArgumentsInManifest(arguments, _T("5.6.7.8"), app_); | |
824 | |
825 EXPECT_EQ(GOOPDATEINSTALL_E_INSTALLER_DID_NOT_WRITE_CLIENTS_KEY, | |
826 InstallApp(_T(""), app_, cmd_exe_dir_)); | |
827 | |
828 EXPECT_FALSE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
829 EXPECT_FALSE(RegKey::HasKey(kFullAppClientStateKeyPath)); | |
830 | |
831 EXPECT_EQ(STATE_ERROR, app_->state()); | |
832 EXPECT_EQ(PingEvent::EVENT_RESULT_ERROR, GetCompletionResult(app_)); | |
833 EXPECT_EQ(GOOPDATEINSTALL_E_INSTALLER_DID_NOT_WRITE_CLIENTS_KEY, | |
834 GetResultCode(app_)); | |
835 EXPECT_STREQ( | |
836 _T("Installation failed. Please try again."), | |
837 GetCompletionMessage(app_)); | |
838 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
839 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
840 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
841 } | |
842 | |
843 // TODO(omaha3): Test for GOOPDATEINSTALL_E_INSTALLER_DID_NOT_CHANGE_VERSION | |
844 // once is_update is supported. | |
845 | |
846 TEST_F(InstallManagerInstallAppUserTest, | |
847 InstallApp_InstallerFailureMsiFileDoesNotExist) { | |
848 CPath msi_dir(app_util::GetTempDir()); | |
849 CPath msi_path(msi_dir); | |
850 msi_path.Append(_T("foo.msi")); | |
851 const CString log_path = msi_path + _T(".log"); | |
852 | |
853 AdjustMsiTries(installer_wrapper_.get()); | |
854 | |
855 ASSERT_SUCCEEDED(File::Remove(log_path)); | |
856 ASSERT_FALSE(File::Exists(log_path)); | |
857 | |
858 app_->next_version()->AddPackage(_T("foo.msi"), 100, _T("hash")); | |
859 | |
860 // TODO(omaha): We should be able to eliminate this. | |
861 SetArgumentsInManifest(CString(), _T("1.2.3.4"), app_); | |
862 | |
863 EXPECT_EQ(GOOPDATEINSTALL_E_INSTALLER_FAILED, | |
864 InstallApp(_T(""), app_, msi_dir)); | |
865 | |
866 EXPECT_EQ(STATE_ERROR, app_->state()); | |
867 EXPECT_EQ(PingEvent::EVENT_RESULT_INSTALLER_ERROR_MSI, | |
868 GetCompletionResult(app_)); | |
869 EXPECT_EQ(GOOPDATEINSTALL_E_INSTALLER_FAILED, GetResultCode(app_)); | |
870 const CString message = GetCompletionMessage(app_); | |
871 EXPECT_STREQ(kError1619MessagePrefix, | |
872 message.Left(kError1619MessagePrefixLength)); | |
873 VerifyStringIsMsiPackageOpenFailedString( | |
874 message.Mid(kError1619MessagePrefixLength)); | |
875 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
876 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
877 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
878 | |
879 // msiexec creates an empty log file. | |
880 EXPECT_TRUE(File::Exists(log_path)); | |
881 EXPECT_SUCCEEDED(File::Remove(log_path)); | |
882 | |
883 EXPECT_FALSE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
884 EXPECT_FALSE(RegKey::HasKey(kFullAppClientStateKeyPath)); | |
885 } | |
886 | |
887 // Simulates the MSI busy error by having an exe installer return the error | |
888 // as its exit code and specifying MSI error using Installer Result API. | |
889 // Assumes reg.exe is in the path. | |
890 // This works because the number of retries is set before InstallApp() and thus | |
891 // defaults to 1 in the InstallerWrapper. | |
892 TEST_F(InstallManagerInstallAppUserTest, InstallApp_MsiIsBusy_NoRetries) { | |
893 CString commands; | |
894 commands.Format(kExecuteTwoCommandsFormat, | |
895 set_installer_result_type_msi_error_cmd_, | |
896 kMsiInstallerBusyExitCodeCmd); | |
897 | |
898 CString arguments; | |
899 arguments.Format(kExecuteCommandAndTerminateSwitch, commands); | |
900 | |
901 app_->next_version()->AddPackage(kCmdExecutable, 100, _T("hash")); | |
902 EXPECT_SUCCEEDED(app_->put_displayName(CComBSTR(_T("Some App")))); | |
903 | |
904 SetArgumentsInManifest(arguments, _T("1.2.3.4"), app_); | |
905 | |
906 LowResTimer install_timer(true); | |
907 | |
908 EXPECT_EQ(GOOPDATEINSTALL_E_MSI_INSTALL_ALREADY_RUNNING, | |
909 InstallApp(_T(""), app_, cmd_exe_dir_)); | |
910 | |
911 EXPECT_GT(2, install_timer.GetSeconds()); // Check Omaha did not retry. | |
912 | |
913 EXPECT_EQ(STATE_ERROR, app_->state()); | |
914 // Even though the error came from the installer, the error type is not | |
915 // set because we have a custom error for this case. | |
916 EXPECT_EQ(PingEvent::EVENT_RESULT_ERROR, GetCompletionResult(app_)); | |
917 EXPECT_EQ(GOOPDATEINSTALL_E_MSI_INSTALL_ALREADY_RUNNING, | |
918 GetResultCode(app_)); | |
919 EXPECT_STREQ(kMsiInstallerBusyErrorMessage, GetCompletionMessage(app_)); | |
920 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
921 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
922 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
923 } | |
924 | |
925 // This test uses cmd.exe as an installer that leaves the payload files. | |
926 TEST_F(InstallManagerInstallAppUserTest, InstallApp_InstallMultipleApps) { | |
927 const TCHAR kPayloadFileName1[] = _T("exe_payload1.txt"); | |
928 const TCHAR kPayloadFileName2[] = _T("exe_payload2.txt"); | |
929 const TCHAR kCommandToExecute[] = _T("echo \"hi\" > %s"); | |
930 | |
931 CString full_command_to_execute; | |
932 full_command_to_execute.Format(kCommandToExecute, kPayloadFileName1); | |
933 CString arguments1; | |
934 arguments1.Format(kExecuteCommandAndTerminateSwitch, full_command_to_execute); | |
935 | |
936 full_command_to_execute.Format(kCommandToExecute, kPayloadFileName2); | |
937 CString arguments2; | |
938 arguments2.Format(kExecuteCommandAndTerminateSwitch, full_command_to_execute); | |
939 | |
940 EXPECT_SUCCEEDED(File::Remove(kPayloadFileName1)); | |
941 EXPECT_FALSE(File::Exists(kPayloadFileName1)); | |
942 EXPECT_SUCCEEDED(File::Remove(kPayloadFileName2)); | |
943 EXPECT_FALSE(File::Exists(kPayloadFileName2)); | |
944 | |
945 // Create the Clients key since this isn't an actual installer. | |
946 EXPECT_SUCCEEDED(RegKey::CreateKey(kFullAppClientsKeyPath)); | |
947 EXPECT_TRUE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
948 EXPECT_SUCCEEDED(RegKey::SetValue(kFullAppClientsKeyPath, | |
949 kRegValueProductVersion, | |
950 _T("0.10.69.5"))); | |
951 | |
952 app_->next_version()->AddPackage(kCmdExecutable, 100, _T("hash")); | |
953 EXPECT_SUCCEEDED(app_->put_displayName(CComBSTR(_T("Exe App")))); | |
954 | |
955 SetArgumentsInManifest(arguments1, _T("0.10.69.5"), app_); | |
956 | |
957 EXPECT_SUCCEEDED(InstallApp(_T(""), app_, cmd_exe_dir_)); | |
958 | |
959 EXPECT_EQ(STATE_INSTALL_COMPLETE, app_->state()); | |
960 EXPECT_EQ(PingEvent::EVENT_RESULT_SUCCESS, GetCompletionResult(app_)); | |
961 EXPECT_EQ(S_OK, GetResultCode(app_)); | |
962 EXPECT_STREQ(_T("Thanks for installing."), GetCompletionMessage(app_)); | |
963 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
964 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
965 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
966 | |
967 EXPECT_TRUE(File::Exists(kPayloadFileName1)); | |
968 EXPECT_SUCCEEDED(File::Remove(kPayloadFileName1)); | |
969 | |
970 // Run the second installer. | |
971 | |
972 App* app2 = NULL; | |
973 ASSERT_SUCCEEDED(app_bundle_->createApp(CComBSTR(kApp2Id), &app2)); | |
974 SetAppStateWaitingToInstall(app2); | |
975 | |
976 // Create the Clients key since this isn't an actual installer. | |
977 EXPECT_SUCCEEDED(RegKey::CreateKey(kFullAppClientsKeyPath)); | |
978 EXPECT_TRUE(RegKey::HasKey(kFullAppClientsKeyPath)); | |
979 EXPECT_SUCCEEDED(RegKey::SetValue(kFullApp2ClientsKeyPath, | |
980 kRegValueProductVersion, | |
981 _T("0.10.69.5"))); | |
982 | |
983 app2->next_version()->AddPackage(kCmdExecutable, 100, _T("hash")); | |
984 EXPECT_SUCCEEDED(app2->put_displayName(CComBSTR(_T("Exe App")))); | |
985 | |
986 SetArgumentsInManifest(arguments2, _T("0.10.69.5"), app2); | |
987 | |
988 EXPECT_SUCCEEDED(InstallApp(_T(""), app2, cmd_exe_dir_)); | |
989 | |
990 EXPECT_EQ(STATE_INSTALL_COMPLETE, app2->state()); | |
991 EXPECT_EQ(PingEvent::EVENT_RESULT_SUCCESS, GetCompletionResult(app2)); | |
992 EXPECT_EQ(S_OK, GetResultCode(app2)); | |
993 EXPECT_STREQ(_T("Thanks for installing."), GetCompletionMessage(app2)); | |
994 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
995 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
996 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, GetPostInstallAction(app_)); | |
997 | |
998 EXPECT_TRUE(File::Exists(kPayloadFileName2)); | |
999 EXPECT_SUCCEEDED(File::Remove(kPayloadFileName2)); | |
1000 } | |
1001 | |
1002 TEST_F(InstallManagerInstallAppUserTest, | |
1003 PopulateSuccessfulInstallResultInfo_ExitSilentlyOnLaunchCommandWithNoComm
and) { // NOLINT | |
1004 SetPostInstallActionInManifest(SUCCESS_ACTION_EXIT_SILENTLY_ON_LAUNCH_CMD, | |
1005 _T(""), | |
1006 false, | |
1007 app_); | |
1008 | |
1009 InstallerResultInfo result_info; | |
1010 result_info.type = INSTALLER_RESULT_SUCCESS; | |
1011 PopulateSuccessfulInstallResultInfo(app_, &result_info); | |
1012 EXPECT_TRUE(GetPostInstallLaunchCommandLine(app_).IsEmpty()); | |
1013 EXPECT_TRUE(GetPostInstallUrl(app_).IsEmpty()); | |
1014 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, result_info.post_install_action); | |
1015 } | |
1016 | |
1017 // Verify that launch command is converted to silently launch command | |
1018 // if success action is silently launch command. Also tests that launch cmd | |
1019 // takes precedence over URL. | |
1020 TEST_F(InstallManagerInstallAppUserTest, | |
1021 PopulateSuccessfulInstallResultInfo_ExitSilentlyOnLaunchCommand) { | |
1022 SetPostInstallActionInManifest(SUCCESS_ACTION_EXIT_SILENTLY_ON_LAUNCH_CMD, | |
1023 _T("http://post_install_succeeded"), | |
1024 true, | |
1025 app_); | |
1026 | |
1027 InstallerResultInfo result_info; | |
1028 result_info.type = INSTALLER_RESULT_SUCCESS; | |
1029 result_info.post_install_action = POST_INSTALL_ACTION_LAUNCH_COMMAND; | |
1030 result_info.post_install_launch_command_line = _T("notepad.exe"); | |
1031 PopulateSuccessfulInstallResultInfo(app_, &result_info); | |
1032 | |
1033 EXPECT_EQ(POST_INSTALL_ACTION_EXIT_SILENTLY_ON_LAUNCH_COMMAND, | |
1034 result_info.post_install_action); | |
1035 } | |
1036 | |
1037 TEST_F(InstallManagerInstallAppUserTest, | |
1038 PopulateSuccessfulInstallResultInfo_LaunchCommandWithDefaultSuccessAction) { | |
1039 SetPostInstallActionInManifest(SUCCESS_ACTION_DEFAULT, | |
1040 _T(""), | |
1041 true, | |
1042 app_); | |
1043 | |
1044 InstallerResultInfo result_info; | |
1045 result_info.type = INSTALLER_RESULT_SUCCESS; | |
1046 result_info.post_install_action = POST_INSTALL_ACTION_LAUNCH_COMMAND; | |
1047 result_info.post_install_launch_command_line = _T("notepad.exe"); | |
1048 PopulateSuccessfulInstallResultInfo(app_, &result_info); | |
1049 | |
1050 EXPECT_EQ(POST_INSTALL_ACTION_LAUNCH_COMMAND, | |
1051 result_info.post_install_action); | |
1052 } | |
1053 | |
1054 // Verify that default install action is converted to exit silently if | |
1055 // if success action is exit silently. | |
1056 TEST_F(InstallManagerInstallAppUserTest, | |
1057 PopulateSuccessfulInstallResultInfo_ExitSilently) { | |
1058 SetPostInstallActionInManifest(SUCCESS_ACTION_EXIT_SILENTLY, | |
1059 _T(""), | |
1060 false, | |
1061 app_); | |
1062 | |
1063 InstallerResultInfo result_info; | |
1064 result_info.type = INSTALLER_RESULT_SUCCESS; | |
1065 result_info.post_install_action = POST_INSTALL_ACTION_DEFAULT; | |
1066 PopulateSuccessfulInstallResultInfo(app_, &result_info); | |
1067 | |
1068 EXPECT_EQ(POST_INSTALL_ACTION_EXIT_SILENTLY, result_info.post_install_action); | |
1069 } | |
1070 | |
1071 TEST_F(InstallManagerInstallAppUserTest, | |
1072 PopulateSuccessfulInstallResultInfo_RestartBrowser) { | |
1073 SetPostInstallActionInManifest(SUCCESS_ACTION_DEFAULT, | |
1074 _T("http://www.google.com/foo/installed_ok"), | |
1075 false, | |
1076 app_); | |
1077 | |
1078 InstallerResultInfo result_info; | |
1079 result_info.type = INSTALLER_RESULT_SUCCESS; | |
1080 result_info.post_install_action = POST_INSTALL_ACTION_DEFAULT; | |
1081 PopulateSuccessfulInstallResultInfo(app_, &result_info); | |
1082 | |
1083 EXPECT_EQ(POST_INSTALL_ACTION_RESTART_BROWSER, | |
1084 result_info.post_install_action); | |
1085 } | |
1086 | |
1087 TEST_F(InstallManagerInstallAppUserTest, | |
1088 PopulateSuccessfulInstallResultInfo_RestartAllBrowsers) { | |
1089 SetPostInstallActionInManifest(SUCCESS_ACTION_DEFAULT, | |
1090 _T("http://www.google.com/gears/installed_ok"), | |
1091 true, | |
1092 app_); | |
1093 | |
1094 InstallerResultInfo result_info; | |
1095 result_info.type = INSTALLER_RESULT_SUCCESS; | |
1096 result_info.post_install_action = POST_INSTALL_ACTION_DEFAULT; | |
1097 PopulateSuccessfulInstallResultInfo(app_, &result_info); | |
1098 | |
1099 EXPECT_EQ(POST_INSTALL_ACTION_RESTART_ALL_BROWSERS, | |
1100 result_info.post_install_action); | |
1101 } | |
1102 | |
1103 TEST_F(InstallManagerInstallAppUserTest, | |
1104 PopulateSuccessfulInstallResultInfo_NoPostInstallUrl) { | |
1105 SetPostInstallActionInManifest(SUCCESS_ACTION_DEFAULT, | |
1106 _T(""), | |
1107 true, | |
1108 app_); | |
1109 | |
1110 InstallerResultInfo result_info; | |
1111 result_info.type = INSTALLER_RESULT_SUCCESS; | |
1112 result_info.post_install_action = POST_INSTALL_ACTION_DEFAULT; | |
1113 PopulateSuccessfulInstallResultInfo(app_, &result_info); | |
1114 | |
1115 EXPECT_EQ(POST_INSTALL_ACTION_DEFAULT, result_info.post_install_action); | |
1116 } | |
1117 | |
1118 | |
1119 TEST_F(InstallManagerInstallAppUserTest, | |
1120 PopulateSuccessfulInstallResultInfo_RebootShouldNotBeOverridden) { | |
1121 const SuccessfulInstallAction kSuccessActions[] = { | |
1122 SUCCESS_ACTION_DEFAULT, | |
1123 SUCCESS_ACTION_EXIT_SILENTLY, | |
1124 SUCCESS_ACTION_EXIT_SILENTLY_ON_LAUNCH_CMD, | |
1125 }; | |
1126 | |
1127 for (int i = 0; i < arraysize(kSuccessActions); ++i) { | |
1128 SetPostInstallActionInManifest(kSuccessActions[i], | |
1129 _T("http://foo/bar"), | |
1130 true, | |
1131 app_); | |
1132 | |
1133 InstallerResultInfo result_info; | |
1134 result_info.type = INSTALLER_RESULT_SUCCESS; | |
1135 result_info.post_install_action = POST_INSTALL_ACTION_REBOOT; | |
1136 result_info.post_install_launch_command_line = _T("foo.exe"); | |
1137 PopulateSuccessfulInstallResultInfo(app_, &result_info); | |
1138 | |
1139 EXPECT_EQ(POST_INSTALL_ACTION_REBOOT, result_info.post_install_action); | |
1140 } | |
1141 } | |
1142 | |
1143 } // namespace omaha | |
OLD | NEW |