]>
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 | |
11 | #define BOOST_TEST_IGNORE_SIGCHLD | |
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> | |
23 | ||
24 | #include <boost/algorithm/string/predicate.hpp> | |
25 | ||
26 | ||
27 | using namespace std; | |
28 | ||
29 | namespace bp = boost::process; | |
30 | ||
31 | BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(2)) | |
32 | { | |
33 | using boost::unit_test::framework::master_test_suite; | |
34 | using namespace boost::asio; | |
35 | ||
36 | boost::asio::io_context io_context; | |
37 | ||
11fdf7f2 TL |
38 | std::error_code ec; |
39 | ||
40 | bool exit_called_for_c1 = false; | |
41 | int exit_code_c1 = 0; | |
42 | bp::child c1( | |
43 | master_test_suite().argv[1], | |
44 | "test", "--exit-code", "123", | |
45 | ec, | |
46 | io_context, | |
47 | bp::on_exit([&](int exit, const std::error_code& ec_in) | |
48 | { | |
49 | BOOST_CHECK(!exit_called_for_c1); | |
50 | exit_code_c1 = exit; exit_called_for_c1=true; | |
51 | BOOST_CHECK(!ec_in); | |
52 | }) | |
53 | ); | |
54 | BOOST_REQUIRE(!ec); | |
55 | ||
56 | bool exit_called_for_c2 = false; | |
57 | int exit_code_c2 = 0; | |
58 | bp::child c2( | |
59 | master_test_suite().argv[1], | |
60 | "test", "--exit-code", "21", | |
61 | ec, | |
62 | io_context, | |
63 | bp::on_exit([&](int exit, const std::error_code& ec_in) | |
64 | { | |
65 | BOOST_CHECK(!exit_called_for_c2); | |
66 | exit_code_c2 = exit; exit_called_for_c2=true; | |
67 | BOOST_CHECK(!ec_in); | |
68 | }) | |
69 | ); | |
70 | BOOST_REQUIRE(!ec); | |
71 | ||
72 | io_context.run(); | |
73 | ||
74 | BOOST_CHECK(exit_called_for_c1); | |
75 | BOOST_CHECK_EQUAL(exit_code_c1, 123); | |
76 | BOOST_CHECK_EQUAL(c1.exit_code(), 123); | |
77 | ||
78 | BOOST_CHECK(exit_called_for_c2); | |
79 | BOOST_CHECK_EQUAL(exit_code_c2, 21); | |
80 | BOOST_CHECK_EQUAL(c2.exit_code(), 21); | |
81 | } | |
82 | ||
83 | BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(3)) | |
84 | { | |
85 | using boost::unit_test::framework::master_test_suite; | |
86 | using namespace boost::asio; | |
87 | ||
88 | boost::asio::io_context io_context; | |
89 | ||
b32b8144 FG |
90 | bool exit_called = false; |
91 | int exit_code = 0; | |
92 | std::error_code ec; | |
11fdf7f2 | 93 | bp::child c1( |
b32b8144 | 94 | master_test_suite().argv[1], |
11fdf7f2 TL |
95 | "test", "--exit-code", "1", |
96 | ec | |
97 | ); | |
98 | BOOST_REQUIRE(!ec); | |
99 | ||
100 | bp::child c2( | |
101 | master_test_suite().argv[1], | |
102 | "test", "--exit-code", "2", "--wait", "1", | |
b32b8144 FG |
103 | ec, |
104 | io_context, | |
105 | bp::on_exit([&](int exit, const std::error_code& ec_in) | |
106 | { | |
107 | exit_code = exit; exit_called=true; | |
108 | BOOST_CHECK(!ec_in); | |
109 | }) | |
110 | ); | |
11fdf7f2 TL |
111 | BOOST_REQUIRE(!ec); |
112 | ||
113 | io_context.run(); | |
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) | |
116 | c1.wait(ec); | |
117 | BOOST_REQUIRE(!ec); | |
118 | ||
119 | BOOST_CHECK(exit_called); | |
120 | BOOST_CHECK_EQUAL(exit_code, 2); | |
121 | BOOST_CHECK_EQUAL(c2.exit_code(), 2); | |
122 | } | |
123 | ||
124 | BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(3)) | |
125 | { | |
126 | using boost::unit_test::framework::master_test_suite; | |
127 | using namespace boost::asio; | |
128 | ||
129 | boost::asio::io_context io_context1; | |
130 | boost::asio::io_context io_context2; | |
131 | ||
132 | std::error_code ec; | |
133 | ||
134 | bool exit_called_for_c1 = false; | |
135 | int exit_code_c1 = 0; | |
136 | bp::child c1( | |
137 | master_test_suite().argv[1], | |
138 | "test", "--exit-code", "1", | |
139 | ec, | |
140 | io_context1, | |
141 | bp::on_exit([&](int exit, const std::error_code& ec_in) | |
142 | { | |
143 | BOOST_CHECK(!exit_called_for_c1); | |
144 | exit_code_c1 = exit; exit_called_for_c1=true; | |
145 | BOOST_CHECK(!ec_in); | |
146 | }) | |
147 | ); | |
148 | BOOST_REQUIRE(!ec); | |
149 | ||
150 | bool exit_called_for_c2 = false; | |
151 | int exit_code_c2 = 0; | |
152 | bp::child c2( | |
153 | master_test_suite().argv[1], | |
154 | "test", "--exit-code", "2", "--wait", "1", | |
155 | ec, | |
156 | io_context2, | |
157 | bp::on_exit([&](int exit, const std::error_code& ec_in) | |
158 | { | |
159 | BOOST_CHECK(!exit_called_for_c2); | |
160 | exit_code_c2 = exit; exit_called_for_c2=true; | |
161 | BOOST_CHECK(!ec_in); | |
162 | }) | |
163 | ); | |
164 | BOOST_REQUIRE(!ec); | |
b32b8144 | 165 | |
11fdf7f2 TL |
166 | // Regression test for #143: make sure each io_context handles its own children |
167 | io_context2.run(); | |
168 | io_context1.run(); | |
169 | c1.wait(ec); | |
b32b8144 | 170 | BOOST_REQUIRE(!ec); |
11fdf7f2 TL |
171 | |
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); | |
178 | } | |
179 | ||
180 | BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(2)) | |
181 | { | |
182 | using boost::unit_test::framework::master_test_suite; | |
183 | using namespace boost::asio; | |
184 | ||
185 | boost::asio::io_context io_context; | |
186 | ||
187 | std::error_code ec; | |
188 | ||
189 | bool exit_called = false; | |
190 | int exit_code = 0; | |
191 | bp::child c( | |
192 | master_test_suite().argv[1], | |
193 | "test", "--abort", | |
194 | ec, | |
195 | io_context, | |
196 | bp::on_exit([&](int exit, const std::error_code& ec_in) | |
197 | { | |
198 | BOOST_CHECK(!exit_called); | |
199 | exit_code = exit; exit_called=true; | |
200 | BOOST_TEST_MESSAGE(ec_in.message()); | |
201 | BOOST_CHECK(!ec_in); | |
202 | }) | |
203 | ); | |
204 | BOOST_REQUIRE(!ec); | |
205 | ||
b32b8144 | 206 | io_context.run(); |
11fdf7f2 | 207 | |
b32b8144 | 208 | BOOST_CHECK(exit_called); |
11fdf7f2 TL |
209 | BOOST_CHECK(exit_code != 0); |
210 | BOOST_CHECK_EQUAL(c.exit_code(), exit_code); | |
b32b8144 FG |
211 | } |
212 | ||
213 | ||
214 | BOOST_AUTO_TEST_CASE(async_future, *boost::unit_test::timeout(2)) | |
215 | { | |
216 | using boost::unit_test::framework::master_test_suite; | |
217 | using namespace boost::asio; | |
218 | ||
219 | boost::asio::io_context io_context; | |
220 | ||
221 | std::error_code ec; | |
222 | std::future<int> fut; | |
223 | bp::child c( | |
224 | master_test_suite().argv[1], | |
225 | "test", "--exit-code", "42", | |
226 | ec, | |
227 | io_context, | |
228 | bp::on_exit=fut | |
229 | ); | |
230 | ||
231 | BOOST_REQUIRE(!ec); | |
232 | io_context.run(); | |
233 | BOOST_REQUIRE(fut.valid()); | |
234 | BOOST_CHECK_EQUAL(fut.get(), 42); | |
235 | } | |
236 | ||
237 | ||
238 | BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(2)) | |
239 | { | |
240 | using boost::unit_test::framework::master_test_suite; | |
241 | ||
242 | boost::asio::io_context io_context; | |
243 | ||
244 | ||
245 | std::error_code ec; | |
246 | ||
247 | boost::asio::streambuf buf; | |
248 | ||
249 | bp::child c(master_test_suite().argv[1], | |
250 | "test", "--echo-stdout", "abc", | |
251 | bp::std_out > buf, | |
252 | io_context, | |
253 | ec); | |
254 | BOOST_REQUIRE(!ec); | |
255 | ||
256 | ||
257 | io_context.run(); | |
258 | std::istream istr(&buf); | |
259 | ||
260 | std::string line; | |
261 | std::getline(istr, line); | |
262 | BOOST_REQUIRE_GE(line.size(), 3); | |
263 | BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); | |
264 | c.wait(); | |
265 | } | |
266 | ||
267 | ||
268 | ||
269 | BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(2)) | |
270 | { | |
271 | ||
272 | using boost::unit_test::framework::master_test_suite; | |
273 | ||
274 | boost::asio::io_context io_context; | |
275 | ||
276 | ||
277 | std::error_code ec; | |
278 | ||
279 | boost::asio::streambuf buf; | |
280 | boost::asio::streambuf in_buf; | |
281 | ||
282 | ||
283 | std::ostream ostr(&in_buf); | |
284 | ostr << "-string" << endl ; | |
285 | ||
286 | bp::child c( | |
287 | master_test_suite().argv[1], | |
288 | "test", "--prefix-once", "test", | |
289 | bp::std_in < in_buf, | |
290 | bp::std_out > buf, | |
291 | io_context, | |
292 | ec | |
293 | ); | |
294 | BOOST_REQUIRE(!ec); | |
295 | ||
296 | ||
297 | io_context.run(); | |
298 | std::istream istr(&buf); | |
299 | ||
300 | std::string line; | |
301 | std::getline(istr, line); | |
302 | ||
303 | std::string val = "test-string"; | |
304 | BOOST_REQUIRE_GE(line.size(), val.size()); | |
305 | if (line >= val) | |
306 | BOOST_CHECK(boost::algorithm::starts_with(line, val)); | |
307 | ||
308 | ||
309 | c.wait(); | |
310 | } | |
311 | ||
312 | ||
313 | BOOST_AUTO_TEST_CASE(async_error, *boost::unit_test::timeout(2)) | |
314 | { | |
315 | using boost::unit_test::framework::master_test_suite; | |
316 | using namespace boost::asio; | |
317 | ||
318 | boost::asio::io_context io_context; | |
319 | ||
320 | bool exit_called = false; | |
321 | std::error_code ec; | |
322 | bp::child c( | |
323 | "doesn't exist", | |
324 | ec, | |
325 | io_context, | |
326 | bp::on_exit([&](int exit, const std::error_code& ec_in) | |
327 | { | |
328 | exit_called=true; | |
329 | }) | |
330 | ); | |
331 | ||
332 | BOOST_REQUIRE(ec); | |
333 | io_context.run(); | |
334 | BOOST_CHECK(!exit_called); | |
335 | } | |
336 |