xref: /aosp_15_r20/system/update_engine/common/subprocess_unittest.cc (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
1*5a923131SAndroid Build Coastguard Worker //
2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2012 The Android Open Source Project
3*5a923131SAndroid Build Coastguard Worker //
4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*5a923131SAndroid Build Coastguard Worker //
8*5a923131SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*5a923131SAndroid Build Coastguard Worker //
10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*5a923131SAndroid Build Coastguard Worker // limitations under the License.
15*5a923131SAndroid Build Coastguard Worker //
16*5a923131SAndroid Build Coastguard Worker 
17*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/subprocess.h"
18*5a923131SAndroid Build Coastguard Worker 
19*5a923131SAndroid Build Coastguard Worker #include <fcntl.h>
20*5a923131SAndroid Build Coastguard Worker #include <poll.h>
21*5a923131SAndroid Build Coastguard Worker #include <sys/types.h>
22*5a923131SAndroid Build Coastguard Worker #include <unistd.h>
23*5a923131SAndroid Build Coastguard Worker 
24*5a923131SAndroid Build Coastguard Worker #include <set>
25*5a923131SAndroid Build Coastguard Worker #include <string>
26*5a923131SAndroid Build Coastguard Worker #include <vector>
27*5a923131SAndroid Build Coastguard Worker 
28*5a923131SAndroid Build Coastguard Worker #include <base/bind.h>
29*5a923131SAndroid Build Coastguard Worker #include <base/files/scoped_temp_dir.h>
30*5a923131SAndroid Build Coastguard Worker #include <base/location.h>
31*5a923131SAndroid Build Coastguard Worker #if BASE_VER < 780000  // Android
32*5a923131SAndroid Build Coastguard Worker #include <base/message_loop/message_loop.h>
33*5a923131SAndroid Build Coastguard Worker #endif  // BASE_VER < 780000
34*5a923131SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
35*5a923131SAndroid Build Coastguard Worker #if BASE_VER >= 780000  // Chrome OS
36*5a923131SAndroid Build Coastguard Worker #include <base/task/single_thread_task_executor.h>
37*5a923131SAndroid Build Coastguard Worker #endif  // BASE_VER >= 780000
38*5a923131SAndroid Build Coastguard Worker #include <base/time/time.h>
39*5a923131SAndroid Build Coastguard Worker #include <brillo/message_loops/base_message_loop.h>
40*5a923131SAndroid Build Coastguard Worker #include <brillo/message_loops/message_loop.h>
41*5a923131SAndroid Build Coastguard Worker #include <brillo/message_loops/message_loop_utils.h>
42*5a923131SAndroid Build Coastguard Worker #include <brillo/strings/string_utils.h>
43*5a923131SAndroid Build Coastguard Worker #include <brillo/unittest_utils.h>
44*5a923131SAndroid Build Coastguard Worker #include <gtest/gtest.h>
45*5a923131SAndroid Build Coastguard Worker 
46*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/test_utils.h"
47*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/utils.h"
48*5a923131SAndroid Build Coastguard Worker 
49*5a923131SAndroid Build Coastguard Worker using base::TimeDelta;
50*5a923131SAndroid Build Coastguard Worker using brillo::MessageLoop;
51*5a923131SAndroid Build Coastguard Worker using std::string;
52*5a923131SAndroid Build Coastguard Worker using std::unique_ptr;
53*5a923131SAndroid Build Coastguard Worker using std::vector;
54*5a923131SAndroid Build Coastguard Worker 
55*5a923131SAndroid Build Coastguard Worker namespace {
56*5a923131SAndroid Build Coastguard Worker 
57*5a923131SAndroid Build Coastguard Worker #ifdef __ANDROID__
58*5a923131SAndroid Build Coastguard Worker #define kBinPath "/system/bin"
59*5a923131SAndroid Build Coastguard Worker #define kUsrBinPath "/system/bin"
60*5a923131SAndroid Build Coastguard Worker #else
61*5a923131SAndroid Build Coastguard Worker #define kBinPath "/bin"
62*5a923131SAndroid Build Coastguard Worker #define kUsrBinPath "/usr/bin"
63*5a923131SAndroid Build Coastguard Worker #endif  // __ANDROID__
64*5a923131SAndroid Build Coastguard Worker 
65*5a923131SAndroid Build Coastguard Worker }  // namespace
66*5a923131SAndroid Build Coastguard Worker 
67*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine {
68*5a923131SAndroid Build Coastguard Worker 
69*5a923131SAndroid Build Coastguard Worker class SubprocessTest : public ::testing::Test {
70*5a923131SAndroid Build Coastguard Worker  protected:
SetUp()71*5a923131SAndroid Build Coastguard Worker   void SetUp() override {
72*5a923131SAndroid Build Coastguard Worker     loop_.SetAsCurrent();
73*5a923131SAndroid Build Coastguard Worker     async_signal_handler_.Init();
74*5a923131SAndroid Build Coastguard Worker     subprocess_.Init(&async_signal_handler_);
75*5a923131SAndroid Build Coastguard Worker   }
76*5a923131SAndroid Build Coastguard Worker 
77*5a923131SAndroid Build Coastguard Worker #if BASE_VER < 780000  // Android
78*5a923131SAndroid Build Coastguard Worker   base::MessageLoopForIO base_loop_;
79*5a923131SAndroid Build Coastguard Worker   brillo::BaseMessageLoop loop_{&base_loop_};
80*5a923131SAndroid Build Coastguard Worker #else   // Chrome OS
81*5a923131SAndroid Build Coastguard Worker   base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
82*5a923131SAndroid Build Coastguard Worker   brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
83*5a923131SAndroid Build Coastguard Worker #endif  // BASE_VER < 780000
84*5a923131SAndroid Build Coastguard Worker   brillo::AsynchronousSignalHandler async_signal_handler_;
85*5a923131SAndroid Build Coastguard Worker   Subprocess subprocess_;
86*5a923131SAndroid Build Coastguard Worker   unique_ptr<base::FileDescriptorWatcher::Controller> watcher_;
87*5a923131SAndroid Build Coastguard Worker };
88*5a923131SAndroid Build Coastguard Worker 
89*5a923131SAndroid Build Coastguard Worker namespace {
90*5a923131SAndroid Build Coastguard Worker 
ExpectedResults(int expected_return_code,const string & expected_output,int return_code,const string & output)91*5a923131SAndroid Build Coastguard Worker void ExpectedResults(int expected_return_code,
92*5a923131SAndroid Build Coastguard Worker                      const string& expected_output,
93*5a923131SAndroid Build Coastguard Worker                      int return_code,
94*5a923131SAndroid Build Coastguard Worker                      const string& output) {
95*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(expected_return_code, return_code);
96*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(expected_output, output);
97*5a923131SAndroid Build Coastguard Worker   MessageLoop::current()->BreakLoop();
98*5a923131SAndroid Build Coastguard Worker }
99*5a923131SAndroid Build Coastguard Worker 
ExpectedEnvVars(int return_code,const string & output)100*5a923131SAndroid Build Coastguard Worker void ExpectedEnvVars(int return_code, const string& output) {
101*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, return_code);
102*5a923131SAndroid Build Coastguard Worker   const std::set<string> allowed_envs = {"LD_LIBRARY_PATH", "PATH"};
103*5a923131SAndroid Build Coastguard Worker   for (const string& key_value : brillo::string_utils::Split(output, "\n")) {
104*5a923131SAndroid Build Coastguard Worker     auto key_value_pair =
105*5a923131SAndroid Build Coastguard Worker         brillo::string_utils::SplitAtFirst(key_value, "=", true);
106*5a923131SAndroid Build Coastguard Worker     EXPECT_NE(allowed_envs.end(), allowed_envs.find(key_value_pair.first));
107*5a923131SAndroid Build Coastguard Worker   }
108*5a923131SAndroid Build Coastguard Worker   MessageLoop::current()->BreakLoop();
109*5a923131SAndroid Build Coastguard Worker }
110*5a923131SAndroid Build Coastguard Worker 
ExpectedDataOnPipe(const Subprocess * subprocess,pid_t * pid,int child_fd,const string & child_fd_data,int expected_return_code,int return_code,const string &)111*5a923131SAndroid Build Coastguard Worker void ExpectedDataOnPipe(const Subprocess* subprocess,
112*5a923131SAndroid Build Coastguard Worker                         pid_t* pid,
113*5a923131SAndroid Build Coastguard Worker                         int child_fd,
114*5a923131SAndroid Build Coastguard Worker                         const string& child_fd_data,
115*5a923131SAndroid Build Coastguard Worker                         int expected_return_code,
116*5a923131SAndroid Build Coastguard Worker                         int return_code,
117*5a923131SAndroid Build Coastguard Worker                         const string& /* output */) {
118*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(expected_return_code, return_code);
119*5a923131SAndroid Build Coastguard Worker 
120*5a923131SAndroid Build Coastguard Worker   // Verify that we can read the data from our end of |child_fd|.
121*5a923131SAndroid Build Coastguard Worker   int fd = subprocess->GetPipeFd(*pid, child_fd);
122*5a923131SAndroid Build Coastguard Worker   EXPECT_NE(-1, fd);
123*5a923131SAndroid Build Coastguard Worker   vector<char> buf(child_fd_data.size() + 1);
124*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<ssize_t>(child_fd_data.size()),
125*5a923131SAndroid Build Coastguard Worker             HANDLE_EINTR(read(fd, buf.data(), buf.size())));
126*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(child_fd_data,
127*5a923131SAndroid Build Coastguard Worker             string(buf.begin(), buf.begin() + child_fd_data.size()));
128*5a923131SAndroid Build Coastguard Worker 
129*5a923131SAndroid Build Coastguard Worker   MessageLoop::current()->BreakLoop();
130*5a923131SAndroid Build Coastguard Worker }
131*5a923131SAndroid Build Coastguard Worker 
132*5a923131SAndroid Build Coastguard Worker }  // namespace
133*5a923131SAndroid Build Coastguard Worker 
TEST_F(SubprocessTest,IsASingleton)134*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, IsASingleton) {
135*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(&subprocess_, &Subprocess::Get());
136*5a923131SAndroid Build Coastguard Worker }
137*5a923131SAndroid Build Coastguard Worker 
TEST_F(SubprocessTest,InactiveInstancesDontChangeTheSingleton)138*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, InactiveInstancesDontChangeTheSingleton) {
139*5a923131SAndroid Build Coastguard Worker   std::unique_ptr<Subprocess> another_subprocess(new Subprocess());
140*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(&subprocess_, &Subprocess::Get());
141*5a923131SAndroid Build Coastguard Worker   another_subprocess.reset();
142*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(&subprocess_, &Subprocess::Get());
143*5a923131SAndroid Build Coastguard Worker }
144*5a923131SAndroid Build Coastguard Worker 
TEST_F(SubprocessTest,SimpleTest)145*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, SimpleTest) {
146*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(subprocess_.Exec({kBinPath "/false"},
147*5a923131SAndroid Build Coastguard Worker                                base::Bind(&ExpectedResults, 1, "")));
148*5a923131SAndroid Build Coastguard Worker   loop_.Run();
149*5a923131SAndroid Build Coastguard Worker }
150*5a923131SAndroid Build Coastguard Worker 
TEST_F(SubprocessTest,EchoTest)151*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, EchoTest) {
152*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(subprocess_.Exec(
153*5a923131SAndroid Build Coastguard Worker       {kBinPath "/sh", "-c", "echo this is stdout; echo this is stderr >&2"},
154*5a923131SAndroid Build Coastguard Worker       base::Bind(&ExpectedResults, 0, "this is stdout\nthis is stderr\n")));
155*5a923131SAndroid Build Coastguard Worker   loop_.Run();
156*5a923131SAndroid Build Coastguard Worker }
157*5a923131SAndroid Build Coastguard Worker 
TEST_F(SubprocessTest,StderrNotIncludedInOutputTest)158*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, StderrNotIncludedInOutputTest) {
159*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(subprocess_.ExecFlags(
160*5a923131SAndroid Build Coastguard Worker       {kBinPath "/sh", "-c", "echo on stdout; echo on stderr >&2"},
161*5a923131SAndroid Build Coastguard Worker       0,
162*5a923131SAndroid Build Coastguard Worker       {},
163*5a923131SAndroid Build Coastguard Worker       base::Bind(&ExpectedResults, 0, "on stdout\n")));
164*5a923131SAndroid Build Coastguard Worker   loop_.Run();
165*5a923131SAndroid Build Coastguard Worker }
166*5a923131SAndroid Build Coastguard Worker 
TEST_F(SubprocessTest,PipeRedirectFdTest)167*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, PipeRedirectFdTest) {
168*5a923131SAndroid Build Coastguard Worker   pid_t pid;
169*5a923131SAndroid Build Coastguard Worker   pid = subprocess_.ExecFlags(
170*5a923131SAndroid Build Coastguard Worker       {kBinPath "/sh", "-c", "echo on pipe >&3"},
171*5a923131SAndroid Build Coastguard Worker       0,
172*5a923131SAndroid Build Coastguard Worker       {3},
173*5a923131SAndroid Build Coastguard Worker       base::Bind(&ExpectedDataOnPipe, &subprocess_, &pid, 3, "on pipe\n", 0));
174*5a923131SAndroid Build Coastguard Worker   ASSERT_NE(0, pid);
175*5a923131SAndroid Build Coastguard Worker 
176*5a923131SAndroid Build Coastguard Worker   // Wrong file descriptor values should return -1.
177*5a923131SAndroid Build Coastguard Worker   ASSERT_EQ(-1, subprocess_.GetPipeFd(pid, 123));
178*5a923131SAndroid Build Coastguard Worker   loop_.Run();
179*5a923131SAndroid Build Coastguard Worker   // Calling GetPipeFd() after the callback runs is invalid.
180*5a923131SAndroid Build Coastguard Worker   ASSERT_EQ(-1, subprocess_.GetPipeFd(pid, 3));
181*5a923131SAndroid Build Coastguard Worker }
182*5a923131SAndroid Build Coastguard Worker 
183*5a923131SAndroid Build Coastguard Worker // Test that a pipe file descriptor open in the parent is not open in the child.
TEST_F(SubprocessTest,PipeClosedWhenNotRedirectedTest)184*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, PipeClosedWhenNotRedirectedTest) {
185*5a923131SAndroid Build Coastguard Worker   brillo::ScopedPipe pipe;
186*5a923131SAndroid Build Coastguard Worker 
187*5a923131SAndroid Build Coastguard Worker   // test_subprocess will return with the errno of fstat, which should be EBADF
188*5a923131SAndroid Build Coastguard Worker   // if the passed file descriptor is closed in the child.
189*5a923131SAndroid Build Coastguard Worker   const vector<string> cmd = {
190*5a923131SAndroid Build Coastguard Worker       test_utils::GetBuildArtifactsPath("test_subprocess"),
191*5a923131SAndroid Build Coastguard Worker       "fstat",
192*5a923131SAndroid Build Coastguard Worker       std::to_string(pipe.writer)};
193*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(subprocess_.ExecFlags(
194*5a923131SAndroid Build Coastguard Worker       cmd, 0, {}, base::Bind(&ExpectedResults, EBADF, "")));
195*5a923131SAndroid Build Coastguard Worker   loop_.Run();
196*5a923131SAndroid Build Coastguard Worker }
197*5a923131SAndroid Build Coastguard Worker 
TEST_F(SubprocessTest,EnvVarsAreFiltered)198*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, EnvVarsAreFiltered) {
199*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(
200*5a923131SAndroid Build Coastguard Worker       subprocess_.Exec({kUsrBinPath "/env"}, base::Bind(&ExpectedEnvVars)));
201*5a923131SAndroid Build Coastguard Worker   loop_.Run();
202*5a923131SAndroid Build Coastguard Worker }
203*5a923131SAndroid Build Coastguard Worker 
TEST_F(SubprocessTest,SynchronousTrueSearchsOnPath)204*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, SynchronousTrueSearchsOnPath) {
205*5a923131SAndroid Build Coastguard Worker   int rc = -1;
206*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(Subprocess::SynchronousExecFlags(
207*5a923131SAndroid Build Coastguard Worker       {"true"}, Subprocess::kSearchPath, &rc, nullptr, nullptr));
208*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, rc);
209*5a923131SAndroid Build Coastguard Worker }
210*5a923131SAndroid Build Coastguard Worker 
TEST_F(SubprocessTest,SynchronousEchoTest)211*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, SynchronousEchoTest) {
212*5a923131SAndroid Build Coastguard Worker   vector<string> cmd = {
213*5a923131SAndroid Build Coastguard Worker       kBinPath "/sh", "-c", "echo -n stdout-here; echo -n stderr-there >&2"};
214*5a923131SAndroid Build Coastguard Worker   int rc = -1;
215*5a923131SAndroid Build Coastguard Worker   string stdout, stderr;
216*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(Subprocess::SynchronousExec(cmd, &rc, &stdout, &stderr));
217*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, rc);
218*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ("stdout-here", stdout);
219*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ("stderr-there", stderr);
220*5a923131SAndroid Build Coastguard Worker }
221*5a923131SAndroid Build Coastguard Worker 
TEST_F(SubprocessTest,SynchronousEchoNoOutputTest)222*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, SynchronousEchoNoOutputTest) {
223*5a923131SAndroid Build Coastguard Worker   int rc = -1;
224*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(Subprocess::SynchronousExec(
225*5a923131SAndroid Build Coastguard Worker       {kBinPath "/sh", "-c", "echo test"}, &rc, nullptr, nullptr));
226*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, rc);
227*5a923131SAndroid Build Coastguard Worker }
228*5a923131SAndroid Build Coastguard Worker 
229*5a923131SAndroid Build Coastguard Worker namespace {
CallbackBad(int return_code,const string & output)230*5a923131SAndroid Build Coastguard Worker void CallbackBad(int return_code, const string& output) {
231*5a923131SAndroid Build Coastguard Worker   ADD_FAILURE() << "should never be called.";
232*5a923131SAndroid Build Coastguard Worker }
233*5a923131SAndroid Build Coastguard Worker }  // namespace
234*5a923131SAndroid Build Coastguard Worker 
235*5a923131SAndroid Build Coastguard Worker // Test that you can cancel a program that's already running.
TEST_F(SubprocessTest,CancelTest)236*5a923131SAndroid Build Coastguard Worker TEST_F(SubprocessTest, CancelTest) {
237*5a923131SAndroid Build Coastguard Worker   base::ScopedTempDir tempdir;
238*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(tempdir.CreateUniqueTempDir());
239*5a923131SAndroid Build Coastguard Worker   string fifo_path = tempdir.GetPath().Append("fifo").value();
240*5a923131SAndroid Build Coastguard Worker   ASSERT_EQ(0, mkfifo(fifo_path.c_str(), 0666));
241*5a923131SAndroid Build Coastguard Worker 
242*5a923131SAndroid Build Coastguard Worker   // Start a process, make sure it is running and try to cancel it. We write
243*5a923131SAndroid Build Coastguard Worker   // two bytes to the fifo, the first one marks that the program is running and
244*5a923131SAndroid Build Coastguard Worker   // the second one marks that the process waited for a timeout and was not
245*5a923131SAndroid Build Coastguard Worker   // killed. We should read the first byte but not the second one.
246*5a923131SAndroid Build Coastguard Worker   vector<string> cmd = {
247*5a923131SAndroid Build Coastguard Worker       kBinPath "/sh",
248*5a923131SAndroid Build Coastguard Worker       "-c",
249*5a923131SAndroid Build Coastguard Worker       android::base::StringPrintf(
250*5a923131SAndroid Build Coastguard Worker           // The 'sleep' launched below could be left behind as an orphaned
251*5a923131SAndroid Build Coastguard Worker           // process when the 'sh' process is terminated by SIGTERM. As a
252*5a923131SAndroid Build Coastguard Worker           // remedy, trap SIGTERM and kill the 'sleep' process, which requires
253*5a923131SAndroid Build Coastguard Worker           // launching 'sleep' in background and then waiting for it.
254*5a923131SAndroid Build Coastguard Worker           "cleanup() { kill \"${sleep_pid}\"; exit 0; }; "
255*5a923131SAndroid Build Coastguard Worker           "trap cleanup TERM; "
256*5a923131SAndroid Build Coastguard Worker           "sleep 60 & "
257*5a923131SAndroid Build Coastguard Worker           "sleep_pid=$!; "
258*5a923131SAndroid Build Coastguard Worker           "printf X >\"%s\"; "
259*5a923131SAndroid Build Coastguard Worker           "wait; "
260*5a923131SAndroid Build Coastguard Worker           "printf Y >\"%s\"; "
261*5a923131SAndroid Build Coastguard Worker           "exit 1",
262*5a923131SAndroid Build Coastguard Worker           fifo_path.c_str(),
263*5a923131SAndroid Build Coastguard Worker           fifo_path.c_str())};
264*5a923131SAndroid Build Coastguard Worker   uint32_t tag = Subprocess::Get().Exec(cmd, base::Bind(&CallbackBad));
265*5a923131SAndroid Build Coastguard Worker   ASSERT_NE(0U, tag);
266*5a923131SAndroid Build Coastguard Worker 
267*5a923131SAndroid Build Coastguard Worker   int fifo_fd = HANDLE_EINTR(open(fifo_path.c_str(), O_RDONLY));
268*5a923131SAndroid Build Coastguard Worker   ASSERT_GE(fifo_fd, 0);
269*5a923131SAndroid Build Coastguard Worker 
270*5a923131SAndroid Build Coastguard Worker   watcher_ = base::FileDescriptorWatcher::WatchReadable(
271*5a923131SAndroid Build Coastguard Worker       fifo_fd,
272*5a923131SAndroid Build Coastguard Worker       base::Bind(
273*5a923131SAndroid Build Coastguard Worker           [](brillo::BaseMessageLoop* loop,
274*5a923131SAndroid Build Coastguard Worker              unique_ptr<base::FileDescriptorWatcher::Controller>* watcher,
275*5a923131SAndroid Build Coastguard Worker              int fifo_fd,
276*5a923131SAndroid Build Coastguard Worker              uint32_t tag) {
277*5a923131SAndroid Build Coastguard Worker             char c{};
278*5a923131SAndroid Build Coastguard Worker             EXPECT_EQ(1, HANDLE_EINTR(read(fifo_fd, &c, 1)));
279*5a923131SAndroid Build Coastguard Worker             EXPECT_EQ('X', c);
280*5a923131SAndroid Build Coastguard Worker             LOG(INFO) << "Killing tag " << tag;
281*5a923131SAndroid Build Coastguard Worker             Subprocess::Get().KillExec(tag);
282*5a923131SAndroid Build Coastguard Worker             loop->BreakLoop();
283*5a923131SAndroid Build Coastguard Worker             ASSERT_TRUE(Subprocess::Get().subprocess_records_.empty());
284*5a923131SAndroid Build Coastguard Worker             *watcher = nullptr;
285*5a923131SAndroid Build Coastguard Worker           },
286*5a923131SAndroid Build Coastguard Worker           &loop_,
287*5a923131SAndroid Build Coastguard Worker           // watcher_ is no longer used outside the clousure.
288*5a923131SAndroid Build Coastguard Worker           base::Unretained(&watcher_),
289*5a923131SAndroid Build Coastguard Worker           fifo_fd,
290*5a923131SAndroid Build Coastguard Worker           tag));
291*5a923131SAndroid Build Coastguard Worker 
292*5a923131SAndroid Build Coastguard Worker   // This test would leak a callback that runs when the child process exits
293*5a923131SAndroid Build Coastguard Worker   // unless we wait for it to run.
294*5a923131SAndroid Build Coastguard Worker   brillo::MessageLoopRunUntil(
295*5a923131SAndroid Build Coastguard Worker       &loop_, TimeDelta::FromSeconds(20), base::Bind([] {
296*5a923131SAndroid Build Coastguard Worker         return Subprocess::Get().subprocess_records_.empty();
297*5a923131SAndroid Build Coastguard Worker       }));
298*5a923131SAndroid Build Coastguard Worker   EXPECT_TRUE(Subprocess::Get().subprocess_records_.empty());
299*5a923131SAndroid Build Coastguard Worker   // Check that there isn't anything else to read from the pipe.
300*5a923131SAndroid Build Coastguard Worker   char c;
301*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, HANDLE_EINTR(read(fifo_fd, &c, 1)));
302*5a923131SAndroid Build Coastguard Worker   IGNORE_EINTR(close(fifo_fd));
303*5a923131SAndroid Build Coastguard Worker }
304*5a923131SAndroid Build Coastguard Worker 
305*5a923131SAndroid Build Coastguard Worker }  // namespace chromeos_update_engine
306