]>
Commit | Line | Data |
---|---|---|
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 | |
26 | using namespace std; | |
27 | ||
28 | namespace bp = boost::process; | |
29 | ||
92f5a8d4 TL |
30 | #if __APPLE__ |
31 | auto abort_sig = signal(SIGALRM, +[](int){std::terminate();}); | |
32 | #endif | |
33 | ||
34 | BOOST_AUTO_TEST_SUITE( async ); | |
35 | ||
36 | ||
37 | BOOST_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 | 89 | BOOST_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 | 135 | BOOST_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 | 201 | BOOST_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 | 240 | BOOST_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 | 269 | BOOST_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 | 303 | BOOST_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 | 350 | BOOST_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 | /* | |
381 | BOOST_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 | ||
416 | BOOST_AUTO_TEST_SUITE_END(); |