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/io.hpp> 16 #include <boost/process/child.hpp> 17 #include <boost/process/exe.hpp> 18 #include <boost/process/args.hpp> 19 #include <boost/process/async_pipe.hpp> 20 21 #include <system_error> 22 23 #include <boost/system/error_code.hpp> 24 25 #include <boost/asio.hpp> 26 #include <boost/algorithm/string/predicate.hpp> 27 #include <string> 28 #include <istream> 29 #if defined(BOOST_WINDOWS_API) 30 # include <windows.h> 31 typedef boost::asio::windows::stream_handle pipe_end; 32 #elif defined(BOOST_POSIX_API) 33 typedef boost::asio::posix::stream_descriptor pipe_end; 34 #endif 35 36 namespace bp = boost::process; 37 38 BOOST_AUTO_TEST_SUITE( bind_stdout_stderr ); 39 40 41 BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(2)) 42 { 43 using boost::unit_test::framework::master_test_suite; 44 45 bp::pipe p1; 46 bp::pipe p2; 47 48 bp::ipstream is1; 49 bp::ipstream is2; 50 51 std::error_code ec; 52 bp::child c( 53 master_test_suite().argv[1], 54 "test", "--echo-stdout-stderr", "hello", 55 bp::std_out>is1, 56 bp::std_err>is2, 57 ec 58 ); 59 BOOST_REQUIRE(!ec); 60 61 62 63 std::string s; 64 is1 >> s; 65 BOOST_CHECK_EQUAL(s, "hello"); 66 67 is2 >> s; 68 BOOST_CHECK_EQUAL(s, "hello"); 69 } 70 71 72 struct read_handler 73 { 74 boost::asio::streambuf &buffer_; 75 read_handlerread_handler76 read_handler(boost::asio::streambuf &buffer) : buffer_(buffer) {} 77 operator ()read_handler78 void operator()(const boost::system::error_code &ec, std::size_t size) 79 { 80 BOOST_REQUIRE(!ec); 81 std::istream is(&buffer_); 82 std::string line; 83 std::getline(is, line); 84 BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); 85 } 86 }; 87 88 BOOST_AUTO_TEST_CASE(async_io, *boost::unit_test::timeout(2)) 89 { 90 using boost::unit_test::framework::master_test_suite; 91 boost::asio::io_context io_context; 92 93 bp::async_pipe p1(io_context); 94 bp::async_pipe p2(io_context); 95 96 std::error_code ec; 97 bp::child c( 98 master_test_suite().argv[1], 99 bp::args={"test", "--echo-stdout-stderr", "abc"}, 100 bp::std_out > p1, 101 bp::std_err > p2, 102 ec 103 ); 104 BOOST_REQUIRE(!ec); 105 106 boost::asio::streambuf buffer1; 107 boost::asio::async_read_until(p1, buffer1, '\n', 108 read_handler(buffer1)); 109 110 boost::asio::streambuf buffer2; 111 boost::asio::async_read_until(p2, buffer2, '\n', 112 read_handler(buffer2)); 113 114 io_context.run(); 115 } 116 117 BOOST_AUTO_TEST_CASE(nul, *boost::unit_test::timeout(2)) 118 { 119 using boost::unit_test::framework::master_test_suite; 120 std::error_code ec; 121 bp::child c( 122 bp::exe(master_test_suite().argv[1]), 123 bp::args+={"test", "--echo-stdout-stderr", "some string"}, 124 (bp::std_err & bp::std_out) > bp::null, 125 ec 126 ); 127 BOOST_REQUIRE(!ec); 128 129 c.wait(); 130 int exit_code = c.exit_code(); 131 #if defined(BOOST_WINDOWS_API) 132 BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); 133 #elif defined(BOOST_POSIX_API) 134 BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); 135 #endif 136 } 137 138 BOOST_AUTO_TEST_SUITE_END();