]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/process/test/async.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / process / test / async.cpp
CommitLineData
b32b8144
FG
1// Copyright (c) 2006, 2007 Julio M. Merino Vidal
2// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
3// Copyright (c) 2009 Boris Schaeling
4// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
5// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9
10#define BOOST_TEST_MAIN
92f5a8d4 11//#define BOOST_TEST_IGNORE_SIGCHLD
b32b8144
FG
12#include <boost/test/included/unit_test.hpp>
13
14#include <boost/process/error.hpp>
15#include <boost/process/async.hpp>
16#include <boost/process/io.hpp>
17#include <boost/process/child.hpp>
18
19#include <boost/thread.hpp>
20#include <future>
21
22#include <boost/system/error_code.hpp>
b32b8144 23#include <boost/algorithm/string/predicate.hpp>
92f5a8d4 24#include <boost/asio/deadline_timer.hpp>
b32b8144
FG
25
26using namespace std;
27
28namespace bp = boost::process;
29
92f5a8d4
TL
30#if __APPLE__
31auto abort_sig = signal(SIGALRM, +[](int){std::terminate();});
32#endif
33
34BOOST_AUTO_TEST_SUITE( async );
35
36
37BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(5))
b32b8144
FG
38{
39 using boost::unit_test::framework::master_test_suite;
40 using namespace boost::asio;
41
42 boost::asio::io_context io_context;
43
11fdf7f2
TL
44 std::error_code ec;
45
46 bool exit_called_for_c1 = false;
47 int exit_code_c1 = 0;
92f5a8d4
TL
48
49 boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
50 timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
51
52 bp::child c1(master_test_suite().argv[1],
53 "test", "--exit-code", "123",
54 ec, io_context,
55 bp::on_exit([&](int exit, const std::error_code& ec_in)
56 {
57 BOOST_CHECK(!exit_called_for_c1);
58 exit_code_c1 = exit; exit_called_for_c1=true;
59 BOOST_CHECK(!ec_in);
60 timeout.cancel();
61 }));
11fdf7f2
TL
62 BOOST_REQUIRE(!ec);
63
64 bool exit_called_for_c2 = false;
65 int exit_code_c2 = 0;
92f5a8d4
TL
66 bp::child c2(master_test_suite().argv[1],
67 "test", "--exit-code", "21",
68 ec, io_context,
69 bp::on_exit([&](int exit, const std::error_code& ec_in)
70 {
71 BOOST_CHECK(!exit_called_for_c2);
72 exit_code_c2 = exit; exit_called_for_c2=true;
73 BOOST_CHECK(!ec_in);
74 })
75 );
11fdf7f2
TL
76 BOOST_REQUIRE(!ec);
77
78 io_context.run();
79
80 BOOST_CHECK(exit_called_for_c1);
81 BOOST_CHECK_EQUAL(exit_code_c1, 123);
82 BOOST_CHECK_EQUAL(c1.exit_code(), 123);
83
84 BOOST_CHECK(exit_called_for_c2);
85 BOOST_CHECK_EQUAL(exit_code_c2, 21);
86 BOOST_CHECK_EQUAL(c2.exit_code(), 21);
87}
88
92f5a8d4 89BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(5))
11fdf7f2
TL
90{
91 using boost::unit_test::framework::master_test_suite;
92 using namespace boost::asio;
93
94 boost::asio::io_context io_context;
95
b32b8144
FG
96 bool exit_called = false;
97 int exit_code = 0;
98 std::error_code ec;
92f5a8d4
TL
99
100 boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(3)};
101 timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
102
11fdf7f2 103 bp::child c1(
b32b8144 104 master_test_suite().argv[1],
11fdf7f2
TL
105 "test", "--exit-code", "1",
106 ec
107 );
108 BOOST_REQUIRE(!ec);
109
110 bp::child c2(
111 master_test_suite().argv[1],
112 "test", "--exit-code", "2", "--wait", "1",
b32b8144
FG
113 ec,
114 io_context,
115 bp::on_exit([&](int exit, const std::error_code& ec_in)
116 {
117 exit_code = exit; exit_called=true;
118 BOOST_CHECK(!ec_in);
92f5a8d4 119 timeout.cancel();
b32b8144
FG
120 })
121 );
11fdf7f2
TL
122 BOOST_REQUIRE(!ec);
123
124 io_context.run();
125 // Regression test for #143: make sure the async SIGCHLD handler on POSIX does not reap the
126 // child c1 is watching (this will error if so)
127 c1.wait(ec);
128 BOOST_REQUIRE(!ec);
129
130 BOOST_CHECK(exit_called);
131 BOOST_CHECK_EQUAL(exit_code, 2);
132 BOOST_CHECK_EQUAL(c2.exit_code(), 2);
133}
134
92f5a8d4 135BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(10))
11fdf7f2
TL
136{
137 using boost::unit_test::framework::master_test_suite;
138 using namespace boost::asio;
139
140 boost::asio::io_context io_context1;
141 boost::asio::io_context io_context2;
142
92f5a8d4
TL
143 boost::asio::deadline_timer timeout1{io_context1, boost::posix_time::seconds(2)};
144 timeout1.async_wait([&](boost::system::error_code ec){if (!ec) io_context1.stop();});
145
146 boost::asio::deadline_timer timeout2{io_context2, boost::posix_time::seconds(7)};
147 timeout2.async_wait([&](boost::system::error_code ec){if (!ec) io_context2.stop();});
11fdf7f2
TL
148 std::error_code ec;
149
150 bool exit_called_for_c1 = false;
151 int exit_code_c1 = 0;
152 bp::child c1(
153 master_test_suite().argv[1],
154 "test", "--exit-code", "1",
155 ec,
156 io_context1,
157 bp::on_exit([&](int exit, const std::error_code& ec_in)
158 {
159 BOOST_CHECK(!exit_called_for_c1);
160 exit_code_c1 = exit; exit_called_for_c1=true;
161 BOOST_CHECK(!ec_in);
92f5a8d4 162 timeout1.cancel();
11fdf7f2
TL
163 })
164 );
165 BOOST_REQUIRE(!ec);
166
167 bool exit_called_for_c2 = false;
168 int exit_code_c2 = 0;
169 bp::child c2(
170 master_test_suite().argv[1],
92f5a8d4 171 "test", "--exit-code", "2", "--wait", "4",
11fdf7f2
TL
172 ec,
173 io_context2,
174 bp::on_exit([&](int exit, const std::error_code& ec_in)
175 {
176 BOOST_CHECK(!exit_called_for_c2);
177 exit_code_c2 = exit; exit_called_for_c2=true;
178 BOOST_CHECK(!ec_in);
92f5a8d4 179 timeout2.cancel();
11fdf7f2
TL
180 })
181 );
182 BOOST_REQUIRE(!ec);
b32b8144 183
11fdf7f2 184 // Regression test for #143: make sure each io_context handles its own children
92f5a8d4
TL
185 std::thread thr1{[&]{io_context1.run();}};
186 std::thread thr2{[&]{io_context2.run();}};
187
188 thr1.join();
189 thr2.join();
11fdf7f2 190 c1.wait(ec);
b32b8144 191 BOOST_REQUIRE(!ec);
11fdf7f2
TL
192
193 BOOST_CHECK(exit_called_for_c1);
194 BOOST_CHECK_EQUAL(exit_code_c1, 1);
195 BOOST_CHECK_EQUAL(c1.exit_code(), 1);
196 BOOST_CHECK(exit_called_for_c2);
197 BOOST_CHECK_EQUAL(exit_code_c2, 2);
198 BOOST_CHECK_EQUAL(c2.exit_code(), 2);
199}
200
92f5a8d4 201BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(5))
11fdf7f2
TL
202{
203 using boost::unit_test::framework::master_test_suite;
204 using namespace boost::asio;
205
206 boost::asio::io_context io_context;
207
208 std::error_code ec;
209
92f5a8d4
TL
210 boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(5)};
211 timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
212
11fdf7f2
TL
213 bool exit_called = false;
214 int exit_code = 0;
215 bp::child c(
216 master_test_suite().argv[1],
217 "test", "--abort",
218 ec,
219 io_context,
220 bp::on_exit([&](int exit, const std::error_code& ec_in)
221 {
222 BOOST_CHECK(!exit_called);
92f5a8d4
TL
223 exit_code = exit;
224 exit_called=true;
11fdf7f2
TL
225 BOOST_TEST_MESSAGE(ec_in.message());
226 BOOST_CHECK(!ec_in);
92f5a8d4 227 timeout.cancel();
11fdf7f2
TL
228 })
229 );
230 BOOST_REQUIRE(!ec);
231
b32b8144 232 io_context.run();
11fdf7f2 233
b32b8144 234 BOOST_CHECK(exit_called);
92f5a8d4 235 BOOST_CHECK_NE(exit_code, 0);
11fdf7f2 236 BOOST_CHECK_EQUAL(c.exit_code(), exit_code);
b32b8144
FG
237}
238
239
92f5a8d4 240BOOST_AUTO_TEST_CASE(async_future, *boost::unit_test::timeout(3))
b32b8144
FG
241{
242 using boost::unit_test::framework::master_test_suite;
243 using namespace boost::asio;
244
245 boost::asio::io_context io_context;
246
92f5a8d4
TL
247 boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
248 timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
249
b32b8144
FG
250 std::error_code ec;
251 std::future<int> fut;
252 bp::child c(
253 master_test_suite().argv[1],
254 "test", "--exit-code", "42",
255 ec,
256 io_context,
257 bp::on_exit=fut
258 );
259
260 BOOST_REQUIRE(!ec);
92f5a8d4 261
b32b8144 262 io_context.run();
92f5a8d4 263
b32b8144
FG
264 BOOST_REQUIRE(fut.valid());
265 BOOST_CHECK_EQUAL(fut.get(), 42);
266}
267
268
92f5a8d4 269BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(5))
b32b8144
FG
270{
271 using boost::unit_test::framework::master_test_suite;
272
273 boost::asio::io_context io_context;
274
275
276 std::error_code ec;
277
278 boost::asio::streambuf buf;
279
92f5a8d4
TL
280 boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
281 timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
282
b32b8144
FG
283 bp::child c(master_test_suite().argv[1],
284 "test", "--echo-stdout", "abc",
285 bp::std_out > buf,
286 io_context,
287 ec);
288 BOOST_REQUIRE(!ec);
289
b32b8144 290 io_context.run();
92f5a8d4 291
b32b8144
FG
292 std::istream istr(&buf);
293
294 std::string line;
295 std::getline(istr, line);
296 BOOST_REQUIRE_GE(line.size(), 3);
297 BOOST_CHECK(boost::algorithm::starts_with(line, "abc"));
298 c.wait();
299}
300
301
302
92f5a8d4 303BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(5))
b32b8144
FG
304{
305
306 using boost::unit_test::framework::master_test_suite;
307
308 boost::asio::io_context io_context;
309
310
311 std::error_code ec;
312
313 boost::asio::streambuf buf;
314 boost::asio::streambuf in_buf;
315
316
317 std::ostream ostr(&in_buf);
318 ostr << "-string" << endl ;
319
92f5a8d4
TL
320 boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
321 timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
322
b32b8144
FG
323 bp::child c(
324 master_test_suite().argv[1],
325 "test", "--prefix-once", "test",
326 bp::std_in < in_buf,
327 bp::std_out > buf,
328 io_context,
329 ec
330 );
331 BOOST_REQUIRE(!ec);
332
b32b8144 333 io_context.run();
92f5a8d4 334
b32b8144
FG
335 std::istream istr(&buf);
336
337 std::string line;
338 std::getline(istr, line);
339
340 std::string val = "test-string";
341 BOOST_REQUIRE_GE(line.size(), val.size());
342 if (line >= val)
343 BOOST_CHECK(boost::algorithm::starts_with(line, val));
344
345
346 c.wait();
347}
348
349
92f5a8d4 350BOOST_AUTO_TEST_CASE(async_error, *boost::unit_test::timeout(3))
b32b8144
FG
351{
352 using boost::unit_test::framework::master_test_suite;
353 using namespace boost::asio;
354
355 boost::asio::io_context io_context;
356
92f5a8d4
TL
357 boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
358 timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
359
b32b8144
FG
360 bool exit_called = false;
361 std::error_code ec;
362 bp::child c(
363 "doesn't exist",
364 ec,
365 io_context,
366 bp::on_exit([&](int exit, const std::error_code& ec_in)
367 {
368 exit_called=true;
369 })
370 );
371
372 BOOST_REQUIRE(ec);
92f5a8d4 373
b32b8144 374 io_context.run();
92f5a8d4 375
b32b8144
FG
376 BOOST_CHECK(!exit_called);
377}
378
92f5a8d4
TL
379
380/*
381BOOST_AUTO_TEST_CASE(mixed_async, *boost::unit_test::timeout(5))
382{
383 using boost::unit_test::framework::master_test_suite;
384 using namespace boost::asio;
385
386 boost::asio::io_context io_context;
387
388 boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
389 timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
390
391 bool exit_called = false;
392 std::error_code ec;
393
394 bp::child c(master_test_suite().argv[1],
395 "--wait", "1", "--exit-code", "42",
396 ec,
397 io_context,
398 bp::on_exit([&](int exit, const std::error_code& ec_in)
399 {
400 timeout.cancel();
401 exit_called=true;
402 BOOST_CHECK_EQUAL(exit, 42);
403 })
404 );
405
406 BOOST_REQUIRE(!ec);
407 std::thread thr([&]{c.wait();});
408 io_context.run();
409
410 BOOST_CHECK(exit_called);
411 BOOST_CHECK_EQUAL(c.exit_code(), 42);
412 thr.join();
413
414}*/
415
416BOOST_AUTO_TEST_SUITE_END();