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/args.hpp> 18 #include <boost/process/async.hpp> 19 20 #include <system_error> 21 #include <boost/system/error_code.hpp> 22 #include <boost/filesystem.hpp> 23 24 #include <boost/asio.hpp> 25 #include <string> 26 #include <cstdlib> 27 #include <iostream> 28 #include <thread> 29 30 #include <boost/config.hpp> 31 32 BOOST_AUTO_TEST_SUITE( bind_stdin ); 33 34 #if defined(BOOST_WINDOWS_API) 35 # include <windows.h> 36 typedef boost::asio::windows::stream_handle pipe_end; 37 #elif defined(BOOST_POSIX_API) 38 # include <sys/wait.h> 39 # include <unistd.h> 40 typedef boost::asio::posix::stream_descriptor pipe_end; 41 #endif 42 43 44 namespace fs = boost::filesystem; 45 namespace bp = boost::process; 46 47 BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(10)) 48 { 49 std::cout << "sync_io" << std::endl; 50 using boost::unit_test::framework::master_test_suite; 51 52 bp::opstream os; 53 bp::ipstream is; 54 55 std::error_code ec; 56 57 bp::child c( 58 master_test_suite().argv[1], 59 bp::args+={"test", "--prefix", "abc"}, 60 bp::std_in <os, 61 bp::std_out>is, 62 ec); 63 64 BOOST_REQUIRE(!ec); 65 66 67 68 os << "hello" << std::endl; 69 70 std::string s; 71 72 73 is >> s; 74 BOOST_CHECK_EQUAL(s, "abchello"); 75 os << 123 << std::endl; 76 is >> s; 77 BOOST_CHECK_EQUAL(s, "abc123"); 78 os << 3.1415 << std::endl; 79 is >> s; 80 BOOST_CHECK_EQUAL(s, "abc3.1415"); 81 82 c.terminate(); 83 c.wait(); 84 85 86 std::this_thread::sleep_for(std::chrono::milliseconds(100)); 87 88 int i = -1; 89 is >> i; 90 BOOST_CHECK(is.eof()); 91 BOOST_CHECK(!is); 92 } 93 94 95 struct write_handler 96 { 97 bp::ipstream &is_; 98 write_handlerwrite_handler99 write_handler(bp::ipstream &is) : is_(is) {} 100 operator ()write_handler101 void operator()(const boost::system::error_code &ec, std::size_t size) 102 { 103 BOOST_REQUIRE_EQUAL(6u, size); 104 std::string s; 105 is_ >> s; 106 BOOST_CHECK_EQUAL(s, "abchello"); 107 } 108 }; 109 110 BOOST_AUTO_TEST_CASE(async_io, *boost::unit_test::timeout(2)) 111 { 112 std::cout << "async_io" << std::endl; 113 using boost::unit_test::framework::master_test_suite; 114 115 boost::asio::io_context io_context; 116 117 bp::async_pipe p1(io_context); 118 bp::ipstream is; 119 120 boost::asio::streambuf sb; 121 std::ostream os(&sb); 122 123 std::error_code ec; 124 bp::child c( 125 master_test_suite().argv[1], 126 "test", "--prefix-once", "abc", 127 bp::std_in<p1, 128 bp::std_out>is, 129 ec 130 ); 131 BOOST_REQUIRE(!ec); 132 133 os << "hello" << std::endl; 134 135 // std::string s = "hello\n"; 136 boost::asio::async_write(p1, sb, 137 write_handler(is)); 138 139 io_context.run(); 140 141 c.wait(); 142 } 143 144 BOOST_AUTO_TEST_CASE(nul, *boost::unit_test::timeout(2)) 145 { 146 std::cout << "nul" << std::endl; 147 148 using boost::unit_test::framework::master_test_suite; 149 150 std::error_code ec; 151 bp::child c( 152 master_test_suite().argv[1], 153 "test", "--is-nul-stdin", 154 bp::std_in<bp::null, 155 ec); 156 157 BOOST_REQUIRE(!ec); 158 159 c.wait(); 160 int exit_code = c.exit_code(); 161 #if defined(BOOST_WINDOWS_API) 162 BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); 163 #elif defined(BOOST_POSIX_API) 164 BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); 165 #endif 166 } 167 168 169 BOOST_AUTO_TEST_CASE(file_io, *boost::unit_test::timeout(2)) 170 { 171 std::cout << "file_io" << std::endl; 172 using boost::unit_test::framework::master_test_suite; 173 174 175 fs::path pth = 176 fs::path(master_test_suite().argv[1]).parent_path() / "std_in_log_file.txt"; 177 bp::ipstream is; 178 179 { 180 boost::filesystem::ofstream fs(pth); 181 fs << 321 << std::endl; 182 fs << 1.2345 << std::endl; 183 fs << "some_string" << std::endl; 184 } 185 std::error_code ec; 186 187 bp::child c( 188 master_test_suite().argv[1], 189 bp::args+={"test", "--prefix", "abc"}, 190 bp::std_in <pth, 191 bp::std_out>is, 192 ec); 193 194 BOOST_REQUIRE(!ec); 195 196 197 std::string s; 198 199 200 is >> s; 201 BOOST_CHECK_EQUAL(s, "abc321"); 202 is >> s; 203 BOOST_CHECK_EQUAL(s, "abc1.2345"); 204 is >> s; 205 BOOST_CHECK_EQUAL(s, "abcsome_string"); 206 207 c.wait(); 208 boost::filesystem::remove(pth); 209 } 210 211 BOOST_AUTO_TEST_CASE(file_io_C, *boost::unit_test::timeout(2)) 212 { 213 //tested, since stdin also yields FILE*. 214 std::cout << "file_io_C" << std::endl; 215 using boost::unit_test::framework::master_test_suite; 216 217 218 fs::path pth = 219 fs::path(master_test_suite().argv[1]).parent_path() / "std_in_log_file_2.txt"; 220 bp::ipstream is; 221 222 { 223 boost::filesystem::ofstream fs(pth); 224 fs << 321 << std::endl; 225 fs << 1.2345 << std::endl; 226 fs << "some_string" << std::endl; 227 } 228 229 FILE * f = fopen(pth.string().c_str(), "r+"); 230 231 BOOST_REQUIRE(f != nullptr); 232 std::error_code ec; 233 234 bp::child c( 235 master_test_suite().argv[1], 236 bp::args+={"test", "--prefix", "abc"}, 237 bp::std_in <f, 238 bp::std_out>is, 239 ec); 240 241 fclose(f); 242 243 BOOST_REQUIRE(!ec); 244 245 246 std::string s; 247 248 249 is >> s; 250 BOOST_CHECK_EQUAL(s, "abc321"); 251 is >> s; 252 BOOST_CHECK_EQUAL(s, "abc1.2345"); 253 is >> s; 254 BOOST_CHECK_EQUAL(s, "abcsome_string"); 255 256 c.wait(); 257 boost::filesystem::remove(pth); 258 } 259 260 BOOST_AUTO_TEST_SUITE_END();