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
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)
10 #define BOOST_TEST_MAIN
11 //#define BOOST_TEST_IGNORE_SIGCHLD
12 #include <boost/test/included/unit_test.hpp>
14 #include <boost/process/error.hpp>
15 #include <boost/process/async.hpp>
16 #include <boost/process/io.hpp>
17 #include <boost/process/child.hpp>
19 #include <boost/thread.hpp>
22 #include <boost/system/error_code.hpp>
23 #include <boost/algorithm/string/predicate.hpp>
24 #include <boost/asio/deadline_timer.hpp>
28 namespace bp
= boost::process
;
31 auto abort_sig
= signal(SIGALRM
, +[](int){std::terminate();});
34 BOOST_AUTO_TEST_SUITE( async
);
37 BOOST_AUTO_TEST_CASE(async_wait
, *boost::unit_test::timeout(5))
39 using boost::unit_test::framework::master_test_suite
;
40 using namespace boost::asio
;
42 boost::asio::io_context io_context
;
46 bool exit_called_for_c1
= false;
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();});
52 bp::child
c1(master_test_suite().argv
[1],
53 "test", "--exit-code", "123",
55 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
57 BOOST_CHECK(!exit_called_for_c1
);
58 exit_code_c1
= exit
; exit_called_for_c1
=true;
64 bool exit_called_for_c2
= false;
66 bp::child
c2(master_test_suite().argv
[1],
67 "test", "--exit-code", "21",
69 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
71 BOOST_CHECK(!exit_called_for_c2
);
72 exit_code_c2
= exit
; exit_called_for_c2
=true;
80 BOOST_CHECK(exit_called_for_c1
);
81 BOOST_CHECK_EQUAL(exit_code_c1
, 123);
82 BOOST_CHECK_EQUAL(c1
.exit_code(), 123);
84 BOOST_CHECK(exit_called_for_c2
);
85 BOOST_CHECK_EQUAL(exit_code_c2
, 21);
86 BOOST_CHECK_EQUAL(c2
.exit_code(), 21);
89 BOOST_AUTO_TEST_CASE(async_wait_sync_wait
, *boost::unit_test::timeout(5))
91 using boost::unit_test::framework::master_test_suite
;
92 using namespace boost::asio
;
94 boost::asio::io_context io_context
;
96 bool exit_called
= false;
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();});
104 master_test_suite().argv
[1],
105 "test", "--exit-code", "1",
111 master_test_suite().argv
[1],
112 "test", "--exit-code", "2", "--wait", "1",
115 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
117 exit_code
= exit
; exit_called
=true;
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)
130 BOOST_CHECK(exit_called
);
131 BOOST_CHECK_EQUAL(exit_code
, 2);
132 BOOST_CHECK_EQUAL(c2
.exit_code(), 2);
135 BOOST_AUTO_TEST_CASE(async_wait_different_contexts
, *boost::unit_test::timeout(10))
137 using boost::unit_test::framework::master_test_suite
;
138 using namespace boost::asio
;
140 boost::asio::io_context io_context1
;
141 boost::asio::io_context io_context2
;
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();});
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();});
150 bool exit_called_for_c1
= false;
151 int exit_code_c1
= 0;
153 master_test_suite().argv
[1],
154 "test", "--exit-code", "1",
157 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
159 BOOST_CHECK(!exit_called_for_c1
);
160 exit_code_c1
= exit
; exit_called_for_c1
=true;
167 bool exit_called_for_c2
= false;
168 int exit_code_c2
= 0;
170 master_test_suite().argv
[1],
171 "test", "--exit-code", "2", "--wait", "4",
174 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
176 BOOST_CHECK(!exit_called_for_c2
);
177 exit_code_c2
= exit
; exit_called_for_c2
=true;
184 // Regression test for #143: make sure each io_context handles its own children
185 std::thread thr1
{[&]{io_context1
.run();}};
186 std::thread thr2
{[&]{io_context2
.run();}};
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);
201 BOOST_AUTO_TEST_CASE(async_wait_abort
, *boost::unit_test::timeout(5))
203 using boost::unit_test::framework::master_test_suite
;
204 using namespace boost::asio
;
206 boost::asio::io_context io_context
;
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();});
213 bool exit_called
= false;
216 master_test_suite().argv
[1],
220 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
222 BOOST_CHECK(!exit_called
);
225 BOOST_TEST_MESSAGE(ec_in
.message());
234 BOOST_CHECK(exit_called
);
235 BOOST_CHECK_NE(exit_code
, 0);
236 BOOST_CHECK_EQUAL(c
.exit_code(), exit_code
);
240 BOOST_AUTO_TEST_CASE(async_future
, *boost::unit_test::timeout(3))
242 using boost::unit_test::framework::master_test_suite
;
243 using namespace boost::asio
;
245 boost::asio::io_context io_context
;
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();});
251 std::future
<int> fut
;
253 master_test_suite().argv
[1],
254 "test", "--exit-code", "42",
264 BOOST_REQUIRE(fut
.valid());
265 BOOST_CHECK_EQUAL(fut
.get(), 42);
269 BOOST_AUTO_TEST_CASE(async_out_stream
, *boost::unit_test::timeout(5))
271 using boost::unit_test::framework::master_test_suite
;
273 boost::asio::io_context io_context
;
278 boost::asio::streambuf buf
;
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();});
283 bp::child
c(master_test_suite().argv
[1],
284 "test", "--echo-stdout", "abc",
292 std::istream
istr(&buf
);
295 std::getline(istr
, line
);
296 BOOST_REQUIRE_GE(line
.size(), 3u);
297 BOOST_CHECK(boost::algorithm::starts_with(line
, "abc"));
303 BOOST_AUTO_TEST_CASE(async_in_stream
, *boost::unit_test::timeout(5))
306 using boost::unit_test::framework::master_test_suite
;
308 boost::asio::io_context io_context
;
313 boost::asio::streambuf buf
;
314 boost::asio::streambuf in_buf
;
317 std::ostream
ostr(&in_buf
);
318 ostr
<< "-string" << endl
;
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();});
324 master_test_suite().argv
[1],
325 "test", "--prefix-once", "test",
335 std::istream
istr(&buf
);
338 std::getline(istr
, line
);
340 std::string val
= "test-string";
341 BOOST_REQUIRE_GE(line
.size(), val
.size());
343 BOOST_CHECK(boost::algorithm::starts_with(line
, val
));
350 BOOST_AUTO_TEST_CASE(async_error
, *boost::unit_test::timeout(3))
352 using boost::unit_test::framework::master_test_suite
;
353 using namespace boost::asio
;
355 boost::asio::io_context io_context
;
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();});
360 bool exit_called
= false;
366 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
376 BOOST_CHECK(!exit_called
);
381 BOOST_AUTO_TEST_CASE(mixed_async, *boost::unit_test::timeout(5))
383 using boost::unit_test::framework::master_test_suite;
384 using namespace boost::asio;
386 boost::asio::io_context io_context;
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();});
391 bool exit_called = false;
394 bp::child c(master_test_suite().argv[1],
395 "--wait", "1", "--exit-code", "42",
398 bp::on_exit([&](int exit, const std::error_code& ec_in)
402 BOOST_CHECK_EQUAL(exit, 42);
407 std::thread thr([&]{c.wait();});
410 BOOST_CHECK(exit_called);
411 BOOST_CHECK_EQUAL(c.exit_code(), 42);
416 BOOST_AUTO_TEST_SUITE_END();