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/system/error_code.hpp> 15 16 #include <boost/asio.hpp> 17 #include <boost/algorithm/string/predicate.hpp> 18 19 #include <boost/process/error.hpp> 20 #include <boost/process/io.hpp> 21 #include <boost/process/args.hpp> 22 #include <boost/process/child.hpp> 23 #include <boost/process/async_pipe.hpp> 24 #include <system_error> 25 26 #include <boost/filesystem.hpp> 27 28 #include <string> 29 #include <istream> 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 BOOST_AUTO_TEST_SUITE( bind_stdout ); 41 42 43 namespace fs = boost::filesystem; 44 namespace bp = boost::process; 45 46 BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(5)) 47 { 48 using boost::unit_test::framework::master_test_suite; 49 50 bp::ipstream is; 51 std::error_code ec; 52 53 bp::child c( 54 master_test_suite().argv[1], 55 bp::args+={"test", "--echo-stdout", "hello"}, 56 bp::std_out > is, 57 ec 58 ); 59 60 BOOST_CHECK(!ec); 61 62 63 std::string s; 64 65 BOOST_TEST_CHECKPOINT("Starting read"); 66 is >> s; 67 BOOST_TEST_CHECKPOINT("Finished read"); 68 69 BOOST_CHECK_EQUAL(s, "hello"); 70 } 71 72 73 struct read_handler 74 { 75 boost::asio::streambuf &buffer_; 76 read_handlerread_handler77 read_handler(boost::asio::streambuf &buffer) : buffer_(buffer) {} 78 operator ()read_handler79 void operator()(const boost::system::error_code &ec, std::size_t size) 80 { 81 BOOST_REQUIRE(!ec); 82 std::istream is(&buffer_); 83 std::string line; 84 std::getline(is, line); 85 BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); 86 } 87 }; 88 89 BOOST_AUTO_TEST_CASE(async_io, *boost::unit_test::timeout(2)) 90 { 91 using boost::unit_test::framework::master_test_suite; 92 93 boost::asio::io_context io_context; 94 bp::async_pipe p(io_context); 95 96 std::error_code ec; 97 bp::child c( 98 master_test_suite().argv[1], 99 "test", "--echo-stdout", "abc", 100 bp::std_out > p, 101 ec 102 ); 103 BOOST_REQUIRE(!ec); 104 105 boost::asio::streambuf buffer; 106 boost::asio::async_read_until(p, buffer, '\n', 107 read_handler(buffer)); 108 109 io_context.run(); 110 } 111 112 BOOST_AUTO_TEST_CASE(nul, *boost::unit_test::timeout(2)) 113 { 114 using boost::unit_test::framework::master_test_suite; 115 116 117 std::error_code ec; 118 bp::child c( 119 master_test_suite().argv[1], 120 bp::args+={"test", "--is-nul-stdout"}, 121 bp::std_out>bp::null, 122 ec 123 ); 124 BOOST_REQUIRE(!ec); 125 126 c.wait(); 127 int exit_code = c.exit_code(); 128 #if defined(BOOST_WINDOWS_API) 129 BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); 130 #elif defined(BOOST_POSIX_API) 131 BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); 132 #endif 133 } 134 135 136 137 BOOST_AUTO_TEST_CASE(file_io, *boost::unit_test::timeout(2)) 138 { 139 using boost::unit_test::framework::master_test_suite; 140 141 fs::path pth = 142 fs::path(master_test_suite().argv[1]).parent_path() / "std_out_log_file.txt"; 143 144 145 FILE* f = fopen(pth.string().c_str(), "w"); 146 BOOST_REQUIRE(f != nullptr); 147 148 std::error_code ec; 149 bp::child c( 150 master_test_suite().argv[1], 151 bp::args={"test", "--echo-stdout", "hello"}, 152 bp::std_out>f, 153 ec 154 ); 155 BOOST_REQUIRE(!ec); 156 157 fclose(f); 158 159 c.wait(); 160 { 161 fs::ifstream is{pth}; 162 163 std::string s; 164 is >> s; 165 BOOST_CHECK_EQUAL(s, "hello"); 166 } 167 boost::filesystem::remove(pth); 168 169 } 170 171 BOOST_AUTO_TEST_SUITE_END();