]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/test_subprocess.cc
update sources to v12.1.1
[ceph.git] / ceph / src / test / test_subprocess.cc
CommitLineData
7c673cae
FG
1// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph distributed storage system
5 *
6 * Copyright (C) 2015 Mirantis Inc
7 *
8 * Author: Mykola Golub <mgolub@mirantis.com>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 */
16
17#include <unistd.h>
18
19#include <iostream>
20
21#include "common/SubProcess.h"
22#include "common/safe_io.h"
23#include "gtest/gtest.h"
224ce89b 24#include "common/fork_function.h"
7c673cae
FG
25
26bool read_from_fd(int fd, std::string &out) {
27 out.clear();
28 char buf[1024];
29 ssize_t n = safe_read(fd, buf, sizeof(buf) - 1);
30 if (n < 0)
31 return false;
32 buf[n] = '\0';
33 out = buf;
34 return true;
35}
36
37TEST(SubProcess, True)
38{
39 SubProcess p("true");
40 ASSERT_EQ(p.spawn(), 0);
41 ASSERT_EQ(p.join(), 0);
42 ASSERT_TRUE(p.err().c_str()[0] == '\0');
43}
44
45TEST(SubProcess, False)
46{
47 SubProcess p("false");
48 ASSERT_EQ(p.spawn(), 0);
49 ASSERT_EQ(p.join(), 1);
50 ASSERT_FALSE(p.err().c_str()[0] == '\0');
51}
52
53TEST(SubProcess, NotFound)
54{
55 SubProcess p("NOTEXISTENTBINARY", SubProcess::CLOSE, SubProcess::CLOSE, SubProcess::PIPE);
56 ASSERT_EQ(p.spawn(), 0);
57 std::string buf;
58 ASSERT_TRUE(read_from_fd(p.get_stderr(), buf));
59 std::cerr << "stderr: " << buf;
60 ASSERT_EQ(p.join(), 1);
61 std::cerr << "err: " << p.err() << std::endl;
62 ASSERT_FALSE(p.err().c_str()[0] == '\0');
63}
64
65TEST(SubProcess, Echo)
66{
67 SubProcess echo("echo", SubProcess::CLOSE, SubProcess::PIPE);
68 echo.add_cmd_args("1", "2", "3", NULL);
69
70 ASSERT_EQ(echo.spawn(), 0);
71 std::string buf;
72 ASSERT_TRUE(read_from_fd(echo.get_stdout(), buf));
73 std::cerr << "stdout: " << buf;
74 ASSERT_EQ(buf, "1 2 3\n");
75 ASSERT_EQ(echo.join(), 0);
76 ASSERT_TRUE(echo.err().c_str()[0] == '\0');
77}
78
79TEST(SubProcess, Cat)
80{
81 SubProcess cat("cat", SubProcess::PIPE, SubProcess::PIPE, SubProcess::PIPE);
82
83 ASSERT_EQ(cat.spawn(), 0);
84 std::string msg("to my, trociny!");
85 int n = write(cat.get_stdin(), msg.c_str(), msg.size());
86 ASSERT_EQ(n, (int)msg.size());
87 cat.close_stdin();
88 std::string buf;
89 ASSERT_TRUE(read_from_fd(cat.get_stdout(), buf));
90 std::cerr << "stdout: " << buf << std::endl;
91 ASSERT_EQ(buf, msg);
92 ASSERT_TRUE(read_from_fd(cat.get_stderr(), buf));
93 ASSERT_EQ(buf, "");
94 ASSERT_EQ(cat.join(), 0);
95 ASSERT_TRUE(cat.err().c_str()[0] == '\0');
96}
97
98TEST(SubProcess, CatDevNull)
99{
100 SubProcess cat("cat", SubProcess::PIPE, SubProcess::PIPE, SubProcess::PIPE);
101 cat.add_cmd_arg("/dev/null");
102
103 ASSERT_EQ(cat.spawn(), 0);
104 std::string buf;
105 ASSERT_TRUE(read_from_fd(cat.get_stdout(), buf));
106 ASSERT_EQ(buf, "");
107 ASSERT_TRUE(read_from_fd(cat.get_stderr(), buf));
108 ASSERT_EQ(buf, "");
109 ASSERT_EQ(cat.join(), 0);
110 ASSERT_TRUE(cat.err().c_str()[0] == '\0');
111}
112
113TEST(SubProcess, Killed)
114{
115 SubProcessTimed cat("cat", SubProcess::PIPE, SubProcess::PIPE);
116
117 ASSERT_EQ(cat.spawn(), 0);
118 cat.kill();
119 ASSERT_EQ(cat.join(), 128 + SIGTERM);
120 std::cerr << "err: " << cat.err() << std::endl;
121 ASSERT_FALSE(cat.err().c_str()[0] == '\0');
122}
123
124TEST(SubProcess, CatWithArgs)
125{
126 SubProcess cat("cat", SubProcess::PIPE, SubProcess::PIPE, SubProcess::PIPE);
127 cat.add_cmd_args("/dev/stdin", "/dev/null", "/NOTEXIST", NULL);
128
129 ASSERT_EQ(cat.spawn(), 0);
130 std::string msg("Hello, Word!");
131 int n = write(cat.get_stdin(), msg.c_str(), msg.size());
132 ASSERT_EQ(n, (int)msg.size());
133 cat.close_stdin();
134 std::string buf;
135 ASSERT_TRUE(read_from_fd(cat.get_stdout(), buf));
136 std::cerr << "stdout: " << buf << std::endl;
137 ASSERT_EQ(buf, msg);
138 ASSERT_TRUE(read_from_fd(cat.get_stderr(), buf));
139 std::cerr << "stderr: " << buf;
140 ASSERT_FALSE(buf.empty());
141 ASSERT_EQ(cat.join(), 1);
142 std::cerr << "err: " << cat.err() << std::endl;
143 ASSERT_FALSE(cat.err().c_str()[0] == '\0');
144}
145
146TEST(SubProcess, Subshell)
147{
148 SubProcess sh("/bin/sh", SubProcess::PIPE, SubProcess::PIPE, SubProcess::PIPE);
149 sh.add_cmd_args("-c",
150 "sleep 0; "
151 "cat; "
152 "echo 'error from subshell' >&2; "
153 "/bin/sh -c 'exit 13'", NULL);
154 ASSERT_EQ(sh.spawn(), 0);
155 std::string msg("hello via subshell");
156 int n = write(sh.get_stdin(), msg.c_str(), msg.size());
157 ASSERT_EQ(n, (int)msg.size());
158 sh.close_stdin();
159 std::string buf;
160 ASSERT_TRUE(read_from_fd(sh.get_stdout(), buf));
161 std::cerr << "stdout: " << buf << std::endl;
162 ASSERT_EQ(buf, msg);
163 ASSERT_TRUE(read_from_fd(sh.get_stderr(), buf));
164 std::cerr << "stderr: " << buf;
165 ASSERT_EQ(buf, "error from subshell\n");
166 ASSERT_EQ(sh.join(), 13);
167 std::cerr << "err: " << sh.err() << std::endl;
168 ASSERT_FALSE(sh.err().c_str()[0] == '\0');
169}
170
171TEST(SubProcessTimed, True)
172{
173 SubProcessTimed p("true", SubProcess::CLOSE, SubProcess::CLOSE, SubProcess::CLOSE, 10);
174 ASSERT_EQ(p.spawn(), 0);
175 ASSERT_EQ(p.join(), 0);
176 ASSERT_TRUE(p.err().c_str()[0] == '\0');
177}
178
179TEST(SubProcessTimed, SleepNoTimeout)
180{
181 SubProcessTimed sleep("sleep", SubProcess::CLOSE, SubProcess::CLOSE, SubProcess::CLOSE, 0);
182 sleep.add_cmd_arg("1");
183
184 ASSERT_EQ(sleep.spawn(), 0);
185 ASSERT_EQ(sleep.join(), 0);
186 ASSERT_TRUE(sleep.err().c_str()[0] == '\0');
187}
188
189TEST(SubProcessTimed, Killed)
190{
191 SubProcessTimed cat("cat", SubProcess::PIPE, SubProcess::PIPE, SubProcess::PIPE, 5);
192
193 ASSERT_EQ(cat.spawn(), 0);
194 cat.kill();
195 std::string buf;
196 ASSERT_TRUE(read_from_fd(cat.get_stdout(), buf));
197 ASSERT_TRUE(buf.empty());
198 ASSERT_TRUE(read_from_fd(cat.get_stderr(), buf));
199 ASSERT_TRUE(buf.empty());
200 ASSERT_EQ(cat.join(), 128 + SIGTERM);
201 std::cerr << "err: " << cat.err() << std::endl;
202 ASSERT_FALSE(cat.err().c_str()[0] == '\0');
203}
204
205TEST(SubProcessTimed, SleepTimedout)
206{
207 SubProcessTimed sleep("sleep", SubProcess::CLOSE, SubProcess::CLOSE, SubProcess::PIPE, 1);
208 sleep.add_cmd_arg("10");
209
210 ASSERT_EQ(sleep.spawn(), 0);
211 std::string buf;
212 ASSERT_TRUE(read_from_fd(sleep.get_stderr(), buf));
213 std::cerr << "stderr: " << buf;
214 ASSERT_FALSE(buf.empty());
215 ASSERT_EQ(sleep.join(), 128 + SIGKILL);
216 std::cerr << "err: " << sleep.err() << std::endl;
217 ASSERT_FALSE(sleep.err().c_str()[0] == '\0');
218}
219
220TEST(SubProcessTimed, SubshellNoTimeout)
221{
222 SubProcessTimed sh("/bin/sh", SubProcess::PIPE, SubProcess::PIPE, SubProcess::PIPE, 0);
223 sh.add_cmd_args("-c", "cat >&2", NULL);
224 ASSERT_EQ(sh.spawn(), 0);
225 std::string msg("the quick brown fox jumps over the lazy dog");
226 int n = write(sh.get_stdin(), msg.c_str(), msg.size());
227 ASSERT_EQ(n, (int)msg.size());
228 sh.close_stdin();
229 std::string buf;
230 ASSERT_TRUE(read_from_fd(sh.get_stdout(), buf));
231 std::cerr << "stdout: " << buf << std::endl;
232 ASSERT_TRUE(buf.empty());
233 ASSERT_TRUE(read_from_fd(sh.get_stderr(), buf));
234 std::cerr << "stderr: " << buf << std::endl;
235 ASSERT_EQ(buf, msg);
236 ASSERT_EQ(sh.join(), 0);
237 ASSERT_TRUE(sh.err().c_str()[0] == '\0');
238}
239
240TEST(SubProcessTimed, SubshellKilled)
241{
242 SubProcessTimed sh("/bin/sh", SubProcess::PIPE, SubProcess::PIPE, SubProcess::PIPE, 10);
243 sh.add_cmd_args("-c", "sh -c cat", NULL);
244 ASSERT_EQ(sh.spawn(), 0);
245 std::string msg("etaoin shrdlu");
246 int n = write(sh.get_stdin(), msg.c_str(), msg.size());
247 ASSERT_EQ(n, (int)msg.size());
248 sh.kill();
249 std::string buf;
250 ASSERT_TRUE(read_from_fd(sh.get_stderr(), buf));
251 ASSERT_TRUE(buf.empty());
252 ASSERT_EQ(sh.join(), 128 + SIGTERM);
253 std::cerr << "err: " << sh.err() << std::endl;
254 ASSERT_FALSE(sh.err().c_str()[0] == '\0');
255}
256
257TEST(SubProcessTimed, SubshellTimedout)
258{
259 SubProcessTimed sh("/bin/sh", SubProcess::PIPE, SubProcess::PIPE, SubProcess::PIPE, 1, SIGTERM);
260 sh.add_cmd_args("-c", "sleep 1000& cat; NEVER REACHED", NULL);
261 ASSERT_EQ(sh.spawn(), 0);
262 std::string buf;
263 ASSERT_TRUE(read_from_fd(sh.get_stderr(), buf));
264 std::cerr << "stderr: " << buf;
265 ASSERT_FALSE(buf.empty());
266 ASSERT_EQ(sh.join(), 128 + SIGTERM);
267 std::cerr << "err: " << sh.err() << std::endl;
268 ASSERT_FALSE(sh.err().c_str()[0] == '\0');
269}
224ce89b
WB
270
271TEST(fork_function, normal)
272{
273 ASSERT_EQ(0, fork_function(10, std::cerr, [&]() { return 0; }));
274 ASSERT_EQ(1, fork_function(10, std::cerr, [&]() { return 1; }));
275 ASSERT_EQ(13, fork_function(10, std::cerr, [&]() { return 13; }));
276 ASSERT_EQ(-1, fork_function(10, std::cerr, [&]() { return -1; }));
277 ASSERT_EQ(-13, fork_function(10, std::cerr, [&]() { return -13; }));
278 ASSERT_EQ(-ETIMEDOUT,
279 fork_function(10, std::cerr, [&]() { return -ETIMEDOUT; }));
280}
281
282TEST(fork_function, timeout)
283{
284 ASSERT_EQ(-ETIMEDOUT, fork_function(2, std::cerr, [&]() {
285 sleep(60);
286 return 0; }));
287 ASSERT_EQ(-ETIMEDOUT, fork_function(2, std::cerr, [&]() {
288 sleep(60);
289 return 1; }));
290 ASSERT_EQ(-ETIMEDOUT, fork_function(2, std::cerr, [&]() {
291 sleep(60);
292 return -111; }));
293}