| 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 | |
| 17 #include <vector> | |
| 18 #include "base/basictypes.h" | |
| 19 #include "base/scoped_ptr.h" | |
| 20 #include "omaha/base/app_util.h" | |
| 21 #include "omaha/base/const_object_names.h" | |
| 22 #include "omaha/base/error.h" | |
| 23 #include "omaha/base/file.h" | |
| 24 #include "omaha/base/path.h" | |
| 25 #include "omaha/base/omaha_version.h" | |
| 26 #include "omaha/base/process.h" | |
| 27 #include "omaha/base/scope_guard.h" | |
| 28 #include "omaha/base/scoped_any.h" | |
| 29 #include "omaha/base/synchronized.h" | |
| 30 #include "omaha/base/system.h" | |
| 31 #include "omaha/base/thread.h" | |
| 32 #include "omaha/base/user_info.h" | |
| 33 #include "omaha/base/utils.h" | |
| 34 #include "omaha/base/vistautil.h" | |
| 35 #include "omaha/common/command_line.h" | |
| 36 #include "omaha/common/config_manager.h" | |
| 37 #include "omaha/common/const_goopdate.h" | |
| 38 #include "omaha/setup/setup.h" | |
| 39 #include "omaha/setup/setup_files.h" | |
| 40 #include "omaha/testing/unit_test.h" | |
| 41 | |
| 42 namespace omaha { | |
| 43 | |
| 44 namespace { | |
| 45 | |
| 46 const int kProcessesCleanupWait = 30000; | |
| 47 | |
| 48 const TCHAR* const kFutureVersionString = _T("9.8.7.6"); | |
| 49 | |
| 50 const TCHAR* const kAppMachineClientsPath = | |
| 51 _T("HKLM\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
| 52 _T("\\Clients\\{50DA5C89-FF97-4536-BF3F-DF54C2F02EA8}\\"); | |
| 53 const TCHAR* const kAppMachineClientStatePath = | |
| 54 _T("HKLM\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
| 55 _T("\\ClientState\\{50DA5C89-FF97-4536-BF3F-DF54C2F02EA8}\\"); | |
| 56 const TCHAR* const kApp2MachineClientsPath = | |
| 57 _T("HKLM\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
| 58 _T("\\Clients\\{CB8E8A3C-7295-4529-B083-D5F76DCD4CC2}\\"); | |
| 59 | |
| 60 const TCHAR* const kAppUserClientsPath = | |
| 61 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
| 62 _T("\\Clients\\{50DA5C89-FF97-4536-BF3F-DF54C2F02EA8}\\"); | |
| 63 const TCHAR* const kAppUserClientStatePath = | |
| 64 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
| 65 _T("\\ClientState\\{50DA5C89-FF97-4536-BF3F-DF54C2F02EA8}\\"); | |
| 66 const TCHAR* const kApp2UserClientsPath = | |
| 67 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
| 68 _T("\\Clients\\{CB8E8A3C-7295-4529-B083-D5F76DCD4CC2}\\"); | |
| 69 | |
| 70 | |
| 71 class HoldLock : public Runnable { | |
| 72 public: | |
| 73 explicit HoldLock(bool is_machine) | |
| 74 : is_machine_(is_machine) { | |
| 75 reset(lock_acquired_event_, ::CreateEvent(NULL, false, false, NULL)); | |
| 76 reset(stop_event_, ::CreateEvent(NULL, false, false, NULL)); | |
| 77 } | |
| 78 | |
| 79 virtual void Run() { | |
| 80 GLock setup_lock; | |
| 81 NamedObjectAttributes setup_lock_attr; | |
| 82 GetNamedObjectAttributes(omaha::kSetupMutex, is_machine_, &setup_lock_attr); | |
| 83 EXPECT_TRUE(setup_lock.InitializeWithSecAttr(setup_lock_attr.name, | |
| 84 &setup_lock_attr.sa)); | |
| 85 __mutexScope(setup_lock); | |
| 86 | |
| 87 EXPECT_TRUE(::SetEvent(get(lock_acquired_event_))); | |
| 88 | |
| 89 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(get(stop_event_), INFINITE)); | |
| 90 } | |
| 91 | |
| 92 void Stop() { | |
| 93 EXPECT_TRUE(::SetEvent(get(stop_event_))); | |
| 94 } | |
| 95 | |
| 96 void WaitForLockToBeAcquired() { | |
| 97 EXPECT_EQ(WAIT_OBJECT_0, | |
| 98 ::WaitForSingleObject(get(lock_acquired_event_), 2000)); | |
| 99 } | |
| 100 | |
| 101 private: | |
| 102 const bool is_machine_; | |
| 103 scoped_event lock_acquired_event_; | |
| 104 scoped_event stop_event_; | |
| 105 | |
| 106 DISALLOW_IMPLICIT_CONSTRUCTORS(HoldLock); | |
| 107 }; | |
| 108 | |
| 109 } // namespace | |
| 110 | |
| 111 void CopyGoopdateFiles(const CString& omaha_path, const CString& version); | |
| 112 | |
| 113 class SetupTest : public testing::Test { | |
| 114 protected: | |
| 115 | |
| 116 typedef std::vector<uint32> Pids; | |
| 117 | |
| 118 // Returns the path to the long-running GoogleUpdate.exe. | |
| 119 static CString CopyGoopdateAndLongRunningFiles(const CString& omaha_path, | |
| 120 const CString& version) { | |
| 121 CopyGoopdateFiles(omaha_path, version); | |
| 122 | |
| 123 CString long_running_target_path = ConcatenatePath(omaha_path, | |
| 124 _T("does_not_shutdown")); | |
| 125 EXPECT_SUCCEEDED(CreateDir(long_running_target_path, NULL)); | |
| 126 long_running_target_path = ConcatenatePath(long_running_target_path, | |
| 127 kOmahaShellFileName); | |
| 128 EXPECT_SUCCEEDED(File::Copy( | |
| 129 ConcatenatePath(ConcatenatePath( | |
| 130 app_util::GetCurrentModuleDirectory(), | |
| 131 _T("unittest_support\\does_not_shutdown")), | |
| 132 kOmahaShellFileName), | |
| 133 long_running_target_path, | |
| 134 false)); | |
| 135 | |
| 136 return long_running_target_path; | |
| 137 } | |
| 138 | |
| 139 static void SetUpTestCase() { | |
| 140 not_listening_machine_exe_path_ = | |
| 141 CopyGoopdateAndLongRunningFiles(GetGoogleUpdateMachinePath(), | |
| 142 GetVersionString()); | |
| 143 not_listening_user_exe_path_ = | |
| 144 CopyGoopdateAndLongRunningFiles(GetGoogleUpdateUserPath(), | |
| 145 GetVersionString()); | |
| 146 } | |
| 147 | |
| 148 explicit SetupTest(bool is_machine) | |
| 149 : is_machine_(is_machine), | |
| 150 omaha_path_(is_machine ? GetGoogleUpdateMachinePath() : | |
| 151 GetGoogleUpdateUserPath()), | |
| 152 not_listening_exe_path_(is_machine ? not_listening_machine_exe_path_ : | |
| 153 not_listening_user_exe_path_), | |
| 154 not_listening_exe_opposite_path_(!is_machine ? | |
| 155 not_listening_machine_exe_path_ : | |
| 156 not_listening_user_exe_path_) { | |
| 157 omaha_exe_path_ = ConcatenatePath(omaha_path_, _T("GoogleUpdate.exe")); | |
| 158 } | |
| 159 | |
| 160 virtual void SetUp() { | |
| 161 ASSERT_SUCCEEDED(CreateDir(omaha_path_, NULL)); | |
| 162 setup_.reset(new omaha::Setup(is_machine_)); | |
| 163 } | |
| 164 | |
| 165 bool ShouldInstall() { | |
| 166 SetupFiles setup_files(is_machine_); | |
| 167 setup_files.Init(); | |
| 168 return setup_->ShouldInstall(&setup_files); | |
| 169 } | |
| 170 | |
| 171 HRESULT StopGoogleUpdateAndWait() { | |
| 172 return setup_->StopGoogleUpdateAndWait(); | |
| 173 } | |
| 174 | |
| 175 HRESULT TerminateCoreProcesses() const { | |
| 176 return setup_->TerminateCoreProcesses(); | |
| 177 } | |
| 178 | |
| 179 // Acquires the Setup Lock in another thread then calls TestInstall(). | |
| 180 void TestInstallWhileHoldingLock() { | |
| 181 HoldLock hold_lock(is_machine_); | |
| 182 | |
| 183 Thread thread; | |
| 184 thread.Start(&hold_lock); | |
| 185 hold_lock.WaitForLockToBeAcquired(); | |
| 186 | |
| 187 EXPECT_EQ(GOOPDATE_E_FAILED_TO_GET_LOCK, setup_->Install(false)); | |
| 188 | |
| 189 hold_lock.Stop(); | |
| 190 thread.WaitTillExit(1000); | |
| 191 } | |
| 192 | |
| 193 void StopGoogleUpdateAndWaitSucceedsTestHelper(bool use_job_objects_only) { | |
| 194 if (is_machine_ && !vista_util::IsUserAdmin()) { | |
| 195 std::wcout << _T("\tTest did not run because the user is not an admin.") | |
| 196 << std::endl; | |
| 197 return; | |
| 198 } | |
| 199 | |
| 200 if (!ShouldRunLargeTest()) { | |
| 201 return; | |
| 202 } | |
| 203 if (IsBuildSystem()) { | |
| 204 std::wcout << _T("\tTest not run because it is flaky on build system.") | |
| 205 << std::endl; | |
| 206 return; | |
| 207 } | |
| 208 | |
| 209 scoped_process core_process; | |
| 210 scoped_process install_process; | |
| 211 scoped_process opposite_process; | |
| 212 scoped_process user_handoff_process; | |
| 213 scoped_process user_install_goopdate_process; | |
| 214 scoped_process user_install_slashinstall_process; | |
| 215 scoped_process setup_phase1_job_process; | |
| 216 scoped_process setup_phase1_job_opposite_process; | |
| 217 scoped_process install_job_opposite_process; | |
| 218 scoped_process silent_job_opposite_process; | |
| 219 scoped_process silent_do_not_kill_job_opposite_process; | |
| 220 scoped_job setup_phase1_job; | |
| 221 scoped_job setup_phase1_job_opposite; | |
| 222 scoped_job install_job_opposite; | |
| 223 scoped_job silent_job_opposite; | |
| 224 scoped_job silent_do_not_kill_job_opposite; | |
| 225 | |
| 226 StartCoreProcessesToShutdown(address(core_process)); | |
| 227 ASSERT_TRUE(core_process); | |
| 228 | |
| 229 if (use_job_objects_only && is_machine_) { | |
| 230 // When starting the core process with psexec, there is a race condition | |
| 231 // between that process initializing (and joining a Job Object) and | |
| 232 // StopGoogleUpdateAndWait() looking for processes. If the latter wins, | |
| 233 // the core process is not found and StopGoogleUpdateAndWait() does not | |
| 234 // wait for the core process. As a result, | |
| 235 // ::WaitForSingleObject(get(core_process), 0)) would fail intermittently. | |
| 236 // Sleep here to allow the process to start and join the job. | |
| 237 // Note that this race condition is similar to ones we might encounter | |
| 238 // in the field when using Job Objects. | |
| 239 ::Sleep(500); | |
| 240 } | |
| 241 | |
| 242 // /install is always ignored. | |
| 243 LaunchProcess(not_listening_exe_path_, | |
| 244 _T("/install"), | |
| 245 is_machine_, | |
| 246 address(install_process)); | |
| 247 ASSERT_TRUE(install_process); | |
| 248 EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(get(install_process), 0)); | |
| 249 | |
| 250 if (vista_util::IsUserAdmin()) { | |
| 251 // GoogleUpdate running from the opposite directory should always be | |
| 252 // ignored. Using a command line that would not be ignored if it were not | |
| 253 // an opposite. | |
| 254 LaunchProcess(not_listening_exe_opposite_path_, | |
| 255 _T(""), | |
| 256 false, | |
| 257 address(opposite_process)); | |
| 258 EXPECT_TRUE(opposite_process); | |
| 259 EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(get(opposite_process), 0)); | |
| 260 } else { | |
| 261 EXPECT_FALSE(is_machine_) | |
| 262 << _T("Unexpected call for machine when non-admin."); | |
| 263 // We can't launch a system process when non-admin. | |
| 264 std::wcout << _T("\tPart of this test did not run because the user is ") | |
| 265 _T("not an admin.") << std::endl; | |
| 266 } | |
| 267 | |
| 268 CString same_needsadmin = is_machine_ ? _T("\"needsadmin=True\"") : | |
| 269 _T("\"needsadmin=False\""); | |
| 270 // Machine setup looks for users running most modes from the machine | |
| 271 // official directory, and user setup looks for users running most modes | |
| 272 // from the user official directory. | |
| 273 // Launching with needsadmin=<same> tests that machine still ignores | |
| 274 // needsadmin=True and user ignores needsadmin=False when the opposite | |
| 275 // instances are running. | |
| 276 LaunchProcess(not_listening_exe_opposite_path_, | |
| 277 _T("/handoff ") + same_needsadmin, | |
| 278 false, // As the user. | |
| 279 address(user_handoff_process)); | |
| 280 EXPECT_TRUE(user_handoff_process); | |
| 281 EXPECT_EQ(WAIT_TIMEOUT, | |
| 282 ::WaitForSingleObject(get(user_handoff_process), 0)); | |
| 283 | |
| 284 // This process should be ignored even though it is running from the correct | |
| 285 // official directory. | |
| 286 LaunchProcess(not_listening_exe_path_, | |
| 287 _T("/install ") + same_needsadmin, | |
| 288 false, // As the user. | |
| 289 address(user_install_slashinstall_process)); | |
| 290 EXPECT_TRUE(user_install_goopdate_process); | |
| 291 EXPECT_EQ(WAIT_TIMEOUT, | |
| 292 ::WaitForSingleObject(get(user_install_goopdate_process), 0)); | |
| 293 | |
| 294 if (use_job_objects_only) { | |
| 295 // This Job Object is ignored. | |
| 296 // Only start this process when only using Job Objects because the | |
| 297 // argument-less process would be caught by the command line search. | |
| 298 LaunchJobProcess(is_machine_, | |
| 299 is_machine_, | |
| 300 kSetupPhase1NonSelfUpdateJobObject, | |
| 301 address(setup_phase1_job_process), | |
| 302 address(setup_phase1_job)); | |
| 303 ASSERT_TRUE(setup_phase1_job_process); | |
| 304 EXPECT_EQ(WAIT_TIMEOUT, | |
| 305 ::WaitForSingleObject(get(setup_phase1_job_process), 0)); | |
| 306 } | |
| 307 | |
| 308 if (is_machine_ || vista_util::IsUserAdmin()) { | |
| 309 // These processes should be ignored because they are for the opposite | |
| 310 // set of processes. | |
| 311 | |
| 312 LaunchJobProcess(!is_machine_, | |
| 313 !is_machine_, | |
| 314 kSetupPhase1NonSelfUpdateJobObject, | |
| 315 address(setup_phase1_job_opposite_process), | |
| 316 address(setup_phase1_job_opposite)); | |
| 317 ASSERT_TRUE(setup_phase1_job_opposite_process); | |
| 318 EXPECT_EQ(WAIT_TIMEOUT, | |
| 319 ::WaitForSingleObject(get(setup_phase1_job_opposite_process), | |
| 320 0)); | |
| 321 | |
| 322 LaunchJobProcess(!is_machine_, | |
| 323 !is_machine_, | |
| 324 kAppInstallJobObject, | |
| 325 address(install_job_opposite_process), | |
| 326 address(install_job_opposite)); | |
| 327 ASSERT_TRUE(install_job_opposite_process); | |
| 328 EXPECT_EQ(WAIT_TIMEOUT, | |
| 329 ::WaitForSingleObject(get(install_job_opposite_process), 0)); | |
| 330 | |
| 331 LaunchJobProcess(!is_machine_, | |
| 332 !is_machine_, | |
| 333 kSilentJobObject, | |
| 334 address(silent_job_opposite_process), | |
| 335 address(silent_job_opposite)); | |
| 336 ASSERT_TRUE(install_job_opposite_process); | |
| 337 EXPECT_EQ(WAIT_TIMEOUT, | |
| 338 ::WaitForSingleObject(get(install_job_opposite_process), 0)); | |
| 339 | |
| 340 LaunchJobProcess(!is_machine_, | |
| 341 !is_machine_, | |
| 342 kSilentDoNotKillJobObject, | |
| 343 address(silent_do_not_kill_job_opposite_process), | |
| 344 address(silent_do_not_kill_job_opposite)); | |
| 345 ASSERT_TRUE(install_job_opposite_process); | |
| 346 EXPECT_EQ(WAIT_TIMEOUT, | |
| 347 ::WaitForSingleObject(get(install_job_opposite_process), 0)); | |
| 348 } | |
| 349 | |
| 350 EXPECT_SUCCEEDED(StopGoogleUpdateAndWait()); | |
| 351 EXPECT_EQ(0, setup_->extra_code1()); | |
| 352 | |
| 353 // Verify the real core process exited and terminate the processes that are | |
| 354 // not listening to shutdown. | |
| 355 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(get(core_process), 0)); | |
| 356 | |
| 357 // Terminate all the processes and wait for them to exit to avoid | |
| 358 // interfering with other tests. | |
| 359 std::vector<HANDLE> started_processes; | |
| 360 started_processes.push_back(get(install_process)); | |
| 361 if (vista_util::IsUserAdmin()) { | |
| 362 started_processes.push_back(get(opposite_process)); | |
| 363 } | |
| 364 started_processes.push_back(get(user_handoff_process)); | |
| 365 started_processes.push_back(get(user_install_goopdate_process)); | |
| 366 started_processes.push_back(get(user_install_slashinstall_process)); | |
| 367 if (use_job_objects_only) { | |
| 368 started_processes.push_back(get(setup_phase1_job_process)); | |
| 369 } | |
| 370 if (is_machine_ || vista_util::IsUserAdmin()) { | |
| 371 started_processes.push_back(get(setup_phase1_job_opposite_process)); | |
| 372 started_processes.push_back(get(install_job_opposite_process)); | |
| 373 started_processes.push_back(get(silent_job_opposite_process)); | |
| 374 started_processes.push_back(get(silent_do_not_kill_job_opposite_process)); | |
| 375 } | |
| 376 | |
| 377 for (size_t i = 0; i < started_processes.size(); ++i) { | |
| 378 SETUP_LOG(L1, (_T("Terminating PID %u]"), | |
| 379 ::GetProcessId(started_processes[i]))); | |
| 380 EXPECT_TRUE(::TerminateProcess(started_processes[i], 1)); | |
| 381 } | |
| 382 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForMultipleObjects(started_processes.size(), | |
| 383 &started_processes[0], | |
| 384 true, // wait for all | |
| 385 kProcessesCleanupWait)); | |
| 386 } | |
| 387 | |
| 388 void StopGoogleUpdateAndWaitSucceedsTest() { | |
| 389 StopGoogleUpdateAndWaitSucceedsTestHelper(false); | |
| 390 } | |
| 391 | |
| 392 HRESULT GetRunningCoreProcesses(Pids* core_processes) { | |
| 393 ASSERT1(core_processes); | |
| 394 | |
| 395 CString user_sid_to_use; | |
| 396 if (is_machine_) { | |
| 397 user_sid_to_use = kLocalSystemSid; | |
| 398 } else { | |
| 399 EXPECT_SUCCEEDED(user_info::GetProcessUser(NULL, NULL, &user_sid_to_use)); | |
| 400 } | |
| 401 | |
| 402 DWORD flags = INCLUDE_ONLY_PROCESS_OWNED_BY_USER | | |
| 403 EXCLUDE_CURRENT_PROCESS | | |
| 404 INCLUDE_PROCESS_COMMAND_LINE_CONTAINING_STRING; | |
| 405 | |
| 406 std::vector<CString> command_lines; | |
| 407 command_lines.push_back(_T("/c")); | |
| 408 | |
| 409 return Process::FindProcesses(flags, | |
| 410 kOmahaShellFileName, | |
| 411 true, | |
| 412 user_sid_to_use, | |
| 413 command_lines, | |
| 414 core_processes); | |
| 415 } | |
| 416 | |
| 417 void KillRunningCoreProcesses() { | |
| 418 Pids core_processes; | |
| 419 EXPECT_SUCCEEDED(GetRunningCoreProcesses(&core_processes)); | |
| 420 | |
| 421 for (size_t i = 0; i < core_processes.size(); ++i) { | |
| 422 scoped_process process(::OpenProcess(PROCESS_TERMINATE, | |
| 423 FALSE, | |
| 424 core_processes[i])); | |
| 425 EXPECT_TRUE(process); | |
| 426 EXPECT_TRUE(::TerminateProcess(get(process), static_cast<uint32>(-2))); | |
| 427 } | |
| 428 } | |
| 429 | |
| 430 // Uses psexec to start processes as SYSTEM if necessary. | |
| 431 // Assumes that psexec blocks until the process exits. | |
| 432 // TODO(omaha): Start the opposite instances and wait for them in | |
| 433 // StopGoogleUpdateAndWaitSucceedsTest. They should not close. | |
| 434 void StartCoreProcessesToShutdown(HANDLE* core_process) { | |
| 435 ASSERT_TRUE(core_process); | |
| 436 | |
| 437 // Find the core process or start one if necessary. | |
| 438 Pids core_processes; | |
| 439 EXPECT_SUCCEEDED(GetRunningCoreProcesses(&core_processes)); | |
| 440 ASSERT_LE(core_processes.size(), static_cast<size_t>(1)) | |
| 441 << _T("Only one core should be running."); | |
| 442 | |
| 443 if (core_processes.empty()) { | |
| 444 LaunchProcess(omaha_exe_path_, | |
| 445 _T("/c"), | |
| 446 is_machine_, | |
| 447 core_process); | |
| 448 } else { | |
| 449 *core_process = ::OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, | |
| 450 FALSE, | |
| 451 core_processes[0]); | |
| 452 } | |
| 453 ASSERT_TRUE(*core_process); | |
| 454 | |
| 455 HANDLE processes[] = {*core_process}; | |
| 456 EXPECT_EQ(WAIT_TIMEOUT, ::WaitForMultipleObjects(arraysize(processes), | |
| 457 processes, | |
| 458 true, // wait for all | |
| 459 0)); | |
| 460 } | |
| 461 | |
| 462 // Launches an instance of GoogleUpdate.exe that doesn't exit. | |
| 463 void StopGoogleUpdateAndWaitProcessesDoNotStopTest() { | |
| 464 LaunchProcessAndExpectStopGoogleUpdateAndWaitKillsProcess( | |
| 465 is_machine_, | |
| 466 _T("")); | |
| 467 } | |
| 468 | |
| 469 void LaunchProcessAndExpectStopGoogleUpdateAndWaitKillsProcess( | |
| 470 bool is_machine_process, | |
| 471 const CString& args) { | |
| 472 ASSERT_TRUE(args); | |
| 473 | |
| 474 if (is_machine_ && !vista_util::IsUserAdmin()) { | |
| 475 std::wcout << _T("\tTest did not run because the user is not an admin.") | |
| 476 << std::endl; | |
| 477 return; | |
| 478 } | |
| 479 | |
| 480 if (!ShouldRunLargeTest()) { | |
| 481 return; | |
| 482 } | |
| 483 scoped_process process; | |
| 484 LaunchProcess(not_listening_exe_path_, | |
| 485 args, | |
| 486 is_machine_process, | |
| 487 address(process)); | |
| 488 ASSERT_TRUE(process); | |
| 489 EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(get(process), 0)); | |
| 490 | |
| 491 // Tests that use this method intermittently fail when run on build systems. | |
| 492 // This code attempts to ensure that the process is further along in the | |
| 493 // initialization process by waiting until Process::GetCommandLine succeeds. | |
| 494 HRESULT hr = E_FAIL; | |
| 495 CString process_cmd; | |
| 496 for (int tries = 0; tries < 100 && FAILED(hr); ++tries) { | |
| 497 hr = Process::GetCommandLine(::GetProcessId(get(process)), &process_cmd); | |
| 498 if (FAILED(hr)) { | |
| 499 ::Sleep(50); | |
| 500 } | |
| 501 } | |
| 502 EXPECT_SUCCEEDED(hr); | |
| 503 | |
| 504 EXPECT_EQ(S_OK, StopGoogleUpdateAndWait()); | |
| 505 // Make sure the process has been killed. | |
| 506 EXPECT_EQ(WAIT_OBJECT_0, | |
| 507 ::WaitForSingleObject(get(process), kProcessesCleanupWait)); | |
| 508 } | |
| 509 | |
| 510 // Starts a core process for this user, a core for the opposite type of user, | |
| 511 // and a /cr process (similar command line to /c), and a process without args. | |
| 512 void TestTerminateCoreProcessesWithBothTypesRunningAndOtherProcesses() { | |
| 513 scoped_process core_process; | |
| 514 scoped_process opposite_core_process; | |
| 515 scoped_process codered_process; | |
| 516 scoped_process noargs_process; | |
| 517 LaunchProcess(not_listening_exe_path_, | |
| 518 _T("/c"), | |
| 519 is_machine_, | |
| 520 address(core_process)); | |
| 521 ASSERT_TRUE(core_process); | |
| 522 EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(get(core_process), 0)); | |
| 523 LaunchProcess(not_listening_exe_opposite_path_, | |
| 524 _T("/c"), | |
| 525 !is_machine_, | |
| 526 address(opposite_core_process)); | |
| 527 ASSERT_TRUE(opposite_core_process); | |
| 528 EXPECT_EQ(WAIT_TIMEOUT, | |
| 529 ::WaitForSingleObject(get(opposite_core_process), 0)); | |
| 530 LaunchProcess(not_listening_exe_path_, | |
| 531 _T("/cr"), | |
| 532 is_machine_, | |
| 533 address(codered_process)); | |
| 534 ASSERT_TRUE(codered_process); | |
| 535 EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(get(codered_process), 0)); | |
| 536 LaunchProcess(not_listening_exe_path_, | |
| 537 _T(""), | |
| 538 is_machine_, | |
| 539 address(noargs_process)); | |
| 540 ASSERT_TRUE(noargs_process); | |
| 541 EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(get(noargs_process), 0)); | |
| 542 | |
| 543 EXPECT_SUCCEEDED(TerminateCoreProcesses()); | |
| 544 | |
| 545 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(get(core_process), 8000)); | |
| 546 HANDLE ignored_processes[] = {get(opposite_core_process), | |
| 547 get(codered_process), | |
| 548 get(noargs_process)}; | |
| 549 EXPECT_EQ(WAIT_TIMEOUT, | |
| 550 ::WaitForMultipleObjects(arraysize(ignored_processes), | |
| 551 ignored_processes, | |
| 552 false, // wait for any | |
| 553 1000)); | |
| 554 | |
| 555 HANDLE started_processes[] = {get(core_process), | |
| 556 get(opposite_core_process), | |
| 557 get(codered_process), | |
| 558 get(noargs_process)}; | |
| 559 EXPECT_TRUE(::TerminateProcess(get(opposite_core_process), 1)); | |
| 560 EXPECT_TRUE(::TerminateProcess(get(codered_process), 1)); | |
| 561 EXPECT_TRUE(::TerminateProcess(get(noargs_process), 1)); | |
| 562 EXPECT_EQ(WAIT_OBJECT_0, | |
| 563 ::WaitForMultipleObjects(arraysize(started_processes), | |
| 564 started_processes, | |
| 565 true, // wait for all | |
| 566 kProcessesCleanupWait)); | |
| 567 } | |
| 568 | |
| 569 // Starts dummy process that doesn't exit and assigns it to the specified job. | |
| 570 // The handle returned by ShellExecute does not have PROCESS_SET_QUOTA access | |
| 571 // rights, so we get a new handle with the correct access rights to return to | |
| 572 // the caller. | |
| 573 void LaunchJobProcess(bool is_machine, | |
| 574 bool as_system, | |
| 575 const CString& job_base_name, | |
| 576 HANDLE* process, | |
| 577 HANDLE* job) { | |
| 578 ASSERT_TRUE(process); | |
| 579 ASSERT_TRUE(job); | |
| 580 ASSERT_TRUE(is_machine || !as_system); | |
| 581 | |
| 582 scoped_process launched_process; | |
| 583 LaunchProcess(is_machine ? not_listening_machine_exe_path_ : | |
| 584 not_listening_user_exe_path_, | |
| 585 _T(""), | |
| 586 as_system, | |
| 587 address(launched_process)); | |
| 588 ASSERT_TRUE(launched_process); | |
| 589 | |
| 590 *process = ::OpenProcess(PROCESS_ALL_ACCESS, | |
| 591 false, | |
| 592 ::GetProcessId(get(launched_process))); | |
| 593 ASSERT_TRUE(*process); | |
| 594 | |
| 595 NamedObjectAttributes job_attr; | |
| 596 GetNamedObjectAttributes(job_base_name, is_machine, &job_attr); | |
| 597 *job = ::CreateJobObject(&job_attr.sa, job_attr.name); | |
| 598 ASSERT_TRUE(*job); | |
| 599 | |
| 600 if (ERROR_ALREADY_EXISTS != ::GetLastError()) { | |
| 601 // Configure the newly created Job Object so it is compatible with any | |
| 602 // real processes that may be created. | |
| 603 JOBOBJECT_EXTENDED_LIMIT_INFORMATION extended_info = {0}; | |
| 604 | |
| 605 ASSERT_TRUE(::QueryInformationJobObject( | |
| 606 *job, | |
| 607 ::JobObjectExtendedLimitInformation, | |
| 608 &extended_info, | |
| 609 sizeof(extended_info), | |
| 610 NULL)) << | |
| 611 _T("Last Error: ") << ::GetLastError() << std::endl; | |
| 612 | |
| 613 extended_info.BasicLimitInformation.LimitFlags = | |
| 614 JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK; | |
| 615 ASSERT_TRUE(::SetInformationJobObject(*job, | |
| 616 ::JobObjectExtendedLimitInformation, | |
| 617 &extended_info, | |
| 618 sizeof(extended_info))) << | |
| 619 _T("Last Error: ") << ::GetLastError() << std::endl; | |
| 620 } | |
| 621 | |
| 622 ASSERT_TRUE(::AssignProcessToJobObject(*job, *process)) << | |
| 623 _T("Last Error: ") << ::GetLastError() << std::endl; | |
| 624 } | |
| 625 | |
| 626 void TestShouldDelayUninstall() { | |
| 627 EXPECT_FALSE(setup_->ShouldDelayUninstall()); | |
| 628 | |
| 629 const TCHAR* key = ConfigManager::Instance()->registry_update(is_machine_); | |
| 630 | |
| 631 DWORD value = 1; | |
| 632 EXPECT_SUCCEEDED(RegKey::SetValue(key, | |
| 633 kRegValueDelayOmahaUninstall, | |
| 634 value)); | |
| 635 EXPECT_TRUE(setup_->ShouldDelayUninstall()); | |
| 636 | |
| 637 value = 0; | |
| 638 EXPECT_SUCCEEDED(RegKey::SetValue(key, | |
| 639 kRegValueDelayOmahaUninstall, | |
| 640 value)); | |
| 641 EXPECT_FALSE(setup_->ShouldDelayUninstall()); | |
| 642 | |
| 643 EXPECT_SUCCEEDED(RegKey::DeleteValue(key, | |
| 644 kRegValueDelayOmahaUninstall)); | |
| 645 EXPECT_FALSE(setup_->ShouldDelayUninstall()); | |
| 646 } | |
| 647 | |
| 648 void TestSetDelayUninstall() { | |
| 649 EXPECT_FALSE(setup_->ShouldDelayUninstall()); | |
| 650 | |
| 651 EXPECT_SUCCEEDED(setup_->SetDelayUninstall(true)); | |
| 652 EXPECT_TRUE(setup_->ShouldDelayUninstall()); | |
| 653 | |
| 654 EXPECT_SUCCEEDED(setup_->SetDelayUninstall(true)); | |
| 655 EXPECT_TRUE(setup_->ShouldDelayUninstall()); | |
| 656 | |
| 657 EXPECT_SUCCEEDED(setup_->SetDelayUninstall(false)); | |
| 658 EXPECT_FALSE(setup_->ShouldDelayUninstall()); | |
| 659 | |
| 660 EXPECT_SUCCEEDED(setup_->SetDelayUninstall(false)); | |
| 661 EXPECT_FALSE(setup_->ShouldDelayUninstall()); | |
| 662 } | |
| 663 | |
| 664 const bool is_machine_; | |
| 665 const CString omaha_path_; | |
| 666 CString omaha_exe_path_; | |
| 667 CString not_listening_exe_path_; | |
| 668 CString not_listening_exe_opposite_path_; | |
| 669 scoped_ptr<omaha::Setup> setup_; | |
| 670 | |
| 671 static CString not_listening_user_exe_path_; | |
| 672 static CString not_listening_machine_exe_path_; | |
| 673 }; | |
| 674 | |
| 675 CString SetupTest::not_listening_user_exe_path_; | |
| 676 CString SetupTest::not_listening_machine_exe_path_; | |
| 677 | |
| 678 class SetupMachineTest : public SetupTest { | |
| 679 protected: | |
| 680 SetupMachineTest() : SetupTest(true) { | |
| 681 } | |
| 682 | |
| 683 static void SetUpTestCase() { | |
| 684 // SeDebugPrivilege is required for elevated admins to open process open | |
| 685 // Local System processes with PROCESS_QUERY_INFORMATION access rights. | |
| 686 System::AdjustPrivilege(SE_DEBUG_NAME, true); | |
| 687 | |
| 688 SetupTest::SetUpTestCase(); | |
| 689 } | |
| 690 }; | |
| 691 | |
| 692 class SetupUserTest : public SetupTest { | |
| 693 protected: | |
| 694 SetupUserTest() : SetupTest(false) { | |
| 695 } | |
| 696 }; | |
| 697 | |
| 698 class SetupFutureVersionInstalledUserTest : public SetupUserTest { | |
| 699 protected: | |
| 700 SetupFutureVersionInstalledUserTest() | |
| 701 : SetupUserTest(), | |
| 702 future_version_path_(ConcatenatePath(omaha_path_, | |
| 703 kFutureVersionString)) { | |
| 704 } | |
| 705 | |
| 706 virtual void SetUp() { | |
| 707 SetupUserTest::SetUp(); | |
| 708 | |
| 709 // Save the existing version if present. | |
| 710 RegKey::GetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 711 kRegValueProductVersion, | |
| 712 &existing_version_); | |
| 713 InstallFutureVersion(); | |
| 714 } | |
| 715 | |
| 716 virtual void TearDown() { | |
| 717 EXPECT_SUCCEEDED(DeleteDirectory(future_version_path_)); | |
| 718 if (existing_version_.IsEmpty()) { | |
| 719 EXPECT_SUCCEEDED(RegKey::DeleteValue(USER_REG_CLIENTS_GOOPDATE, | |
| 720 kRegValueProductVersion)); | |
| 721 } else { | |
| 722 EXPECT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 723 kRegValueProductVersion, | |
| 724 existing_version_)); | |
| 725 } | |
| 726 | |
| 727 SetupUserTest::TearDown(); | |
| 728 } | |
| 729 | |
| 730 void InstallFutureVersion() { | |
| 731 DeleteDirectory(future_version_path_); | |
| 732 EXPECT_FALSE(File::IsDirectory(future_version_path_)); | |
| 733 | |
| 734 EXPECT_SUCCEEDED(CreateDir(future_version_path_, NULL)); | |
| 735 | |
| 736 EXPECT_SUCCEEDED(File::Copy( | |
| 737 ConcatenatePath(app_util::GetCurrentModuleDirectory(), | |
| 738 kOmahaShellFileName), | |
| 739 omaha_path_ + kOmahaShellFileName, | |
| 740 false)); | |
| 741 | |
| 742 EXPECT_SUCCEEDED(File::Copy( | |
| 743 ConcatenatePath(app_util::GetCurrentModuleDirectory(), | |
| 744 kOmahaDllName), | |
| 745 ConcatenatePath(future_version_path_, kOmahaDllName), | |
| 746 false)); | |
| 747 EXPECT_SUCCEEDED(File::Copy( | |
| 748 ConcatenatePath(app_util::GetCurrentModuleDirectory(), | |
| 749 _T("goopdateres_en.dll")), | |
| 750 ConcatenatePath(future_version_path_, _T("goopdateres_en.dll")), | |
| 751 false)); | |
| 752 | |
| 753 EXPECT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 754 kRegValueProductVersion, | |
| 755 kFutureVersionString)); | |
| 756 } | |
| 757 | |
| 758 CString existing_version_; // Saves the existing version from the registry. | |
| 759 const CString future_version_path_; | |
| 760 static const TCHAR* const kAppGuid_; | |
| 761 }; | |
| 762 | |
| 763 const TCHAR* const SetupFutureVersionInstalledUserTest::kAppGuid_ = | |
| 764 _T("{01D33078-BA95-4da6-A3FC-F31593FD4AA2}"); | |
| 765 | |
| 766 class SetupRegistryProtectedUserTest : public SetupUserTest { | |
| 767 protected: | |
| 768 SetupRegistryProtectedUserTest() | |
| 769 : SetupUserTest(), | |
| 770 hive_override_key_name_(kRegistryHiveOverrideRoot) { | |
| 771 } | |
| 772 | |
| 773 static void SetUpTestCase() { | |
| 774 this_version_ = GetVersionString(); | |
| 775 expected_is_overinstall_ = !OFFICIAL_BUILD; | |
| 776 #ifdef DEBUG | |
| 777 if (RegKey::HasValue(MACHINE_REG_UPDATE_DEV, kRegValueNameOverInstall)) { | |
| 778 DWORD value = 0; | |
| 779 EXPECT_SUCCEEDED(RegKey::GetValue(MACHINE_REG_UPDATE_DEV, | |
| 780 kRegValueNameOverInstall, | |
| 781 &value)); | |
| 782 expected_is_overinstall_ = value != 0; | |
| 783 } | |
| 784 #endif | |
| 785 } | |
| 786 | |
| 787 virtual void SetUp() { | |
| 788 SetupUserTest::SetUp(); | |
| 789 | |
| 790 RegKey::DeleteKey(hive_override_key_name_, true); | |
| 791 // Do not override HKLM because it contains the CSIDL_* definitions. | |
| 792 OverrideSpecifiedRegistryHives(hive_override_key_name_, false, true); | |
| 793 } | |
| 794 | |
| 795 virtual void TearDown() { | |
| 796 RestoreRegistryHives(); | |
| 797 ASSERT_SUCCEEDED(RegKey::DeleteKey(hive_override_key_name_, true)); | |
| 798 | |
| 799 SetupUserTest::TearDown(); | |
| 800 } | |
| 801 | |
| 802 const CString hive_override_key_name_; | |
| 803 | |
| 804 static CString this_version_; | |
| 805 static bool expected_is_overinstall_; | |
| 806 }; | |
| 807 | |
| 808 CString SetupRegistryProtectedUserTest::this_version_; | |
| 809 bool SetupRegistryProtectedUserTest::expected_is_overinstall_; | |
| 810 | |
| 811 class SetupRegistryProtectedMachineTest : public SetupMachineTest { | |
| 812 protected: | |
| 813 SetupRegistryProtectedMachineTest() | |
| 814 : SetupMachineTest(), | |
| 815 hive_override_key_name_(kRegistryHiveOverrideRoot) { | |
| 816 } | |
| 817 | |
| 818 virtual void SetUp() { | |
| 819 SetupMachineTest::SetUp(); | |
| 820 | |
| 821 RegKey::DeleteKey(hive_override_key_name_, true); | |
| 822 OverrideRegistryHives(hive_override_key_name_); | |
| 823 } | |
| 824 | |
| 825 virtual void TearDown() { | |
| 826 RestoreRegistryHives(); | |
| 827 ASSERT_SUCCEEDED(RegKey::DeleteKey(hive_override_key_name_, true)); | |
| 828 | |
| 829 SetupMachineTest::TearDown(); | |
| 830 } | |
| 831 | |
| 832 const CString hive_override_key_name_; | |
| 833 }; | |
| 834 | |
| 835 // TODO(omaha3): These tests are left over from Omaha2's InstallSelfSilently(), | |
| 836 // which like Omaha3's Install(), does not install the app. It did, however, | |
| 837 // start another process to complete installation. This would cause it to fail | |
| 838 // if the shell or main DLL were missing. | |
| 839 TEST_F(SetupFutureVersionInstalledUserTest, DISABLED_Install_NoRunKey) { | |
| 840 RegKey::DeleteKey(kRegistryHiveOverrideRoot, true); | |
| 841 OverrideSpecifiedRegistryHives(kRegistryHiveOverrideRoot, false, true); | |
| 842 | |
| 843 // Write the future version to the override registry. | |
| 844 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 845 kRegValueProductVersion, | |
| 846 kFutureVersionString)); | |
| 847 | |
| 848 CString dll_path = ConcatenatePath(future_version_path_, kOmahaDllName); | |
| 849 ASSERT_SUCCEEDED(File::Remove(dll_path)); | |
| 850 ASSERT_FALSE(File::Exists(dll_path)); | |
| 851 | |
| 852 EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), | |
| 853 setup_->Install(false)); | |
| 854 EXPECT_EQ(0, setup_->extra_code1()); | |
| 855 | |
| 856 RestoreRegistryHives(); | |
| 857 ASSERT_SUCCEEDED(RegKey::DeleteKey(kRegistryHiveOverrideRoot, true)); | |
| 858 } | |
| 859 | |
| 860 // Command line must be valid to avoid displaying invalid command line error. | |
| 861 TEST_F(SetupFutureVersionInstalledUserTest, Install_ValidRunKey) { | |
| 862 RegKey::DeleteKey(kRegistryHiveOverrideRoot, true); | |
| 863 OverrideSpecifiedRegistryHives(kRegistryHiveOverrideRoot, false, true); | |
| 864 | |
| 865 // Write the future version to the override registry. | |
| 866 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 867 kRegValueProductVersion, | |
| 868 kFutureVersionString)); | |
| 869 | |
| 870 const TCHAR kRunKey[] = | |
| 871 _T("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"); | |
| 872 const CString shell_path = ConcatenatePath(omaha_path_, kOmahaShellFileName); | |
| 873 CString run_value; | |
| 874 run_value.Format(_T("\"%s\" /cr"), shell_path); | |
| 875 ASSERT_SUCCEEDED(RegKey::SetValue(kRunKey, _T("Google Update"), run_value)); | |
| 876 | |
| 877 CString dll_path = ConcatenatePath(future_version_path_, kOmahaDllName); | |
| 878 ASSERT_SUCCEEDED(File::Remove(dll_path)); | |
| 879 ASSERT_FALSE(File::Exists(dll_path)); | |
| 880 | |
| 881 EXPECT_SUCCEEDED(setup_->Install(false)); | |
| 882 EXPECT_EQ(0, setup_->extra_code1()); | |
| 883 | |
| 884 RestoreRegistryHives(); | |
| 885 ASSERT_SUCCEEDED(RegKey::DeleteKey(kRegistryHiveOverrideRoot, true)); | |
| 886 } | |
| 887 | |
| 888 TEST_F(SetupUserTest, Install_LockTimedOut) { | |
| 889 TestInstallWhileHoldingLock(); | |
| 890 } | |
| 891 | |
| 892 TEST_F(SetupMachineTest, Install_LockTimedOut) { | |
| 893 if (!vista_util::IsUserAdmin()) { | |
| 894 std::wcout << _T("\tTest did not run because the user is not an admin.") | |
| 895 << std::endl; | |
| 896 return; | |
| 897 } | |
| 898 | |
| 899 TestInstallWhileHoldingLock(); | |
| 900 } | |
| 901 | |
| 902 // | |
| 903 // ShouldInstall tests. | |
| 904 // | |
| 905 | |
| 906 TEST_F(SetupRegistryProtectedUserTest, ShouldInstall_NewerVersion) { | |
| 907 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 908 kRegValueProductVersion, | |
| 909 _T("1.0.3.4"))); | |
| 910 EXPECT_TRUE(ShouldInstall()); | |
| 911 } | |
| 912 | |
| 913 TEST_F(SetupRegistryProtectedUserTest, ShouldInstall_OlderVersion) { | |
| 914 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 915 kRegValueProductVersion, | |
| 916 _T("9.8.7.6"))); | |
| 917 EXPECT_FALSE(ShouldInstall()); | |
| 918 } | |
| 919 | |
| 920 TEST_F(SetupRegistryProtectedUserTest, | |
| 921 ShouldInstall_SameVersionFilesMissingSameLanguage) { | |
| 922 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE, | |
| 923 kRegValueInstalledVersion, | |
| 924 this_version_)); | |
| 925 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 926 kRegValueProductVersion, | |
| 927 this_version_)); | |
| 928 ASSERT_SUCCEEDED( | |
| 929 DeleteDirectory(ConcatenatePath(omaha_path_, this_version_))); | |
| 930 CString file_path = ConcatenatePath( | |
| 931 ConcatenatePath(omaha_path_, this_version_), | |
| 932 kOmahaDllName); | |
| 933 ASSERT_FALSE(File::Exists(file_path)); | |
| 934 | |
| 935 EXPECT_TRUE(ShouldInstall()); | |
| 936 } | |
| 937 | |
| 938 TEST_F(SetupRegistryProtectedUserTest, | |
| 939 ShouldInstall_SameVersionFilesPresentSameLanguage) { | |
| 940 if (!ShouldRunLargeTest()) { | |
| 941 return; | |
| 942 } | |
| 943 | |
| 944 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE, | |
| 945 kRegValueInstalledVersion, | |
| 946 this_version_)); | |
| 947 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 948 kRegValueProductVersion, | |
| 949 this_version_)); | |
| 950 | |
| 951 CopyGoopdateFiles(omaha_path_, this_version_); | |
| 952 | |
| 953 EXPECT_EQ(expected_is_overinstall_, ShouldInstall()); | |
| 954 | |
| 955 // Override OverInstall to test official behavior on non-official builds. | |
| 956 | |
| 957 DWORD existing_overinstall(0); | |
| 958 bool had_existing_overinstall = SUCCEEDED(RegKey::GetValue( | |
| 959 MACHINE_REG_UPDATE_DEV, | |
| 960 kRegValueNameOverInstall, | |
| 961 &existing_overinstall)); | |
| 962 | |
| 963 EXPECT_SUCCEEDED(RegKey::SetValue(MACHINE_REG_UPDATE_DEV, | |
| 964 kRegValueNameOverInstall, | |
| 965 static_cast<DWORD>(0))); | |
| 966 #ifdef DEBUG | |
| 967 EXPECT_FALSE(ShouldInstall()); | |
| 968 #else | |
| 969 EXPECT_EQ(expected_is_overinstall_, ShouldInstall()); | |
| 970 #endif | |
| 971 | |
| 972 // Restore "overinstall" | |
| 973 if (had_existing_overinstall) { | |
| 974 EXPECT_SUCCEEDED(RegKey::SetValue(MACHINE_REG_UPDATE_DEV, | |
| 975 kRegValueNameOverInstall, | |
| 976 existing_overinstall)); | |
| 977 } else { | |
| 978 EXPECT_SUCCEEDED(RegKey::DeleteValue(MACHINE_REG_UPDATE_DEV, | |
| 979 kRegValueNameOverInstall)); | |
| 980 } | |
| 981 } | |
| 982 | |
| 983 TEST_F(SetupRegistryProtectedUserTest, | |
| 984 ShouldInstall_SameVersionFilesPresentSameLanguageMissingInstalledVer) { | |
| 985 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 986 kRegValueProductVersion, | |
| 987 this_version_)); | |
| 988 | |
| 989 CopyGoopdateFiles(omaha_path_, this_version_); | |
| 990 | |
| 991 EXPECT_TRUE(ShouldInstall()); | |
| 992 } | |
| 993 | |
| 994 TEST_F(SetupRegistryProtectedUserTest, | |
| 995 ShouldInstall_SameVersionFilesPresentSameLanguageNewerInstalledVer) { | |
| 996 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE, | |
| 997 kRegValueInstalledVersion, | |
| 998 kRegValueInstalledVersion)); | |
| 999 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 1000 kRegValueProductVersion, | |
| 1001 this_version_)); | |
| 1002 | |
| 1003 CopyGoopdateFiles(omaha_path_, this_version_); | |
| 1004 | |
| 1005 EXPECT_TRUE(ShouldInstall()); | |
| 1006 } | |
| 1007 | |
| 1008 TEST_F(SetupRegistryProtectedUserTest, | |
| 1009 ShouldInstall_SameVersionFilesPresentDifferentLanguage) { | |
| 1010 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE, | |
| 1011 kRegValueInstalledVersion, | |
| 1012 this_version_)); | |
| 1013 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 1014 kRegValueProductVersion, | |
| 1015 this_version_)); | |
| 1016 | |
| 1017 CopyGoopdateFiles(omaha_path_, this_version_); | |
| 1018 | |
| 1019 EXPECT_EQ(expected_is_overinstall_, ShouldInstall()); | |
| 1020 } | |
| 1021 | |
| 1022 TEST_F(SetupRegistryProtectedUserTest, | |
| 1023 ShouldInstall_SameVersionFilesPresentNoLanguage) { | |
| 1024 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE, | |
| 1025 kRegValueInstalledVersion, | |
| 1026 this_version_)); | |
| 1027 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 1028 kRegValueProductVersion, | |
| 1029 this_version_)); | |
| 1030 | |
| 1031 CopyGoopdateFiles(omaha_path_, this_version_); | |
| 1032 | |
| 1033 EXPECT_EQ(expected_is_overinstall_, ShouldInstall()); | |
| 1034 } | |
| 1035 | |
| 1036 TEST_F(SetupRegistryProtectedUserTest, | |
| 1037 ShouldInstall_SameVersionRequiredFileMissing) { | |
| 1038 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE, | |
| 1039 kRegValueInstalledVersion, | |
| 1040 this_version_)); | |
| 1041 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 1042 kRegValueProductVersion, | |
| 1043 this_version_)); | |
| 1044 | |
| 1045 CopyGoopdateFiles(omaha_path_, this_version_); | |
| 1046 CString path = ConcatenatePath(ConcatenatePath(omaha_path_, this_version_), | |
| 1047 kOmahaDllName); | |
| 1048 ASSERT_SUCCEEDED(File::Remove(path)); | |
| 1049 ASSERT_FALSE(File::Exists(path)); | |
| 1050 | |
| 1051 EXPECT_TRUE(ShouldInstall()); | |
| 1052 } | |
| 1053 | |
| 1054 TEST_F(SetupRegistryProtectedUserTest, | |
| 1055 ShouldInstall_SameVersionOptionalFileMissing) { | |
| 1056 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE, | |
| 1057 kRegValueInstalledVersion, | |
| 1058 this_version_)); | |
| 1059 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 1060 kRegValueProductVersion, | |
| 1061 this_version_)); | |
| 1062 | |
| 1063 CopyGoopdateFiles(omaha_path_, this_version_); | |
| 1064 CString path = ConcatenatePath(ConcatenatePath(omaha_path_, this_version_), | |
| 1065 UPDATE_PLUGIN_FILENAME); | |
| 1066 ASSERT_SUCCEEDED(File::Remove(path)); | |
| 1067 ASSERT_FALSE(File::Exists(path)); | |
| 1068 | |
| 1069 DWORD existing_overinstall(0); | |
| 1070 bool had_existing_overinstall = SUCCEEDED(RegKey::GetValue( | |
| 1071 MACHINE_REG_UPDATE_DEV, | |
| 1072 kRegValueNameOverInstall, | |
| 1073 &existing_overinstall)); | |
| 1074 if (had_existing_overinstall) { | |
| 1075 EXPECT_SUCCEEDED(RegKey::DeleteValue(MACHINE_REG_UPDATE_DEV, | |
| 1076 kRegValueNameOverInstall)); | |
| 1077 } | |
| 1078 | |
| 1079 EXPECT_TRUE(ShouldInstall()); | |
| 1080 | |
| 1081 // Restore "overinstall" | |
| 1082 if (had_existing_overinstall) { | |
| 1083 EXPECT_SUCCEEDED(RegKey::SetValue(MACHINE_REG_UPDATE_DEV, | |
| 1084 kRegValueNameOverInstall, | |
| 1085 existing_overinstall)); | |
| 1086 } | |
| 1087 } | |
| 1088 | |
| 1089 TEST_F(SetupRegistryProtectedUserTest, ShouldInstall_SameVersionShellMissing) { | |
| 1090 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE, | |
| 1091 kRegValueInstalledVersion, | |
| 1092 this_version_)); | |
| 1093 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 1094 kRegValueProductVersion, | |
| 1095 this_version_)); | |
| 1096 | |
| 1097 CopyGoopdateFiles(omaha_path_, this_version_); | |
| 1098 CString shell_path = ConcatenatePath(omaha_path_, kOmahaShellFileName); | |
| 1099 ASSERT_TRUE(SUCCEEDED(File::DeleteAfterReboot(shell_path)) || | |
| 1100 !vista_util::IsUserAdmin()); | |
| 1101 ASSERT_FALSE(File::Exists(shell_path)); | |
| 1102 | |
| 1103 EXPECT_TRUE(ShouldInstall()); | |
| 1104 } | |
| 1105 | |
| 1106 TEST_F(SetupRegistryProtectedUserTest, ShouldInstall_NewerVersionShellMissing) { | |
| 1107 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE, | |
| 1108 kRegValueInstalledVersion, | |
| 1109 this_version_)); | |
| 1110 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
| 1111 kRegValueProductVersion, | |
| 1112 kFutureVersionString)); | |
| 1113 | |
| 1114 CopyGoopdateFiles(omaha_path_, kFutureVersionString); | |
| 1115 CString shell_path = ConcatenatePath(omaha_path_, kOmahaShellFileName); | |
| 1116 ASSERT_TRUE(SUCCEEDED(File::DeleteAfterReboot(shell_path)) || | |
| 1117 !vista_util::IsUserAdmin()); | |
| 1118 ASSERT_FALSE(File::Exists(shell_path)); | |
| 1119 | |
| 1120 EXPECT_FALSE(ShouldInstall()); | |
| 1121 | |
| 1122 EXPECT_SUCCEEDED( | |
| 1123 DeleteDirectory(ConcatenatePath(omaha_path_, kFutureVersionString))); | |
| 1124 } | |
| 1125 | |
| 1126 // | |
| 1127 // ShouldDelayUninstall/SetDelayUninstall tests. | |
| 1128 // | |
| 1129 | |
| 1130 TEST_F(SetupRegistryProtectedUserTest, ShouldDelayUninstall) { | |
| 1131 TestShouldDelayUninstall(); | |
| 1132 } | |
| 1133 | |
| 1134 TEST_F(SetupRegistryProtectedUserTest, SetDelayUninstall) { | |
| 1135 TestSetDelayUninstall(); | |
| 1136 } | |
| 1137 | |
| 1138 TEST_F(SetupRegistryProtectedMachineTest, ShouldDelayUninstall) { | |
| 1139 TestShouldDelayUninstall(); | |
| 1140 } | |
| 1141 | |
| 1142 TEST_F(SetupRegistryProtectedMachineTest, SetDelayUninstall) { | |
| 1143 TestSetDelayUninstall(); | |
| 1144 } | |
| 1145 | |
| 1146 // | |
| 1147 // StopGoogleUpdateAndWait tests. | |
| 1148 // | |
| 1149 // These are "large" tests. | |
| 1150 // They kill currently running GoogleUpdate processes, including the core, owned | |
| 1151 // by the current user or SYSTEM. | |
| 1152 // A core may already be running, so if a core process is found, it is used for | |
| 1153 // the tests. Otherwise, they launch a core from a previous build. | |
| 1154 // Using a previous build ensures that the shutdown event hasn't changed. | |
| 1155 // There is no test directly that this version can shutdown itself, but that is | |
| 1156 // much less likely to break. | |
| 1157 // The Succeeds tests will fail if any processes that don't listen to the | |
| 1158 // shutdown event are running. | |
| 1159 // | |
| 1160 | |
| 1161 // TODO(omaha3): Make these tests pass. | |
| 1162 TEST_F(SetupUserTest, DISABLED_StopGoogleUpdateAndWait_Succeeds) { | |
| 1163 StopGoogleUpdateAndWaitSucceedsTest(); | |
| 1164 } | |
| 1165 | |
| 1166 TEST_F(SetupMachineTest, DISABLED_StopGoogleUpdateAndWait_Succeeds) { | |
| 1167 StopGoogleUpdateAndWaitSucceedsTest(); | |
| 1168 } | |
| 1169 | |
| 1170 // TODO(omaha): If start using Job Objects again, enable these tests. | |
| 1171 /* | |
| 1172 TEST_F(SetupUserTest, StopGoogleUpdateAndWait_SucceedsUsingOnlyJobObjects) { | |
| 1173 StopGoogleUpdateAndWaitWithProcessSearchDisabledSucceedsTest(); | |
| 1174 } | |
| 1175 | |
| 1176 TEST_F(SetupMachineTest, StopGoogleUpdateAndWait_SucceedsUsingOnlyJobObjects) { | |
| 1177 StopGoogleUpdateAndWaitWithProcessSearchDisabledSucceedsTest(); | |
| 1178 } | |
| 1179 */ | |
| 1180 | |
| 1181 TEST_F(SetupUserTest, StopGoogleUpdateAndWait_ProcessesDoNotStop) { | |
| 1182 StopGoogleUpdateAndWaitProcessesDoNotStopTest(); | |
| 1183 } | |
| 1184 | |
| 1185 TEST_F(SetupMachineTest, StopGoogleUpdateAndWait_ProcessesDoNotStop) { | |
| 1186 StopGoogleUpdateAndWaitProcessesDoNotStopTest(); | |
| 1187 } | |
| 1188 | |
| 1189 TEST_F(SetupMachineTest, | |
| 1190 StopGoogleUpdateAndWait_MachineHandoffWorkerRunningAsUser) { | |
| 1191 LaunchProcessAndExpectStopGoogleUpdateAndWaitKillsProcess( | |
| 1192 false, | |
| 1193 _T("/handoff \"needsadmin=True\"")); | |
| 1194 } | |
| 1195 | |
| 1196 // Process mode is unknown because Omaha 3 does not recognize IG. | |
| 1197 TEST_F(SetupMachineTest, | |
| 1198 StopGoogleUpdateAndWait_MachineLegacyInstallGoogleUpdateWorkerRunningAsUs
er) { // NOLINT | |
| 1199 LaunchProcessAndExpectStopGoogleUpdateAndWaitKillsProcess( | |
| 1200 false, | |
| 1201 _T("/ig \"needsadmin=True\"")); | |
| 1202 } | |
| 1203 | |
| 1204 TEST_F(SetupMachineTest, | |
| 1205 StopGoogleUpdateAndWait_UserHandoffWorkerRunningAsSystem) { | |
| 1206 LaunchProcessAndExpectStopGoogleUpdateAndWaitKillsProcess( | |
| 1207 true, | |
| 1208 _T("/handoff \"needsadmin=False\"")); | |
| 1209 } | |
| 1210 | |
| 1211 // Process mode is unknown because Omaha 3 does not recognize IG. | |
| 1212 TEST_F(SetupMachineTest, | |
| 1213 StopGoogleUpdateAndWait_UserLegacyInstallGoogleUpdateWorkerRunningAsSyste
m) { // NOLINT | |
| 1214 LaunchProcessAndExpectStopGoogleUpdateAndWaitKillsProcess( | |
| 1215 true, | |
| 1216 _T("/ig \"needsadmin=False\"")); | |
| 1217 } | |
| 1218 | |
| 1219 TEST_F(SetupUserTest, TerminateCoreProcesses_NoneRunning) { | |
| 1220 KillRunningCoreProcesses(); | |
| 1221 | |
| 1222 EXPECT_SUCCEEDED(TerminateCoreProcesses()); | |
| 1223 } | |
| 1224 | |
| 1225 TEST_F(SetupUserTest, | |
| 1226 TerminateCoreProcesses_BothTypesRunningAndSimilarArgsProcess) { | |
| 1227 TestTerminateCoreProcessesWithBothTypesRunningAndOtherProcesses(); | |
| 1228 } | |
| 1229 | |
| 1230 TEST_F(SetupMachineTest, TerminateCoreProcesses_NoneRunning) { | |
| 1231 KillRunningCoreProcesses(); | |
| 1232 | |
| 1233 EXPECT_SUCCEEDED(TerminateCoreProcesses()); | |
| 1234 } | |
| 1235 | |
| 1236 TEST_F(SetupMachineTest, | |
| 1237 TerminateCoreProcesses_BothTypesRunningAndSimilarArgsProcess) { | |
| 1238 if (!vista_util::IsUserAdmin()) { | |
| 1239 std::wcout << _T("\tTest did not run because the user is not an admin.") | |
| 1240 << std::endl; | |
| 1241 return; | |
| 1242 } | |
| 1243 TestTerminateCoreProcessesWithBothTypesRunningAndOtherProcesses(); | |
| 1244 } | |
| 1245 | |
| 1246 } // namespace omaha | |
| OLD | NEW |