]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/test_subprocess.cc
1 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph distributed storage system
6 * Copyright (C) 2015 Mirantis Inc
8 * Author: Mykola Golub <mgolub@mirantis.com>
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.
21 #include "common/SubProcess.h"
22 #include "common/safe_io.h"
23 #include "gtest/gtest.h"
24 #include "common/fork_function.h"
27 // Some of the tests expect GNU binaries to be available. We'll just rely on
28 // the ones provided by Msys (which also comes with Git for Windows).
29 #define SHELL "bash.exe"
31 #define SHELL "/bin/sh"
34 bool read_from_fd(int fd
, std::string
&out
) {
37 ssize_t n
= safe_read(fd
, buf
, sizeof(buf
) - 1);
45 TEST(SubProcess
, True
)
48 ASSERT_EQ(p
.spawn(), 0);
49 ASSERT_EQ(p
.join(), 0);
50 ASSERT_TRUE(p
.err().c_str()[0] == '\0');
53 TEST(SubProcess
, False
)
55 SubProcess
p("false");
56 ASSERT_EQ(p
.spawn(), 0);
57 ASSERT_EQ(p
.join(), 1);
58 ASSERT_FALSE(p
.err().c_str()[0] == '\0');
61 TEST(SubProcess
, NotFound
)
63 SubProcess
p("NOTEXISTENTBINARY", SubProcess::CLOSE
, SubProcess::CLOSE
, SubProcess::PIPE
);
65 // Windows will error out early.
66 ASSERT_EQ(p
.spawn(), -1);
68 ASSERT_EQ(p
.spawn(), 0);
70 ASSERT_TRUE(read_from_fd(p
.get_stderr(), buf
));
71 std::cerr
<< "stderr: " << buf
;
72 ASSERT_EQ(p
.join(), 1);
73 std::cerr
<< "err: " << p
.err() << std::endl
;
74 ASSERT_FALSE(p
.err().c_str()[0] == '\0');
78 TEST(SubProcess
, Echo
)
80 SubProcess
echo("echo", SubProcess::CLOSE
, SubProcess::PIPE
);
81 echo
.add_cmd_args("1", "2", "3", NULL
);
83 ASSERT_EQ(echo
.spawn(), 0);
85 ASSERT_TRUE(read_from_fd(echo
.get_stdout(), buf
));
86 std::cerr
<< "stdout: " << buf
;
87 ASSERT_EQ(buf
, "1 2 3\n");
88 ASSERT_EQ(echo
.join(), 0);
89 ASSERT_TRUE(echo
.err().c_str()[0] == '\0');
94 SubProcess
cat("cat", SubProcess::PIPE
, SubProcess::PIPE
, SubProcess::PIPE
);
96 ASSERT_EQ(cat
.spawn(), 0);
97 std::string
msg("to my, trociny!");
98 int n
= write(cat
.get_stdin(), msg
.c_str(), msg
.size());
99 ASSERT_EQ(n
, (int)msg
.size());
102 ASSERT_TRUE(read_from_fd(cat
.get_stdout(), buf
));
103 std::cerr
<< "stdout: " << buf
<< std::endl
;
105 ASSERT_TRUE(read_from_fd(cat
.get_stderr(), buf
));
107 ASSERT_EQ(cat
.join(), 0);
108 ASSERT_TRUE(cat
.err().c_str()[0] == '\0');
111 TEST(SubProcess
, CatDevNull
)
113 SubProcess
cat("cat", SubProcess::PIPE
, SubProcess::PIPE
, SubProcess::PIPE
);
114 cat
.add_cmd_arg("/dev/null");
116 ASSERT_EQ(cat
.spawn(), 0);
118 ASSERT_TRUE(read_from_fd(cat
.get_stdout(), buf
));
120 ASSERT_TRUE(read_from_fd(cat
.get_stderr(), buf
));
122 ASSERT_EQ(cat
.join(), 0);
123 ASSERT_TRUE(cat
.err().c_str()[0] == '\0');
126 TEST(SubProcess
, Killed
)
128 SubProcessTimed
cat("cat", SubProcess::PIPE
, SubProcess::PIPE
);
130 ASSERT_EQ(cat
.spawn(), 0);
132 ASSERT_EQ(cat
.join(), 128 + SIGTERM
);
133 std::cerr
<< "err: " << cat
.err() << std::endl
;
134 ASSERT_FALSE(cat
.err().c_str()[0] == '\0');
138 TEST(SubProcess
, CatWithArgs
)
140 SubProcess
cat("cat", SubProcess::PIPE
, SubProcess::PIPE
, SubProcess::PIPE
);
141 cat
.add_cmd_args("/dev/stdin", "/dev/null", "/NOTEXIST", NULL
);
143 ASSERT_EQ(cat
.spawn(), 0);
144 std::string
msg("Hello, Word!");
145 int n
= write(cat
.get_stdin(), msg
.c_str(), msg
.size());
146 ASSERT_EQ(n
, (int)msg
.size());
149 ASSERT_TRUE(read_from_fd(cat
.get_stdout(), buf
));
150 std::cerr
<< "stdout: " << buf
<< std::endl
;
152 ASSERT_TRUE(read_from_fd(cat
.get_stderr(), buf
));
153 std::cerr
<< "stderr: " << buf
;
154 ASSERT_FALSE(buf
.empty());
155 ASSERT_EQ(cat
.join(), 1);
156 std::cerr
<< "err: " << cat
.err() << std::endl
;
157 ASSERT_FALSE(cat
.err().c_str()[0] == '\0');
161 TEST(SubProcess
, Subshell
)
163 SubProcess
sh(SHELL
, SubProcess::PIPE
, SubProcess::PIPE
, SubProcess::PIPE
);
164 sh
.add_cmd_args("-c",
167 "echo 'error from subshell' >&2; "
168 SHELL
" -c 'exit 13'", NULL
);
169 ASSERT_EQ(sh
.spawn(), 0);
170 std::string
msg("hello via subshell");
171 int n
= write(sh
.get_stdin(), msg
.c_str(), msg
.size());
172 ASSERT_EQ(n
, (int)msg
.size());
175 ASSERT_TRUE(read_from_fd(sh
.get_stdout(), buf
));
176 std::cerr
<< "stdout: " << buf
<< std::endl
;
178 ASSERT_TRUE(read_from_fd(sh
.get_stderr(), buf
));
179 std::cerr
<< "stderr: " << buf
;
180 ASSERT_EQ(buf
, "error from subshell\n");
181 ASSERT_EQ(sh
.join(), 13);
182 std::cerr
<< "err: " << sh
.err() << std::endl
;
183 ASSERT_FALSE(sh
.err().c_str()[0] == '\0');
186 TEST(SubProcessTimed
, True
)
188 SubProcessTimed
p("true", SubProcess::CLOSE
, SubProcess::CLOSE
, SubProcess::CLOSE
, 10);
189 ASSERT_EQ(p
.spawn(), 0);
190 ASSERT_EQ(p
.join(), 0);
191 ASSERT_TRUE(p
.err().c_str()[0] == '\0');
194 TEST(SubProcessTimed
, SleepNoTimeout
)
196 SubProcessTimed
sleep("sleep", SubProcess::CLOSE
, SubProcess::CLOSE
, SubProcess::CLOSE
, 0);
197 sleep
.add_cmd_arg("1");
199 ASSERT_EQ(sleep
.spawn(), 0);
200 ASSERT_EQ(sleep
.join(), 0);
201 ASSERT_TRUE(sleep
.err().c_str()[0] == '\0');
204 TEST(SubProcessTimed
, Killed
)
206 SubProcessTimed
cat("cat", SubProcess::PIPE
, SubProcess::PIPE
, SubProcess::PIPE
, 5);
208 ASSERT_EQ(cat
.spawn(), 0);
211 ASSERT_TRUE(read_from_fd(cat
.get_stdout(), buf
));
212 ASSERT_TRUE(buf
.empty());
213 ASSERT_TRUE(read_from_fd(cat
.get_stderr(), buf
));
214 ASSERT_TRUE(buf
.empty());
215 ASSERT_EQ(cat
.join(), 128 + SIGTERM
);
216 std::cerr
<< "err: " << cat
.err() << std::endl
;
217 ASSERT_FALSE(cat
.err().c_str()[0] == '\0');
220 TEST(SubProcessTimed
, SleepTimedout
)
222 SubProcessTimed
sleep("sleep", SubProcess::CLOSE
, SubProcess::CLOSE
, SubProcess::PIPE
, 1);
223 sleep
.add_cmd_arg("10");
225 ASSERT_EQ(sleep
.spawn(), 0);
227 ASSERT_TRUE(read_from_fd(sleep
.get_stderr(), buf
));
229 std::cerr
<< "stderr: " << buf
;
230 ASSERT_FALSE(buf
.empty());
232 ASSERT_EQ(sleep
.join(), 128 + SIGKILL
);
233 std::cerr
<< "err: " << sleep
.err() << std::endl
;
234 ASSERT_FALSE(sleep
.err().c_str()[0] == '\0');
237 TEST(SubProcessTimed
, SubshellNoTimeout
)
239 SubProcessTimed
sh(SHELL
, SubProcess::PIPE
, SubProcess::PIPE
, SubProcess::PIPE
, 0);
240 sh
.add_cmd_args("-c", "cat >&2", NULL
);
241 ASSERT_EQ(sh
.spawn(), 0);
242 std::string
msg("the quick brown fox jumps over the lazy dog");
243 int n
= write(sh
.get_stdin(), msg
.c_str(), msg
.size());
244 ASSERT_EQ(n
, (int)msg
.size());
247 ASSERT_TRUE(read_from_fd(sh
.get_stdout(), buf
));
248 std::cerr
<< "stdout: " << buf
<< std::endl
;
249 ASSERT_TRUE(buf
.empty());
250 ASSERT_TRUE(read_from_fd(sh
.get_stderr(), buf
));
251 std::cerr
<< "stderr: " << buf
<< std::endl
;
253 ASSERT_EQ(sh
.join(), 0);
254 ASSERT_TRUE(sh
.err().c_str()[0] == '\0');
257 TEST(SubProcessTimed
, SubshellKilled
)
259 SubProcessTimed
sh(SHELL
, SubProcess::PIPE
, SubProcess::PIPE
, SubProcess::PIPE
, 10);
260 sh
.add_cmd_args("-c", SHELL
"-c cat", NULL
);
261 ASSERT_EQ(sh
.spawn(), 0);
262 std::string
msg("etaoin shrdlu");
263 int n
= write(sh
.get_stdin(), msg
.c_str(), msg
.size());
264 ASSERT_EQ(n
, (int)msg
.size());
267 ASSERT_TRUE(read_from_fd(sh
.get_stderr(), buf
));
268 ASSERT_TRUE(buf
.empty());
269 ASSERT_EQ(sh
.join(), 128 + SIGTERM
);
270 std::cerr
<< "err: " << sh
.err() << std::endl
;
271 ASSERT_FALSE(sh
.err().c_str()[0] == '\0');
274 TEST(SubProcessTimed
, SubshellTimedout
)
276 SubProcessTimed
sh(SHELL
, SubProcess::PIPE
, SubProcess::PIPE
, SubProcess::PIPE
, 1, SIGTERM
);
277 sh
.add_cmd_args("-c", "sleep 1000& cat; NEVER REACHED", NULL
);
278 ASSERT_EQ(sh
.spawn(), 0);
281 ASSERT_TRUE(read_from_fd(sh
.get_stderr(), buf
));
282 std::cerr
<< "stderr: " << buf
;
283 ASSERT_FALSE(buf
.empty());
285 ASSERT_EQ(sh
.join(), 128 + SIGTERM
);
286 std::cerr
<< "err: " << sh
.err() << std::endl
;
287 ASSERT_FALSE(sh
.err().c_str()[0] == '\0');
291 TEST(fork_function
, normal
)
293 ASSERT_EQ(0, fork_function(10, std::cerr
, [&]() { return 0; }));
294 ASSERT_EQ(1, fork_function(10, std::cerr
, [&]() { return 1; }));
295 ASSERT_EQ(13, fork_function(10, std::cerr
, [&]() { return 13; }));
296 ASSERT_EQ(-1, fork_function(10, std::cerr
, [&]() { return -1; }));
297 ASSERT_EQ(-13, fork_function(10, std::cerr
, [&]() { return -13; }));
298 ASSERT_EQ(-ETIMEDOUT
,
299 fork_function(10, std::cerr
, [&]() { return -ETIMEDOUT
; }));
302 TEST(fork_function
, timeout
)
304 ASSERT_EQ(-ETIMEDOUT
, fork_function(2, std::cerr
, [&]() {
307 ASSERT_EQ(-ETIMEDOUT
, fork_function(2, std::cerr
, [&]() {
310 ASSERT_EQ(-ETIMEDOUT
, fork_function(2, std::cerr
, [&]() {