blob: c6cbab012d88355b9a58401919f2b505a72ff48b [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>
Alex Deymo0b3db6b2015-08-10 15:19:37 -070031#include <base/message_loop/message_loop.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070032#include <base/strings/string_util.h>
33#include <base/strings/stringprintf.h>
34#include <base/time/time.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070035#include <brillo/bind_lambda.h>
36#include <brillo/message_loops/base_message_loop.h>
37#include <brillo/message_loops/message_loop.h>
38#include <brillo/message_loops/message_loop_utils.h>
39#include <brillo/strings/string_utils.h>
adlr@google.com3defe6a2009-12-04 20:57:17 +000040#include <gtest/gtest.h>
Gilad Arnold8e3f1262013-01-08 14:59:54 -080041
Alex Deymo39910dc2015-11-09 17:04:30 -080042#include "update_engine/common/test_utils.h"
43#include "update_engine/common/utils.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000044
Gilad Arnold8e3f1262013-01-08 14:59:54 -080045using base::TimeDelta;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070046using brillo::MessageLoop;
adlr@google.com3defe6a2009-12-04 20:57:17 +000047using std::string;
48using std::vector;
49
Alex Deymo279bbab2016-02-12 16:26:17 -080050namespace {
51
52#ifdef __ANDROID__
53#define kBinPath "/system/bin"
54#define kUsrBinPath "/system/bin"
55#else
56#define kBinPath "/bin"
57#define kUsrBinPath "/usr/bin"
58#endif // __ANDROID__
59
60} // namespace
61
adlr@google.com3defe6a2009-12-04 20:57:17 +000062namespace chromeos_update_engine {
63
64class SubprocessTest : public ::testing::Test {
65 protected:
Alex Deymo60ca1a72015-06-18 18:19:15 -070066 void SetUp() override {
67 loop_.SetAsCurrent();
Alex Deymob7ca0962014-10-01 17:58:07 -070068 async_signal_handler_.Init();
69 subprocess_.Init(&async_signal_handler_);
Alex Deymo60ca1a72015-06-18 18:19:15 -070070 }
71
Alex Deymo0b3db6b2015-08-10 15:19:37 -070072 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070073 brillo::BaseMessageLoop loop_{&base_loop_};
74 brillo::AsynchronousSignalHandler async_signal_handler_;
Alex Deymo461b2592015-07-24 20:10:52 -070075 Subprocess subprocess_;
adlr@google.com3defe6a2009-12-04 20:57:17 +000076};
77
78namespace {
Alex Deymo461b2592015-07-24 20:10:52 -070079
Alex Deymo461b2592015-07-24 20:10:52 -070080void ExpectedResults(int expected_return_code, const string& expected_output,
81 int return_code, const string& output) {
82 EXPECT_EQ(expected_return_code, return_code);
83 EXPECT_EQ(expected_output, output);
Alex Deymo60ca1a72015-06-18 18:19:15 -070084 MessageLoop::current()->BreakLoop();
adlr@google.com3defe6a2009-12-04 20:57:17 +000085}
86
Alex Deymo461b2592015-07-24 20:10:52 -070087void ExpectedEnvVars(int return_code, const string& output) {
Darin Petkov6f03a3b2010-11-10 14:27:14 -080088 EXPECT_EQ(0, return_code);
Alex Deymo461b2592015-07-24 20:10:52 -070089 const std::set<string> allowed_envs = {"LD_LIBRARY_PATH", "PATH"};
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070090 for (string key_value : brillo::string_utils::Split(output, "\n")) {
91 auto key_value_pair = brillo::string_utils::SplitAtFirst(
Alex Deymo461b2592015-07-24 20:10:52 -070092 key_value, "=", true);
93 EXPECT_NE(allowed_envs.end(), allowed_envs.find(key_value_pair.first));
94 }
Alex Deymo29b81532015-07-09 11:51:49 -070095 MessageLoop::current()->BreakLoop();
96}
97
Alex Vakulenkod2779df2014-06-16 13:19:00 -070098} // namespace
adlr@google.com3defe6a2009-12-04 20:57:17 +000099
Alex Deymo461b2592015-07-24 20:10:52 -0700100TEST_F(SubprocessTest, IsASingleton) {
101 EXPECT_EQ(&subprocess_, &Subprocess::Get());
102}
103
104TEST_F(SubprocessTest, InactiveInstancesDontChangeTheSingleton) {
105 std::unique_ptr<Subprocess> another_subprocess(new Subprocess());
106 EXPECT_EQ(&subprocess_, &Subprocess::Get());
107 another_subprocess.reset();
108 EXPECT_EQ(&subprocess_, &Subprocess::Get());
109}
110
Alex Deymo60ca1a72015-06-18 18:19:15 -0700111TEST_F(SubprocessTest, SimpleTest) {
Alex Deymo279bbab2016-02-12 16:26:17 -0800112 EXPECT_TRUE(subprocess_.Exec({kBinPath "/false"},
Alex Deymo461b2592015-07-24 20:10:52 -0700113 base::Bind(&ExpectedResults, 1, "")));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700114 loop_.Run();
adlr@google.com3defe6a2009-12-04 20:57:17 +0000115}
116
Alex Deymo60ca1a72015-06-18 18:19:15 -0700117TEST_F(SubprocessTest, EchoTest) {
Alex Deymo461b2592015-07-24 20:10:52 -0700118 EXPECT_TRUE(subprocess_.Exec(
Alex Deymo279bbab2016-02-12 16:26:17 -0800119 {kBinPath "/sh", "-c", "echo this is stdout; echo this is stderr >&2"},
Alex Deymo461b2592015-07-24 20:10:52 -0700120 base::Bind(&ExpectedResults, 0, "this is stdout\nthis is stderr\n")));
Alex Deymo29b81532015-07-09 11:51:49 -0700121 loop_.Run();
122}
123
124TEST_F(SubprocessTest, StderrNotIncludedInOutputTest) {
Alex Deymo461b2592015-07-24 20:10:52 -0700125 EXPECT_TRUE(subprocess_.ExecFlags(
Alex Deymo279bbab2016-02-12 16:26:17 -0800126 {kBinPath "/sh", "-c", "echo on stdout; echo on stderr >&2"},
Alex Deymo461b2592015-07-24 20:10:52 -0700127 0,
128 base::Bind(&ExpectedResults, 0, "on stdout\n")));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700129 loop_.Run();
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800130}
131
Alex Deymo461b2592015-07-24 20:10:52 -0700132TEST_F(SubprocessTest, EnvVarsAreFiltered) {
Alex Deymo279bbab2016-02-12 16:26:17 -0800133 EXPECT_TRUE(
134 subprocess_.Exec({kUsrBinPath "/env"}, base::Bind(&ExpectedEnvVars)));
Alex Deymo461b2592015-07-24 20:10:52 -0700135 loop_.Run();
136}
137
138TEST_F(SubprocessTest, SynchronousTrueSearchsOnPath) {
139 int rc = -1;
140 EXPECT_TRUE(Subprocess::SynchronousExecFlags(
141 {"true"}, Subprocess::kSearchPath, &rc, nullptr));
142 EXPECT_EQ(0, rc);
143}
144
Alex Deymo60ca1a72015-06-18 18:19:15 -0700145TEST_F(SubprocessTest, SynchronousEchoTest) {
146 vector<string> cmd = {
Alex Deymo279bbab2016-02-12 16:26:17 -0800147 kBinPath "/sh",
148 "-c",
149 "echo -n stdout-here; echo -n stderr-there >&2"};
Darin Petkov85d02b72011-05-17 13:25:51 -0700150 int rc = -1;
151 string stdout;
152 ASSERT_TRUE(Subprocess::SynchronousExec(cmd, &rc, &stdout));
153 EXPECT_EQ(0, rc);
154 EXPECT_EQ("stdout-herestderr-there", stdout);
155}
156
Alex Deymo60ca1a72015-06-18 18:19:15 -0700157TEST_F(SubprocessTest, SynchronousEchoNoOutputTest) {
Darin Petkov85d02b72011-05-17 13:25:51 -0700158 int rc = -1;
Alex Deymo461b2592015-07-24 20:10:52 -0700159 ASSERT_TRUE(Subprocess::SynchronousExec(
Alex Deymo279bbab2016-02-12 16:26:17 -0800160 {kBinPath "/sh", "-c", "echo test"}, &rc, nullptr));
Darin Petkov85d02b72011-05-17 13:25:51 -0700161 EXPECT_EQ(0, rc);
162}
163
adlr@google.com3defe6a2009-12-04 20:57:17 +0000164namespace {
Alex Deymo461b2592015-07-24 20:10:52 -0700165void CallbackBad(int return_code, const string& output) {
166 ADD_FAILURE() << "should never be called.";
adlr@google.com3defe6a2009-12-04 20:57:17 +0000167}
Alex Deymo60ca1a72015-06-18 18:19:15 -0700168} // namespace
169
Alex Deymo279bbab2016-02-12 16:26:17 -0800170// Test that you can cancel a program that's already running.
Alex Deymo60ca1a72015-06-18 18:19:15 -0700171TEST_F(SubprocessTest, CancelTest) {
Alex Deymo279bbab2016-02-12 16:26:17 -0800172 base::ScopedTempDir tempdir;
173 ASSERT_TRUE(tempdir.CreateUniqueTempDir());
174 string fifo_path = tempdir.path().Append("fifo").value();
175 EXPECT_EQ(0, mkfifo(fifo_path.c_str(), 0666));
176
177 // Start a process, make sure it is running and try to cancel it. We write
178 // two bytes to the fifo, the first one marks that the program is running and
179 // the second one marks that the process waited for a timeout and was not
180 // killed. We should read the first byte but not the second one.
181 vector<string> cmd = {
182 kBinPath "/sh",
183 "-c",
184 base::StringPrintf(
185 "echo -n X >\"%s\"; sleep 60; echo -n Y >\"%s\"; exit 1",
186 fifo_path.c_str(),
187 fifo_path.c_str())};
188 uint32_t tag = Subprocess::Get().Exec(cmd, base::Bind(&CallbackBad));
189 EXPECT_NE(0U, tag);
190
191 int fifo_fd = HANDLE_EINTR(open(fifo_path.c_str(), O_RDONLY));
192 EXPECT_GE(fifo_fd, 0);
193
194 loop_.WatchFileDescriptor(FROM_HERE,
195 fifo_fd,
196 MessageLoop::WatchMode::kWatchRead,
197 false,
198 base::Bind([fifo_fd, tag] {
199 char c;
200 EXPECT_EQ(1, HANDLE_EINTR(read(fifo_fd, &c, 1)));
201 EXPECT_EQ('X', c);
202 LOG(INFO) << "Killing tag " << tag;
203 Subprocess::Get().KillExec(tag);
204 }));
205
Alex Deymo60ca1a72015-06-18 18:19:15 -0700206 // This test would leak a callback that runs when the child process exits
207 // unless we wait for it to run.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700208 brillo::MessageLoopRunUntil(
Alex Deymo60ca1a72015-06-18 18:19:15 -0700209 &loop_,
Alex Deymo279bbab2016-02-12 16:26:17 -0800210 TimeDelta::FromSeconds(120),
211 base::Bind([] { return Subprocess::Get().subprocess_records_.empty(); }));
212 EXPECT_TRUE(Subprocess::Get().subprocess_records_.empty());
213 // Check that there isn't anything else to read from the pipe.
214 char c;
215 EXPECT_EQ(0, HANDLE_EINTR(read(fifo_fd, &c, 1)));
216 IGNORE_EINTR(close(fifo_fd));
adlr@google.com3defe6a2009-12-04 20:57:17 +0000217}
218
219} // namespace chromeos_update_engine