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