1// 2// Copyright (C) 2015 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// 16 17#include "shill/process_manager.h" 18 19#include <string> 20#include <vector> 21 22#include <base/bind.h> 23#include <brillo/minijail/mock_minijail.h> 24#include <gmock/gmock.h> 25#include <gtest/gtest.h> 26 27#include "shill/mock_event_dispatcher.h" 28 29using base::Bind; 30using base::Callback; 31using base::CancelableClosure; 32using base::Closure; 33using base::Unretained; 34using std::string; 35using std::vector; 36using testing::_; 37using testing::DoAll; 38using testing::Return; 39using testing::SetArgumentPointee; 40using testing::StrEq; 41 42namespace shill { 43 44class ProcessManagerTest : public testing::Test { 45 public: 46 ProcessManagerTest() : process_manager_(ProcessManager::GetInstance()) {} 47 48 virtual void SetUp() { 49 process_manager_->dispatcher_ = &dispatcher_; 50 process_manager_->minijail_ = &minijail_; 51 } 52 53 virtual void TearDown() { 54 process_manager_->watched_processes_.clear(); 55 process_manager_->pending_termination_processes_.clear(); 56 } 57 58 void AddWatchedProcess(pid_t pid, const Callback<void(int)>& callback) { 59 process_manager_->watched_processes_.emplace(pid, callback); 60 } 61 62 void AddTerminateProcess(pid_t pid, 63 std::unique_ptr<CancelableClosure> timeout_handler) { 64 process_manager_->pending_termination_processes_.emplace( 65 pid, std::move(timeout_handler)); 66 } 67 68 void AssertEmptyWatchedProcesses() { 69 EXPECT_TRUE(process_manager_->watched_processes_.empty()); 70 } 71 72 void AssertNonEmptyWatchedProcesses() { 73 EXPECT_FALSE(process_manager_->watched_processes_.empty()); 74 } 75 76 void AssertEmptyTerminateProcesses() { 77 EXPECT_TRUE(process_manager_->pending_termination_processes_.empty()); 78 } 79 80 void OnProcessExited(pid_t pid, int exit_status) { 81 siginfo_t info; 82 info.si_status = exit_status; 83 process_manager_->OnProcessExited(pid, info); 84 } 85 86 void OnTerminationTimeout(pid_t pid, bool kill_signal) { 87 process_manager_->ProcessTerminationTimeoutHandler(pid, kill_signal); 88 } 89 90 protected: 91 class CallbackObserver { 92 public: 93 CallbackObserver() 94 : exited_callback_( 95 Bind(&CallbackObserver::OnProcessExited, Unretained(this))), 96 termination_timeout_callback_( 97 Bind(&CallbackObserver::OnTerminationTimeout, 98 Unretained(this))) {} 99 virtual ~CallbackObserver() {} 100 101 MOCK_METHOD1(OnProcessExited, void(int exit_status)); 102 MOCK_METHOD0(OnTerminationTimeout, void()); 103 104 Callback<void(int)> exited_callback_; 105 Closure termination_timeout_callback_; 106 }; 107 108 MockEventDispatcher dispatcher_; 109 brillo::MockMinijail minijail_; 110 ProcessManager* process_manager_; 111}; 112 113MATCHER_P2(IsProcessArgs, program, args, "") { 114 if (string(arg[0]) != program) { 115 return false; 116 } 117 int index = 1; 118 for (const auto& option : args) { 119 if (string(arg[index++]) != option) { 120 return false; 121 } 122 } 123 return arg[index] == nullptr; 124} 125 126TEST_F(ProcessManagerTest, WatchedProcessExited) { 127 const pid_t kPid = 123; 128 const int kExitStatus = 1; 129 CallbackObserver observer; 130 AddWatchedProcess(kPid, observer.exited_callback_); 131 132 EXPECT_CALL(observer, OnProcessExited(kExitStatus)).Times(1); 133 OnProcessExited(kPid, kExitStatus); 134 AssertEmptyWatchedProcesses(); 135} 136 137TEST_F(ProcessManagerTest, TerminateProcessExited) { 138 const pid_t kPid = 123; 139 CallbackObserver observer; 140 std::unique_ptr<CancelableClosure> timeout_handler( 141 new CancelableClosure(observer.termination_timeout_callback_)); 142 AddTerminateProcess(kPid, std::move(timeout_handler)); 143 144 EXPECT_CALL(observer, OnTerminationTimeout()).Times(0); 145 OnProcessExited(kPid, 1); 146 AssertEmptyTerminateProcesses(); 147} 148 149TEST_F(ProcessManagerTest, 150 StartProcessInMinijailWithPipesReturnsPidAndWatchesChild) { 151 const string kProgram = "/usr/bin/dump"; 152 const vector<string> kArgs = { "-b", "-g" }; 153 const string kUser = "user"; 154 const string kGroup = "group"; 155 const uint64_t kCapMask = 1; 156 const pid_t kPid = 123; 157 int stdin_fd; 158 int stdout_fd; 159 int stderr_fd; 160 161 EXPECT_CALL(minijail_, DropRoot(_, StrEq(kUser), StrEq(kGroup))) 162 .WillOnce(Return(true)); 163#if !defined(__ANDROID__) 164 EXPECT_CALL(minijail_, UseCapabilities(_, kCapMask)).Times(1); 165#endif // __ANDROID__ 166 EXPECT_CALL(minijail_, 167 RunPipesAndDestroy(_, // minijail* 168 IsProcessArgs(kProgram, kArgs), 169 _, // pid_t* 170 &stdin_fd, 171 &stdout_fd, 172 &stderr_fd)) 173 .WillOnce(DoAll(SetArgumentPointee<2>(kPid), Return(true))); 174 pid_t actual_pid = 175 process_manager_->StartProcessInMinijailWithPipes( 176 FROM_HERE, 177 base::FilePath(kProgram), 178 kArgs, 179 kUser, 180 kGroup, 181 kCapMask, 182 Callback<void(int)>(), 183 &stdin_fd, 184 &stdout_fd, 185 &stderr_fd); 186 EXPECT_EQ(kPid, actual_pid); 187 AssertNonEmptyWatchedProcesses(); 188} 189 190TEST_F(ProcessManagerTest, 191 StartProcessInMinijailWithPipesHandlesFailureOfDropRoot) { 192 const string kProgram = "/usr/bin/dump"; 193 const vector<string> kArgs = { "-b", "-g" }; 194 const string kUser = "user"; 195 const string kGroup = "group"; 196 const uint64_t kCapMask = 1; 197 198 EXPECT_CALL(minijail_, DropRoot(_, StrEq(kUser), StrEq(kGroup))) 199 .WillOnce(Return(false)); 200 EXPECT_CALL(minijail_, 201 RunPipesAndDestroy(_, IsProcessArgs(kProgram, kArgs), _, _, _, _)) 202 .Times(0); 203 pid_t actual_pid = 204 process_manager_->StartProcessInMinijailWithPipes( 205 FROM_HERE, 206 base::FilePath(kProgram), 207 kArgs, 208 kUser, 209 kGroup, 210 kCapMask, 211 Callback<void(int)>(), 212 nullptr, 213 nullptr, 214 nullptr); 215 EXPECT_EQ(-1, actual_pid); 216 AssertEmptyWatchedProcesses(); 217} 218 219TEST_F(ProcessManagerTest, 220 StartProcessInMinijailWithPipesHandlesFailureOfRunAndDestroy) { 221 const string kProgram = "/usr/bin/dump"; 222 const vector<string> kArgs = { "-b", "-g" }; 223 const string kUser = "user"; 224 const string kGroup = "group"; 225 const uint64_t kCapMask = 1; 226 227 EXPECT_CALL(minijail_, DropRoot(_, StrEq(kUser), StrEq(kGroup))) 228 .WillOnce(Return(true)); 229#if !defined(__ANDROID__) 230 EXPECT_CALL(minijail_, UseCapabilities(_, kCapMask)).Times(1); 231#endif // __ANDROID__ 232 EXPECT_CALL(minijail_, 233 RunPipesAndDestroy(_, IsProcessArgs(kProgram, kArgs), _, _, _, _)) 234 .WillOnce(Return(false)); 235 pid_t actual_pid = 236 process_manager_->StartProcessInMinijailWithPipes( 237 FROM_HERE, 238 base::FilePath(kProgram), 239 kArgs, 240 kUser, 241 kGroup, 242 kCapMask, 243 Callback<void(int)>(), 244 nullptr, 245 nullptr, 246 nullptr); 247 EXPECT_EQ(-1, actual_pid); 248 AssertEmptyWatchedProcesses(); 249} 250 251TEST_F(ProcessManagerTest, UpdateExitCallbackUpdatesCallback) { 252 const pid_t kPid = 123; 253 const int kExitStatus = 1; 254 CallbackObserver original_observer; 255 AddWatchedProcess(kPid, original_observer.exited_callback_); 256 257 CallbackObserver new_observer; 258 EXPECT_CALL(original_observer, OnProcessExited(_)).Times(0); 259 EXPECT_TRUE(process_manager_->UpdateExitCallback( 260 kPid, 261 new_observer.exited_callback_)); 262 EXPECT_CALL(new_observer, OnProcessExited(_)).Times(1); 263 OnProcessExited(kPid, kExitStatus); 264} 265 266} // namespace shill 267