1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2012 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
163defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/subprocess.h"
18aab50e31f0b80ed53a9b8d5dbabcf943974bd32cAlex Deymo
195d5278068a007fc090368fba664fe130645880f7Alex Deymo#include <fcntl.h>
20b6c562adec6e9491712f156f8fd50e2b807ff302Gilad Arnold#include <poll.h>
213defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <sys/types.h>
223defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <unistd.h>
238e3f1263218c5046d2281c1d1d3c886acda85b47Gilad Arnold
24461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo#include <set>
253defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <string>
263defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <vector>
278e3f1263218c5046d2281c1d1d3c886acda85b47Gilad Arnold
2860ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo#include <base/bind.h>
29279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo#include <base/files/scoped_temp_dir.h>
3060ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo#include <base/location.h>
310b3db6b6040f53eb9859e614f7fe4c681213d33aAlex Deymo#include <base/message_loop/message_loop.h>
3275039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/string_util.h>
3375039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/stringprintf.h>
3475039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/time/time.h>
353f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/bind_lambda.h>
363f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/message_loops/base_message_loop.h>
373f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/message_loops/message_loop.h>
383f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/message_loops/message_loop_utils.h>
393f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/strings/string_utils.h>
40b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo#include <brillo/unittest_utils.h>
413defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <gtest/gtest.h>
428e3f1263218c5046d2281c1d1d3c886acda85b47Gilad Arnold
4339910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/test_utils.h"
4439910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h"
453defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
468e3f1263218c5046d2281c1d1d3c886acda85b47Gilad Arnoldusing base::TimeDelta;
473f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkousing brillo::MessageLoop;
483defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comusing std::string;
493defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comusing std::vector;
503defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
51279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymonamespace {
52279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo
53279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo#ifdef __ANDROID__
54279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo#define kBinPath "/system/bin"
55279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo#define kUsrBinPath "/system/bin"
56279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo#else
57279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo#define kBinPath "/bin"
58279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo#define kUsrBinPath "/usr/bin"
59279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo#endif  // __ANDROID__
60279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo
61279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo}  // namespace
62279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo
633defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comnamespace chromeos_update_engine {
643defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
653defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comclass SubprocessTest : public ::testing::Test {
663defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com protected:
6760ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  void SetUp() override {
6860ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo    loop_.SetAsCurrent();
69b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo    async_signal_handler_.Init();
70b7ca096f98a43ebbf412f1b2d3d15bb184f871f8Alex Deymo    subprocess_.Init(&async_signal_handler_);
7160ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  }
7260ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo
730b3db6b6040f53eb9859e614f7fe4c681213d33aAlex Deymo  base::MessageLoopForIO base_loop_;
743f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::BaseMessageLoop loop_{&base_loop_};
753f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::AsynchronousSignalHandler async_signal_handler_;
76461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  Subprocess subprocess_;
773defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com};
783defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
793defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comnamespace {
80461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo
81461b259af8815d782200782c5ba3599d8de4a66cAlex Deymovoid ExpectedResults(int expected_return_code, const string& expected_output,
82461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo                     int return_code, const string& output) {
83461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  EXPECT_EQ(expected_return_code, return_code);
84461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  EXPECT_EQ(expected_output, output);
8560ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  MessageLoop::current()->BreakLoop();
863defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}
873defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
88461b259af8815d782200782c5ba3599d8de4a66cAlex Deymovoid ExpectedEnvVars(int return_code, const string& output) {
896f03a3b868d4b632931400628763036f79c449f7Darin Petkov  EXPECT_EQ(0, return_code);
90461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  const std::set<string> allowed_envs = {"LD_LIBRARY_PATH", "PATH"};
913f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  for (string key_value : brillo::string_utils::Split(output, "\n")) {
923f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko    auto key_value_pair = brillo::string_utils::SplitAtFirst(
93461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo        key_value, "=", true);
94461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo    EXPECT_NE(allowed_envs.end(), allowed_envs.find(key_value_pair.first));
95461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  }
9660ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  MessageLoop::current()->BreakLoop();
976f03a3b868d4b632931400628763036f79c449f7Darin Petkov}
986f03a3b868d4b632931400628763036f79c449f7Darin Petkov
99b108b608030bed6677cb86589a9df02a7df181c1Alex Deymovoid ExpectedDataOnPipe(const Subprocess* subprocess,
100b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo                        pid_t* pid,
101b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo                        int child_fd,
102b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo                        const string& child_fd_data,
103b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo                        int expected_return_code,
104b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo                        int return_code,
105b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo                        const string& /* output */) {
106b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  EXPECT_EQ(expected_return_code, return_code);
107b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo
108b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  // Verify that we can read the data from our end of |child_fd|.
109b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  int fd = subprocess->GetPipeFd(*pid, child_fd);
110b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  EXPECT_NE(-1, fd);
111b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  vector<char> buf(child_fd_data.size() + 1);
112b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  EXPECT_EQ(static_cast<ssize_t>(child_fd_data.size()),
113b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo            HANDLE_EINTR(read(fd, buf.data(), buf.size())));
114b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  EXPECT_EQ(child_fd_data,
115b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo            string(buf.begin(), buf.begin() + child_fd_data.size()));
116b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo
117b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  MessageLoop::current()->BreakLoop();
118b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo}
119b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo
120461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo}  // namespace
121461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo
122461b259af8815d782200782c5ba3599d8de4a66cAlex DeymoTEST_F(SubprocessTest, IsASingleton) {
123461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  EXPECT_EQ(&subprocess_, &Subprocess::Get());
12429b815316519829f133b39dd1cae7ab6224c9da2Alex Deymo}
12529b815316519829f133b39dd1cae7ab6224c9da2Alex Deymo
126461b259af8815d782200782c5ba3599d8de4a66cAlex DeymoTEST_F(SubprocessTest, InactiveInstancesDontChangeTheSingleton) {
127461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  std::unique_ptr<Subprocess> another_subprocess(new Subprocess());
128461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  EXPECT_EQ(&subprocess_, &Subprocess::Get());
129461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  another_subprocess.reset();
130461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  EXPECT_EQ(&subprocess_, &Subprocess::Get());
131461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo}
1323defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
13360ca1a7bca7cc804ec80b510483081ef894de4cdAlex DeymoTEST_F(SubprocessTest, SimpleTest) {
134279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  EXPECT_TRUE(subprocess_.Exec({kBinPath "/false"},
135461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo                               base::Bind(&ExpectedResults, 1, "")));
13660ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  loop_.Run();
1373defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}
1383defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
13960ca1a7bca7cc804ec80b510483081ef894de4cdAlex DeymoTEST_F(SubprocessTest, EchoTest) {
140461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  EXPECT_TRUE(subprocess_.Exec(
141279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      {kBinPath "/sh", "-c", "echo this is stdout; echo this is stderr >&2"},
142461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo      base::Bind(&ExpectedResults, 0, "this is stdout\nthis is stderr\n")));
14329b815316519829f133b39dd1cae7ab6224c9da2Alex Deymo  loop_.Run();
14429b815316519829f133b39dd1cae7ab6224c9da2Alex Deymo}
14529b815316519829f133b39dd1cae7ab6224c9da2Alex Deymo
14629b815316519829f133b39dd1cae7ab6224c9da2Alex DeymoTEST_F(SubprocessTest, StderrNotIncludedInOutputTest) {
147461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  EXPECT_TRUE(subprocess_.ExecFlags(
148279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      {kBinPath "/sh", "-c", "echo on stdout; echo on stderr >&2"},
149461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo      0,
150b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo      {},
151461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo      base::Bind(&ExpectedResults, 0, "on stdout\n")));
152461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  loop_.Run();
153461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo}
154461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo
155b108b608030bed6677cb86589a9df02a7df181c1Alex DeymoTEST_F(SubprocessTest, PipeRedirectFdTest) {
156b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  pid_t pid;
157b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  pid = subprocess_.ExecFlags(
158b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo      {kBinPath "/sh", "-c", "echo on pipe >&3"},
159b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo      0,
160b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo      {3},
161b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo      base::Bind(&ExpectedDataOnPipe, &subprocess_, &pid, 3, "on pipe\n", 0));
162b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  EXPECT_NE(0, pid);
163b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo
164b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  // Wrong file descriptor values should return -1.
165b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  EXPECT_EQ(-1, subprocess_.GetPipeFd(pid, 123));
166b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  loop_.Run();
167b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  // Calling GetPipeFd() after the callback runs is invalid.
168b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  EXPECT_EQ(-1, subprocess_.GetPipeFd(pid, 3));
169b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo}
170b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo
171b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo// Test that a pipe file descriptor open in the parent is not open in the child.
172b108b608030bed6677cb86589a9df02a7df181c1Alex DeymoTEST_F(SubprocessTest, PipeClosedWhenNotRedirectedTest) {
173b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  brillo::ScopedPipe pipe;
174b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  const vector<string> cmd = {kBinPath "/sh", "-c",
175b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo     base::StringPrintf("echo on pipe >/proc/self/fd/%d", pipe.writer)};
176b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  EXPECT_TRUE(subprocess_.ExecFlags(
177b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo      cmd,
178b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo      0,
179b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo      {},
180b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo      base::Bind(&ExpectedResults, 1, "")));
181b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo  loop_.Run();
182b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo}
183b108b608030bed6677cb86589a9df02a7df181c1Alex Deymo
184461b259af8815d782200782c5ba3599d8de4a66cAlex DeymoTEST_F(SubprocessTest, EnvVarsAreFiltered) {
185279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  EXPECT_TRUE(
186279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      subprocess_.Exec({kUsrBinPath "/env"}, base::Bind(&ExpectedEnvVars)));
18760ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  loop_.Run();
1886f03a3b868d4b632931400628763036f79c449f7Darin Petkov}
1896f03a3b868d4b632931400628763036f79c449f7Darin Petkov
190461b259af8815d782200782c5ba3599d8de4a66cAlex DeymoTEST_F(SubprocessTest, SynchronousTrueSearchsOnPath) {
191461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  int rc = -1;
192461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  EXPECT_TRUE(Subprocess::SynchronousExecFlags(
193461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo      {"true"}, Subprocess::kSearchPath, &rc, nullptr));
194461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  EXPECT_EQ(0, rc);
195461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo}
196461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo
19760ca1a7bca7cc804ec80b510483081ef894de4cdAlex DeymoTEST_F(SubprocessTest, SynchronousEchoTest) {
19860ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  vector<string> cmd = {
199279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      kBinPath "/sh",
200279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      "-c",
201279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      "echo -n stdout-here; echo -n stderr-there >&2"};
20285d02b7a8593f662818b3fe5f31281c443574654Darin Petkov  int rc = -1;
20385d02b7a8593f662818b3fe5f31281c443574654Darin Petkov  string stdout;
20485d02b7a8593f662818b3fe5f31281c443574654Darin Petkov  ASSERT_TRUE(Subprocess::SynchronousExec(cmd, &rc, &stdout));
20585d02b7a8593f662818b3fe5f31281c443574654Darin Petkov  EXPECT_EQ(0, rc);
20685d02b7a8593f662818b3fe5f31281c443574654Darin Petkov  EXPECT_EQ("stdout-herestderr-there", stdout);
20785d02b7a8593f662818b3fe5f31281c443574654Darin Petkov}
20885d02b7a8593f662818b3fe5f31281c443574654Darin Petkov
20960ca1a7bca7cc804ec80b510483081ef894de4cdAlex DeymoTEST_F(SubprocessTest, SynchronousEchoNoOutputTest) {
21085d02b7a8593f662818b3fe5f31281c443574654Darin Petkov  int rc = -1;
211461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  ASSERT_TRUE(Subprocess::SynchronousExec(
212279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      {kBinPath "/sh", "-c", "echo test"}, &rc, nullptr));
21385d02b7a8593f662818b3fe5f31281c443574654Darin Petkov  EXPECT_EQ(0, rc);
21485d02b7a8593f662818b3fe5f31281c443574654Darin Petkov}
21585d02b7a8593f662818b3fe5f31281c443574654Darin Petkov
2163defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comnamespace {
217461b259af8815d782200782c5ba3599d8de4a66cAlex Deymovoid CallbackBad(int return_code, const string& output) {
218461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  ADD_FAILURE() << "should never be called.";
2193defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}
220279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo}  // namespace
2213defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
222279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo// Test that you can cancel a program that's already running.
223279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex DeymoTEST_F(SubprocessTest, CancelTest) {
224279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  base::ScopedTempDir tempdir;
225279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  ASSERT_TRUE(tempdir.CreateUniqueTempDir());
226279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  string fifo_path = tempdir.path().Append("fifo").value();
227279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  EXPECT_EQ(0, mkfifo(fifo_path.c_str(), 0666));
228279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo
229279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  // Start a process, make sure it is running and try to cancel it. We write
230279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  // two bytes to the fifo, the first one marks that the program is running and
231279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  // the second one marks that the process waited for a timeout and was not
232279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  // killed. We should read the first byte but not the second one.
233279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  vector<string> cmd = {
234279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      kBinPath "/sh",
235279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      "-c",
236279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      base::StringPrintf(
237279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo          "echo -n  X >\"%s\"; sleep 60; echo -n  Y >\"%s\"; exit 1",
238279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo          fifo_path.c_str(),
239279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo          fifo_path.c_str())};
240461b259af8815d782200782c5ba3599d8de4a66cAlex Deymo  uint32_t tag = Subprocess::Get().Exec(cmd, base::Bind(&CallbackBad));
24180f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  EXPECT_NE(0U, tag);
2423defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
243279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  int fifo_fd = HANDLE_EINTR(open(fifo_path.c_str(), O_RDONLY));
244279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  EXPECT_GE(fifo_fd, 0);
245279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo
246279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  loop_.WatchFileDescriptor(FROM_HERE,
247279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo                            fifo_fd,
248279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo                            MessageLoop::WatchMode::kWatchRead,
249279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo                            false,
250279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo                            base::Bind([fifo_fd, tag] {
251279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo                              char c;
252279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo                              EXPECT_EQ(1, HANDLE_EINTR(read(fifo_fd, &c, 1)));
253279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo                              EXPECT_EQ('X', c);
254279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo                              LOG(INFO) << "Killing tag " << tag;
255279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo                              Subprocess::Get().KillExec(tag);
256279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo                            }));
25760ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo
25860ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  // This test would leak a callback that runs when the child process exits
25960ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo  // unless we wait for it to run.
2603f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::MessageLoopRunUntil(
26160ca1a7bca7cc804ec80b510483081ef894de4cdAlex Deymo      &loop_,
262279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      TimeDelta::FromSeconds(120),
263279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo      base::Bind([] { return Subprocess::Get().subprocess_records_.empty(); }));
264279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  EXPECT_TRUE(Subprocess::Get().subprocess_records_.empty());
265279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  // Check that there isn't anything else to read from the pipe.
266279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  char c;
267279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  EXPECT_EQ(0, HANDLE_EINTR(read(fifo_fd, &c, 1)));
268279bbab3740df13c306c1a9e03f3d3beed9aef0fAlex Deymo  IGNORE_EINTR(close(fifo_fd));
2693defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}
2703defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com
2713defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}  // namespace chromeos_update_engine
272