blob: abeb84f4651ef14035c651acb001e26c49f5d4d3 [file] [log] [blame]
Peter Qiu17746262015-08-04 22:52:47 -07001// Copyright 2015 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/process_manager.h"
6
Peter Qiu16580042015-08-05 20:39:28 -07007#include <string>
8#include <vector>
9
Peter Qiu17746262015-08-04 22:52:47 -070010#include <base/bind.h>
Peter Qiu16580042015-08-05 20:39:28 -070011#include <chromeos/minijail/mock_minijail.h>
Peter Qiu17746262015-08-04 22:52:47 -070012#include <gmock/gmock.h>
13#include <gtest/gtest.h>
14
15#include "shill/mock_event_dispatcher.h"
16
17using base::Bind;
18using base::Callback;
19using base::CancelableClosure;
20using base::Closure;
21using base::Unretained;
Peter Qiu16580042015-08-05 20:39:28 -070022using std::string;
23using std::vector;
24using testing::_;
25using testing::DoAll;
26using testing::Return;
27using testing::SetArgumentPointee;
28using testing::StrEq;
Peter Qiu17746262015-08-04 22:52:47 -070029
30namespace shill {
31
32class ProcessManagerTest : public testing::Test {
33 public:
34 ProcessManagerTest() : process_manager_(ProcessManager::GetInstance()) {}
35
36 virtual void SetUp() {
37 process_manager_->dispatcher_ = &dispatcher_;
Peter Qiu16580042015-08-05 20:39:28 -070038 process_manager_->minijail_ = &minijail_;
Peter Qiu17746262015-08-04 22:52:47 -070039 }
40
41 virtual void TearDown() {
42 process_manager_->watched_processes_.clear();
43 process_manager_->pending_termination_processes_.clear();
44 }
45
46 void AddWatchedProcess(pid_t pid, const Callback<void(int)>& callback) {
47 process_manager_->watched_processes_.emplace(pid, callback);
48 }
49
50 void AddTerminateProcess(pid_t pid,
51 std::unique_ptr<CancelableClosure> timeout_handler) {
52 process_manager_->pending_termination_processes_.emplace(
53 pid, std::move(timeout_handler));
54 }
55
56 void AssertEmptyWatchedProcesses() {
57 EXPECT_TRUE(process_manager_->watched_processes_.empty());
58 }
59
Peter Qiu16580042015-08-05 20:39:28 -070060 void AssertNonEmptyWatchedProcesses() {
61 EXPECT_FALSE(process_manager_->watched_processes_.empty());
62 }
63
Peter Qiu17746262015-08-04 22:52:47 -070064 void AssertEmptyTerminateProcesses() {
65 EXPECT_TRUE(process_manager_->pending_termination_processes_.empty());
66 }
67
68 void OnProcessExited(pid_t pid, int exit_status) {
69 siginfo_t info;
70 info.si_status = exit_status;
71 process_manager_->OnProcessExited(pid, info);
72 }
73
74 void OnTerminationTimeout(pid_t pid, bool kill_signal) {
75 process_manager_->ProcessTerminationTimeoutHandler(pid, kill_signal);
76 }
77
78 protected:
79 class CallbackObserver {
80 public:
81 CallbackObserver()
82 : exited_callback_(
83 Bind(&CallbackObserver::OnProcessExited, Unretained(this))),
84 termination_timeout_callback_(
85 Bind(&CallbackObserver::OnTerminationTimeout,
86 Unretained(this))) {}
87 virtual ~CallbackObserver() {}
88
89 MOCK_METHOD1(OnProcessExited, void(int exit_status));
90 MOCK_METHOD0(OnTerminationTimeout, void());
91
92 Callback<void(int)> exited_callback_;
93 Closure termination_timeout_callback_;
94 };
95
96 MockEventDispatcher dispatcher_;
Peter Qiu16580042015-08-05 20:39:28 -070097 chromeos::MockMinijail minijail_;
Peter Qiu17746262015-08-04 22:52:47 -070098 ProcessManager* process_manager_;
99};
100
Peter Qiu16580042015-08-05 20:39:28 -0700101MATCHER_P2(IsProcessArgs, program, args, "") {
102 if (string(arg[0]) != program) {
103 return false;
104 }
105 int index = 1;
106 for (const auto& option : args) {
107 if (string(arg[index++]) != option) {
108 return false;
109 }
110 }
111 return arg[index] == nullptr;
112}
113
Peter Qiu17746262015-08-04 22:52:47 -0700114TEST_F(ProcessManagerTest, WatchedProcessExited) {
115 const pid_t kPid = 123;
116 const int kExitStatus = 1;
117 CallbackObserver observer;
118 AddWatchedProcess(kPid, observer.exited_callback_);
119
120 EXPECT_CALL(observer, OnProcessExited(kExitStatus)).Times(1);
121 OnProcessExited(kPid, kExitStatus);
122 AssertEmptyWatchedProcesses();
123}
124
125TEST_F(ProcessManagerTest, TerminateProcessExited) {
126 const pid_t kPid = 123;
127 CallbackObserver observer;
128 std::unique_ptr<CancelableClosure> timeout_handler(
129 new CancelableClosure(observer.termination_timeout_callback_));
130 AddTerminateProcess(kPid, std::move(timeout_handler));
131
132 EXPECT_CALL(observer, OnTerminationTimeout()).Times(0);
133 OnProcessExited(kPid, 1);
134 AssertEmptyTerminateProcesses();
135}
136
Peter Qiu16580042015-08-05 20:39:28 -0700137TEST_F(ProcessManagerTest, StartProcessInMinijail) {
138 const string kProgram = "/usr/bin/dump";
139 const vector<string> kArgs = { "-b", "-g" };
140 const string kUser = "user";
141 const string kGroup = "group";
142 const uint64_t kCapMask = 1;
143 const pid_t kPid = 123;
144
145 EXPECT_CALL(minijail_, DropRoot(_, StrEq(kUser), StrEq(kGroup))).Times(1);
146 EXPECT_CALL(minijail_, UseCapabilities(_, kCapMask)).Times(1);
147 EXPECT_CALL(minijail_, RunAndDestroy(_, IsProcessArgs(kProgram, kArgs), _))
148 .WillOnce(DoAll(SetArgumentPointee<2>(kPid), Return(true)));
149 pid_t actual_pid =
150 process_manager_->StartProcessInMinijail(FROM_HERE,
151 base::FilePath(kProgram),
152 kArgs,
153 kUser,
154 kGroup,
155 kCapMask,
156 Callback<void(int)>());
157 EXPECT_EQ(kPid, actual_pid);
158 AssertNonEmptyWatchedProcesses();
159}
160
161TEST_F(ProcessManagerTest, StartProcessInMinijailFailed) {
162 const string kProgram = "/usr/bin/dump";
163 const vector<string> kArgs = { "-b", "-g" };
164 const string kUser = "user";
165 const string kGroup = "group";
166 const uint64_t kCapMask = 1;
167
168 EXPECT_CALL(minijail_, DropRoot(_, StrEq(kUser), StrEq(kGroup))).Times(1);
169 EXPECT_CALL(minijail_, UseCapabilities(_, kCapMask)).Times(1);
170 EXPECT_CALL(minijail_, RunAndDestroy(_, IsProcessArgs(kProgram, kArgs), _))
171 .WillOnce(Return(false));
172 pid_t actual_pid =
173 process_manager_->StartProcessInMinijail(FROM_HERE,
174 base::FilePath(kProgram),
175 kArgs,
176 kUser,
177 kGroup,
178 kCapMask,
179 Callback<void(int)>());
180 EXPECT_EQ(-1, actual_pid);
181 AssertEmptyWatchedProcesses();
182}
183
Peter Qiu17746262015-08-04 22:52:47 -0700184} // namespace shill