Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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
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"
24 #include "common/fork_function.h"
25
26 bool 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
37 TEST(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
45 TEST(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
53 TEST(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
65 TEST(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
79 TEST(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
98 TEST(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
113 TEST(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
124 TEST(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
146 TEST(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
171 TEST(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
179 TEST(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
189 TEST(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
205 TEST(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
220 TEST(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
240 TEST(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
257 TEST(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 }
270
271 TEST(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
282 TEST(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 }