blob: 2a8be94a46a0c87052b6dd030fb6313bb9f977d9 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
adlr@google.com3defe6a2009-12-04 20:57:17 +000016
Alex Deymo39910dc2015-11-09 17:04:30 -080017#include "update_engine/common/subprocess.h"
Alex Deymoaab50e32014-11-10 19:55:35 -080018
Alex Deymo5d527802014-07-18 14:24:13 -070019#include <fcntl.h>
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070020#include <poll.h>
adlr@google.com3defe6a2009-12-04 20:57:17 +000021#include <sys/types.h>
22#include <unistd.h>
Gilad Arnold8e3f1262013-01-08 14:59:54 -080023
Alex Deymo461b2592015-07-24 20:10:52 -070024#include <set>
adlr@google.com3defe6a2009-12-04 20:57:17 +000025#include <string>
26#include <vector>
Gilad Arnold8e3f1262013-01-08 14:59:54 -080027
Alex Deymo60ca1a72015-06-18 18:19:15 -070028#include <base/bind.h>
Alex Deymo279bbab2016-02-12 16:26:17 -080029#include <base/files/scoped_temp_dir.h>
Alex Deymo60ca1a72015-06-18 18:19:15 -070030#include <base/location.h>
Qijiang Fanb0b6cc22020-10-15 21:54:11 +090031#if BASE_VER < 780000 // Android
Alex Deymo0b3db6b2015-08-10 15:19:37 -070032#include <base/message_loop/message_loop.h>
Qijiang Fanb0b6cc22020-10-15 21:54:11 +090033#endif // BASE_VER < 780000
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -070034#include <android-base/stringprintf.h>
Qijiang Fanb0b6cc22020-10-15 21:54:11 +090035#if BASE_VER >= 780000 // Chrome OS
36#include <base/task/single_thread_task_executor.h>
37#endif // BASE_VER >= 780000
Alex Vakulenko75039d72014-03-25 12:36:28 -070038#include <base/time/time.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070039#include <brillo/message_loops/base_message_loop.h>
40#include <brillo/message_loops/message_loop.h>
41#include <brillo/message_loops/message_loop_utils.h>
42#include <brillo/strings/string_utils.h>
Alex Deymoe384bb22016-03-29 17:23:33 -070043#include <brillo/unittest_utils.h>
adlr@google.com3defe6a2009-12-04 20:57:17 +000044#include <gtest/gtest.h>
Gilad Arnold8e3f1262013-01-08 14:59:54 -080045
Alex Deymo39910dc2015-11-09 17:04:30 -080046#include "update_engine/common/test_utils.h"
47#include "update_engine/common/utils.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000048
Gilad Arnold8e3f1262013-01-08 14:59:54 -080049using base::TimeDelta;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070050using brillo::MessageLoop;
adlr@google.com3defe6a2009-12-04 20:57:17 +000051using std::string;
Qijiang Fan6955bcc2019-11-19 20:33:43 +090052using std::unique_ptr;
adlr@google.com3defe6a2009-12-04 20:57:17 +000053using std::vector;
54
Alex Deymo279bbab2016-02-12 16:26:17 -080055namespace {
56
57#ifdef __ANDROID__
58#define kBinPath "/system/bin"
59#define kUsrBinPath "/system/bin"
60#else
61#define kBinPath "/bin"
62#define kUsrBinPath "/usr/bin"
63#endif // __ANDROID__
64
65} // namespace
66
adlr@google.com3defe6a2009-12-04 20:57:17 +000067namespace chromeos_update_engine {
68
69class SubprocessTest : public ::testing::Test {
70 protected:
Alex Deymo60ca1a72015-06-18 18:19:15 -070071 void SetUp() override {
72 loop_.SetAsCurrent();
Alex Deymob7ca0962014-10-01 17:58:07 -070073 async_signal_handler_.Init();
74 subprocess_.Init(&async_signal_handler_);
Alex Deymo60ca1a72015-06-18 18:19:15 -070075 }
76
Qijiang Fanb0b6cc22020-10-15 21:54:11 +090077#if BASE_VER < 780000 // Android
Alex Deymo0b3db6b2015-08-10 15:19:37 -070078 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070079 brillo::BaseMessageLoop loop_{&base_loop_};
Qijiang Fanb0b6cc22020-10-15 21:54:11 +090080#else // Chrome OS
81 base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
82 brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
83#endif // BASE_VER < 780000
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070084 brillo::AsynchronousSignalHandler async_signal_handler_;
Alex Deymo461b2592015-07-24 20:10:52 -070085 Subprocess subprocess_;
Qijiang Fan6955bcc2019-11-19 20:33:43 +090086 unique_ptr<base::FileDescriptorWatcher::Controller> watcher_;
adlr@google.com3defe6a2009-12-04 20:57:17 +000087};
88
89namespace {
Alex Deymo461b2592015-07-24 20:10:52 -070090
Amin Hassanib2689592019-01-13 17:04:28 -080091void ExpectedResults(int expected_return_code,
92 const string& expected_output,
93 int return_code,
94 const string& output) {
Alex Deymo461b2592015-07-24 20:10:52 -070095 EXPECT_EQ(expected_return_code, return_code);
96 EXPECT_EQ(expected_output, output);
Alex Deymo60ca1a72015-06-18 18:19:15 -070097 MessageLoop::current()->BreakLoop();
adlr@google.com3defe6a2009-12-04 20:57:17 +000098}
99
Alex Deymo461b2592015-07-24 20:10:52 -0700100void ExpectedEnvVars(int return_code, const string& output) {
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800101 EXPECT_EQ(0, return_code);
Alex Deymo461b2592015-07-24 20:10:52 -0700102 const std::set<string> allowed_envs = {"LD_LIBRARY_PATH", "PATH"};
Chih-Hung Hsieh5c6bb1d2016-07-27 13:33:15 -0700103 for (const string& key_value : brillo::string_utils::Split(output, "\n")) {
Amin Hassanib2689592019-01-13 17:04:28 -0800104 auto key_value_pair =
105 brillo::string_utils::SplitAtFirst(key_value, "=", true);
Alex Deymo461b2592015-07-24 20:10:52 -0700106 EXPECT_NE(allowed_envs.end(), allowed_envs.find(key_value_pair.first));
107 }
Alex Deymo29b81532015-07-09 11:51:49 -0700108 MessageLoop::current()->BreakLoop();
109}
110
Alex Deymoe384bb22016-03-29 17:23:33 -0700111void ExpectedDataOnPipe(const Subprocess* subprocess,
112 pid_t* pid,
113 int child_fd,
114 const string& child_fd_data,
115 int expected_return_code,
116 int return_code,
117 const string& /* output */) {
118 EXPECT_EQ(expected_return_code, return_code);
119
120 // Verify that we can read the data from our end of |child_fd|.
121 int fd = subprocess->GetPipeFd(*pid, child_fd);
122 EXPECT_NE(-1, fd);
123 vector<char> buf(child_fd_data.size() + 1);
124 EXPECT_EQ(static_cast<ssize_t>(child_fd_data.size()),
125 HANDLE_EINTR(read(fd, buf.data(), buf.size())));
126 EXPECT_EQ(child_fd_data,
127 string(buf.begin(), buf.begin() + child_fd_data.size()));
128
129 MessageLoop::current()->BreakLoop();
130}
131
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700132} // namespace
adlr@google.com3defe6a2009-12-04 20:57:17 +0000133
Alex Deymo461b2592015-07-24 20:10:52 -0700134TEST_F(SubprocessTest, IsASingleton) {
135 EXPECT_EQ(&subprocess_, &Subprocess::Get());
136}
137
138TEST_F(SubprocessTest, InactiveInstancesDontChangeTheSingleton) {
139 std::unique_ptr<Subprocess> another_subprocess(new Subprocess());
140 EXPECT_EQ(&subprocess_, &Subprocess::Get());
141 another_subprocess.reset();
142 EXPECT_EQ(&subprocess_, &Subprocess::Get());
143}
144
Alex Deymo60ca1a72015-06-18 18:19:15 -0700145TEST_F(SubprocessTest, SimpleTest) {
Kelvin Zhange53a3182023-10-24 16:20:52 -0700146 ASSERT_TRUE(subprocess_.Exec({kBinPath "/false"},
Alex Deymo461b2592015-07-24 20:10:52 -0700147 base::Bind(&ExpectedResults, 1, "")));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700148 loop_.Run();
adlr@google.com3defe6a2009-12-04 20:57:17 +0000149}
150
Alex Deymo60ca1a72015-06-18 18:19:15 -0700151TEST_F(SubprocessTest, EchoTest) {
Kelvin Zhange53a3182023-10-24 16:20:52 -0700152 ASSERT_TRUE(subprocess_.Exec(
Alex Deymo279bbab2016-02-12 16:26:17 -0800153 {kBinPath "/sh", "-c", "echo this is stdout; echo this is stderr >&2"},
Alex Deymo461b2592015-07-24 20:10:52 -0700154 base::Bind(&ExpectedResults, 0, "this is stdout\nthis is stderr\n")));
Alex Deymo29b81532015-07-09 11:51:49 -0700155 loop_.Run();
156}
157
158TEST_F(SubprocessTest, StderrNotIncludedInOutputTest) {
Kelvin Zhange53a3182023-10-24 16:20:52 -0700159 ASSERT_TRUE(subprocess_.ExecFlags(
Alex Deymo279bbab2016-02-12 16:26:17 -0800160 {kBinPath "/sh", "-c", "echo on stdout; echo on stderr >&2"},
Alex Deymo461b2592015-07-24 20:10:52 -0700161 0,
Alex Deymoe384bb22016-03-29 17:23:33 -0700162 {},
Alex Deymo461b2592015-07-24 20:10:52 -0700163 base::Bind(&ExpectedResults, 0, "on stdout\n")));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700164 loop_.Run();
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800165}
166
Alex Deymoe384bb22016-03-29 17:23:33 -0700167TEST_F(SubprocessTest, PipeRedirectFdTest) {
168 pid_t pid;
169 pid = subprocess_.ExecFlags(
170 {kBinPath "/sh", "-c", "echo on pipe >&3"},
171 0,
172 {3},
173 base::Bind(&ExpectedDataOnPipe, &subprocess_, &pid, 3, "on pipe\n", 0));
Kelvin Zhange53a3182023-10-24 16:20:52 -0700174 ASSERT_NE(0, pid);
Alex Deymoe384bb22016-03-29 17:23:33 -0700175
176 // Wrong file descriptor values should return -1.
Kelvin Zhange53a3182023-10-24 16:20:52 -0700177 ASSERT_EQ(-1, subprocess_.GetPipeFd(pid, 123));
Alex Deymoe384bb22016-03-29 17:23:33 -0700178 loop_.Run();
179 // Calling GetPipeFd() after the callback runs is invalid.
Kelvin Zhange53a3182023-10-24 16:20:52 -0700180 ASSERT_EQ(-1, subprocess_.GetPipeFd(pid, 3));
Alex Deymoe384bb22016-03-29 17:23:33 -0700181}
182
183// Test that a pipe file descriptor open in the parent is not open in the child.
184TEST_F(SubprocessTest, PipeClosedWhenNotRedirectedTest) {
185 brillo::ScopedPipe pipe;
Alex Deymo279d5722016-04-07 16:22:13 -0700186
187 // test_subprocess will return with the errno of fstat, which should be EBADF
188 // if the passed file descriptor is closed in the child.
189 const vector<string> cmd = {
190 test_utils::GetBuildArtifactsPath("test_subprocess"),
191 "fstat",
192 std::to_string(pipe.writer)};
Kelvin Zhange53a3182023-10-24 16:20:52 -0700193 ASSERT_TRUE(subprocess_.ExecFlags(
Alex Deymo279d5722016-04-07 16:22:13 -0700194 cmd, 0, {}, base::Bind(&ExpectedResults, EBADF, "")));
Alex Deymoe384bb22016-03-29 17:23:33 -0700195 loop_.Run();
196}
197
Alex Deymo461b2592015-07-24 20:10:52 -0700198TEST_F(SubprocessTest, EnvVarsAreFiltered) {
Kelvin Zhange53a3182023-10-24 16:20:52 -0700199 ASSERT_TRUE(
Alex Deymo279bbab2016-02-12 16:26:17 -0800200 subprocess_.Exec({kUsrBinPath "/env"}, base::Bind(&ExpectedEnvVars)));
Alex Deymo461b2592015-07-24 20:10:52 -0700201 loop_.Run();
202}
203
204TEST_F(SubprocessTest, SynchronousTrueSearchsOnPath) {
205 int rc = -1;
Kelvin Zhange53a3182023-10-24 16:20:52 -0700206 ASSERT_TRUE(Subprocess::SynchronousExecFlags(
Amin Hassani3a4caa12019-11-06 11:12:28 -0800207 {"true"}, Subprocess::kSearchPath, &rc, nullptr, nullptr));
Alex Deymo461b2592015-07-24 20:10:52 -0700208 EXPECT_EQ(0, rc);
209}
210
Alex Deymo60ca1a72015-06-18 18:19:15 -0700211TEST_F(SubprocessTest, SynchronousEchoTest) {
212 vector<string> cmd = {
Amin Hassanib2689592019-01-13 17:04:28 -0800213 kBinPath "/sh", "-c", "echo -n stdout-here; echo -n stderr-there >&2"};
Darin Petkov85d02b72011-05-17 13:25:51 -0700214 int rc = -1;
Amin Hassani3a4caa12019-11-06 11:12:28 -0800215 string stdout, stderr;
216 ASSERT_TRUE(Subprocess::SynchronousExec(cmd, &rc, &stdout, &stderr));
Darin Petkov85d02b72011-05-17 13:25:51 -0700217 EXPECT_EQ(0, rc);
Amin Hassani3a4caa12019-11-06 11:12:28 -0800218 EXPECT_EQ("stdout-here", stdout);
219 EXPECT_EQ("stderr-there", stderr);
Darin Petkov85d02b72011-05-17 13:25:51 -0700220}
221
Alex Deymo60ca1a72015-06-18 18:19:15 -0700222TEST_F(SubprocessTest, SynchronousEchoNoOutputTest) {
Darin Petkov85d02b72011-05-17 13:25:51 -0700223 int rc = -1;
Alex Deymo461b2592015-07-24 20:10:52 -0700224 ASSERT_TRUE(Subprocess::SynchronousExec(
Amin Hassani3a4caa12019-11-06 11:12:28 -0800225 {kBinPath "/sh", "-c", "echo test"}, &rc, nullptr, nullptr));
Darin Petkov85d02b72011-05-17 13:25:51 -0700226 EXPECT_EQ(0, rc);
227}
228
adlr@google.com3defe6a2009-12-04 20:57:17 +0000229namespace {
Alex Deymo461b2592015-07-24 20:10:52 -0700230void CallbackBad(int return_code, const string& output) {
231 ADD_FAILURE() << "should never be called.";
adlr@google.com3defe6a2009-12-04 20:57:17 +0000232}
Alex Deymo60ca1a72015-06-18 18:19:15 -0700233} // namespace
234
Alex Deymo279bbab2016-02-12 16:26:17 -0800235// Test that you can cancel a program that's already running.
Alex Deymo60ca1a72015-06-18 18:19:15 -0700236TEST_F(SubprocessTest, CancelTest) {
Alex Deymo279bbab2016-02-12 16:26:17 -0800237 base::ScopedTempDir tempdir;
238 ASSERT_TRUE(tempdir.CreateUniqueTempDir());
Hidehiko Abe2b9d2412017-12-13 18:56:18 +0900239 string fifo_path = tempdir.GetPath().Append("fifo").value();
Kelvin Zhange53a3182023-10-24 16:20:52 -0700240 ASSERT_EQ(0, mkfifo(fifo_path.c_str(), 0666));
Alex Deymo279bbab2016-02-12 16:26:17 -0800241
242 // Start a process, make sure it is running and try to cancel it. We write
243 // two bytes to the fifo, the first one marks that the program is running and
244 // the second one marks that the process waited for a timeout and was not
245 // killed. We should read the first byte but not the second one.
246 vector<string> cmd = {
247 kBinPath "/sh",
248 "-c",
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -0700249 android::base::StringPrintf(
Ben Chan70a21192017-01-10 19:56:50 -0800250 // The 'sleep' launched below could be left behind as an orphaned
251 // process when the 'sh' process is terminated by SIGTERM. As a
252 // remedy, trap SIGTERM and kill the 'sleep' process, which requires
253 // launching 'sleep' in background and then waiting for it.
254 "cleanup() { kill \"${sleep_pid}\"; exit 0; }; "
255 "trap cleanup TERM; "
256 "sleep 60 & "
257 "sleep_pid=$!; "
258 "printf X >\"%s\"; "
259 "wait; "
260 "printf Y >\"%s\"; "
261 "exit 1",
Alex Deymo279bbab2016-02-12 16:26:17 -0800262 fifo_path.c_str(),
263 fifo_path.c_str())};
264 uint32_t tag = Subprocess::Get().Exec(cmd, base::Bind(&CallbackBad));
Kelvin Zhange53a3182023-10-24 16:20:52 -0700265 ASSERT_NE(0U, tag);
Alex Deymo279bbab2016-02-12 16:26:17 -0800266
267 int fifo_fd = HANDLE_EINTR(open(fifo_path.c_str(), O_RDONLY));
Kelvin Zhange53a3182023-10-24 16:20:52 -0700268 ASSERT_GE(fifo_fd, 0);
Alex Deymo279bbab2016-02-12 16:26:17 -0800269
Qijiang Fan6955bcc2019-11-19 20:33:43 +0900270 watcher_ = base::FileDescriptorWatcher::WatchReadable(
271 fifo_fd,
272 base::Bind(
Kelvin Zhang1e926312023-09-27 18:10:25 -0700273 [](brillo::BaseMessageLoop* loop,
274 unique_ptr<base::FileDescriptorWatcher::Controller>* watcher,
Qijiang Fan6955bcc2019-11-19 20:33:43 +0900275 int fifo_fd,
276 uint32_t tag) {
Kelvin Zhang1e926312023-09-27 18:10:25 -0700277 char c{};
Qijiang Fan6955bcc2019-11-19 20:33:43 +0900278 EXPECT_EQ(1, HANDLE_EINTR(read(fifo_fd, &c, 1)));
279 EXPECT_EQ('X', c);
280 LOG(INFO) << "Killing tag " << tag;
281 Subprocess::Get().KillExec(tag);
Kelvin Zhang1e926312023-09-27 18:10:25 -0700282 loop->BreakLoop();
283 ASSERT_TRUE(Subprocess::Get().subprocess_records_.empty());
Qijiang Fan6955bcc2019-11-19 20:33:43 +0900284 *watcher = nullptr;
285 },
Kelvin Zhang1e926312023-09-27 18:10:25 -0700286 &loop_,
Qijiang Fan6955bcc2019-11-19 20:33:43 +0900287 // watcher_ is no longer used outside the clousure.
288 base::Unretained(&watcher_),
289 fifo_fd,
290 tag));
Alex Deymo279bbab2016-02-12 16:26:17 -0800291
Alex Deymo60ca1a72015-06-18 18:19:15 -0700292 // This test would leak a callback that runs when the child process exits
293 // unless we wait for it to run.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700294 brillo::MessageLoopRunUntil(
Qijiang Fan15a6ead2020-07-25 17:19:49 +0900295 &loop_, TimeDelta::FromSeconds(20), base::Bind([] {
Amin Hassanib2689592019-01-13 17:04:28 -0800296 return Subprocess::Get().subprocess_records_.empty();
297 }));
Alex Deymo279bbab2016-02-12 16:26:17 -0800298 EXPECT_TRUE(Subprocess::Get().subprocess_records_.empty());
299 // Check that there isn't anything else to read from the pipe.
300 char c;
301 EXPECT_EQ(0, HANDLE_EINTR(read(fifo_fd, &c, 1)));
302 IGNORE_EINTR(close(fifo_fd));
adlr@google.com3defe6a2009-12-04 20:57:17 +0000303}
304
305} // namespace chromeos_update_engine