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>
24 #include <boost/algorithm/string/predicate.hpp>
29 namespace bp
= boost::process
;
31 BOOST_AUTO_TEST_CASE(async_wait
, *boost::unit_test::timeout(2))
33 using boost::unit_test::framework::master_test_suite
;
34 using namespace boost::asio
;
36 boost::asio::io_context io_context
;
40 bool exit_called_for_c1
= false;
43 master_test_suite().argv
[1],
44 "test", "--exit-code", "123",
47 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
49 BOOST_CHECK(!exit_called_for_c1
);
50 exit_code_c1
= exit
; exit_called_for_c1
=true;
56 bool exit_called_for_c2
= false;
59 master_test_suite().argv
[1],
60 "test", "--exit-code", "21",
63 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
65 BOOST_CHECK(!exit_called_for_c2
);
66 exit_code_c2
= exit
; exit_called_for_c2
=true;
74 BOOST_CHECK(exit_called_for_c1
);
75 BOOST_CHECK_EQUAL(exit_code_c1
, 123);
76 BOOST_CHECK_EQUAL(c1
.exit_code(), 123);
78 BOOST_CHECK(exit_called_for_c2
);
79 BOOST_CHECK_EQUAL(exit_code_c2
, 21);
80 BOOST_CHECK_EQUAL(c2
.exit_code(), 21);
83 BOOST_AUTO_TEST_CASE(async_wait_sync_wait
, *boost::unit_test::timeout(3))
85 using boost::unit_test::framework::master_test_suite
;
86 using namespace boost::asio
;
88 boost::asio::io_context io_context
;
90 bool exit_called
= false;
94 master_test_suite().argv
[1],
95 "test", "--exit-code", "1",
101 master_test_suite().argv
[1],
102 "test", "--exit-code", "2", "--wait", "1",
105 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
107 exit_code
= exit
; exit_called
=true;
114 // Regression test for #143: make sure the async SIGCHLD handler on POSIX does not reap the
115 // child c1 is watching (this will error if so)
119 BOOST_CHECK(exit_called
);
120 BOOST_CHECK_EQUAL(exit_code
, 2);
121 BOOST_CHECK_EQUAL(c2
.exit_code(), 2);
124 BOOST_AUTO_TEST_CASE(async_wait_different_contexts
, *boost::unit_test::timeout(3))
126 using boost::unit_test::framework::master_test_suite
;
127 using namespace boost::asio
;
129 boost::asio::io_context io_context1
;
130 boost::asio::io_context io_context2
;
134 bool exit_called_for_c1
= false;
135 int exit_code_c1
= 0;
137 master_test_suite().argv
[1],
138 "test", "--exit-code", "1",
141 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
143 BOOST_CHECK(!exit_called_for_c1
);
144 exit_code_c1
= exit
; exit_called_for_c1
=true;
150 bool exit_called_for_c2
= false;
151 int exit_code_c2
= 0;
153 master_test_suite().argv
[1],
154 "test", "--exit-code", "2", "--wait", "1",
157 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
159 BOOST_CHECK(!exit_called_for_c2
);
160 exit_code_c2
= exit
; exit_called_for_c2
=true;
166 // Regression test for #143: make sure each io_context handles its own children
172 BOOST_CHECK(exit_called_for_c1
);
173 BOOST_CHECK_EQUAL(exit_code_c1
, 1);
174 BOOST_CHECK_EQUAL(c1
.exit_code(), 1);
175 BOOST_CHECK(exit_called_for_c2
);
176 BOOST_CHECK_EQUAL(exit_code_c2
, 2);
177 BOOST_CHECK_EQUAL(c2
.exit_code(), 2);
180 BOOST_AUTO_TEST_CASE(async_wait_abort
, *boost::unit_test::timeout(2))
182 using boost::unit_test::framework::master_test_suite
;
183 using namespace boost::asio
;
185 boost::asio::io_context io_context
;
189 bool exit_called
= false;
192 master_test_suite().argv
[1],
196 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
198 BOOST_CHECK(!exit_called
);
199 exit_code
= exit
; exit_called
=true;
200 BOOST_TEST_MESSAGE(ec_in
.message());
208 BOOST_CHECK(exit_called
);
209 BOOST_CHECK(exit_code
!= 0);
210 BOOST_CHECK_EQUAL(c
.exit_code(), exit_code
);
214 BOOST_AUTO_TEST_CASE(async_future
, *boost::unit_test::timeout(2))
216 using boost::unit_test::framework::master_test_suite
;
217 using namespace boost::asio
;
219 boost::asio::io_context io_context
;
222 std::future
<int> fut
;
224 master_test_suite().argv
[1],
225 "test", "--exit-code", "42",
233 BOOST_REQUIRE(fut
.valid());
234 BOOST_CHECK_EQUAL(fut
.get(), 42);
238 BOOST_AUTO_TEST_CASE(async_out_stream
, *boost::unit_test::timeout(2))
240 using boost::unit_test::framework::master_test_suite
;
242 boost::asio::io_context io_context
;
247 boost::asio::streambuf buf
;
249 bp::child
c(master_test_suite().argv
[1],
250 "test", "--echo-stdout", "abc",
258 std::istream
istr(&buf
);
261 std::getline(istr
, line
);
262 BOOST_REQUIRE_GE(line
.size(), 3);
263 BOOST_CHECK(boost::algorithm::starts_with(line
, "abc"));
269 BOOST_AUTO_TEST_CASE(async_in_stream
, *boost::unit_test::timeout(2))
272 using boost::unit_test::framework::master_test_suite
;
274 boost::asio::io_context io_context
;
279 boost::asio::streambuf buf
;
280 boost::asio::streambuf in_buf
;
283 std::ostream
ostr(&in_buf
);
284 ostr
<< "-string" << endl
;
287 master_test_suite().argv
[1],
288 "test", "--prefix-once", "test",
298 std::istream
istr(&buf
);
301 std::getline(istr
, line
);
303 std::string val
= "test-string";
304 BOOST_REQUIRE_GE(line
.size(), val
.size());
306 BOOST_CHECK(boost::algorithm::starts_with(line
, val
));
313 BOOST_AUTO_TEST_CASE(async_error
, *boost::unit_test::timeout(2))
315 using boost::unit_test::framework::master_test_suite
;
316 using namespace boost::asio
;
318 boost::asio::io_context io_context
;
320 bool exit_called
= false;
326 bp::on_exit([&](int exit
, const std::error_code
& ec_in
)
334 BOOST_CHECK(!exit_called
);