1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/updater/win/test/test_executables.h"
6 
7 #include <memory>
8 
9 #include "base/base_paths.h"
10 #include "base/command_line.h"
11 #include "base/logging.h"
12 #include "base/path_service.h"
13 #include "base/process/launch.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/win/win_util.h"
17 #include "chrome/updater/constants.h"
18 #include "chrome/updater/win/test/test_inheritable_event.h"
19 #include "chrome/updater/win/test/test_strings.h"
20 
21 namespace updater {
22 
23 // If you add another test executable here, also add it to the data_deps in
24 // the "test_executables" target of updater/win/test/BUILD.gn.
25 const base::char16 kTestProcessExecutableName[] = L"updater_test_process.exe";
26 
LongRunningProcess(base::CommandLine * cmd)27 base::Process LongRunningProcess(base::CommandLine* cmd) {
28   base::FilePath exe_dir;
29   if (!base::PathService::Get(base::DIR_EXE, &exe_dir)) {
30     LOG(ERROR) << "Failed to get the executable path, unable to create always "
31                   "running process";
32     return base::Process();
33   }
34 
35   base::FilePath exe_path = exe_dir.Append(updater::kTestProcessExecutableName);
36   base::CommandLine command_line(exe_path);
37 
38   // This will ensure this new process will run for one minute before dying.
39   command_line.AppendSwitchASCII(updater::kTestSleepMinutesSwitch, "1");
40 
41   auto init_done_event = updater::CreateInheritableEvent(
42       base::WaitableEvent::ResetPolicy::AUTOMATIC,
43       base::WaitableEvent::InitialState::NOT_SIGNALED);
44   command_line.AppendSwitchNative(
45       updater::kInitDoneNotifierSwitch,
46       base::NumberToString16(
47           base::win::HandleToUint32(init_done_event->handle())));
48 
49   if (cmd)
50     *cmd = command_line;
51 
52   base::LaunchOptions launch_options;
53   launch_options.handles_to_inherit.push_back(init_done_event->handle());
54   base::Process result = base::LaunchProcess(command_line, launch_options);
55 
56   if (!init_done_event->TimedWait(base::TimeDelta::FromSeconds(10))) {
57     LOG(ERROR) << "Process did not signal";
58     result.Terminate(/*exit_code=*/1, /*wait=*/false);
59     return base::Process();
60   }
61 
62   return result;
63 }
64 
65 }  // namespace updater
66