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