diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/process/test | |
parent | Initial commit. (diff) | |
download | ceph-upstream/16.2.11+ds.tar.xz ceph-upstream/16.2.11+ds.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/process/test')
59 files changed, 6130 insertions, 0 deletions
diff --git a/src/boost/libs/process/test/Jamfile.jam b/src/boost/libs/process/test/Jamfile.jam new file mode 100644 index 000000000..329634cc0 --- /dev/null +++ b/src/boost/libs/process/test/Jamfile.jam @@ -0,0 +1,134 @@ +# Copyright (c) 2006, 2007 Julio M. Merino Vidal +# Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +# Copyright (c) 2009 Boris Schaeling +# Copyright (c) 2010 Felipe Tanus, Boris Schaeling +# Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +# Copyright (c) 2016 Klemens D. Morgenstern +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +import os ; + +if [ os.name ] = NT +{ + lib ws2_32 ; + lib shell32 ; + lib Advapi32 ; + lib Ntdll ; +} + +project : requirements + <define>BOOST_ASIO_NO_DEPRECATED + <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS + <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE + <toolset>msvc:<cxxflags>/bigobj + <target-os>windows:<define>WIN32_LEAN_AND_MEAN + <target-os>linux:<linkflags>-lpthread + <os>NT,<toolset>cw:<library>ws2_32 + <os>NT,<toolset>gcc:<library>ws2_32 +; + + + +import testing ; + + +alias program_options : /boost//program_options : <link>static ; +alias filesystem : /boost//filesystem ; +alias iostreams : /boost//iostreams ; +alias system : /boost//system ; +alias thread : /boost//thread ; +alias coroutine : /boost//coroutine : <link>static ; + +lib multi_ref : multi_ref1.cpp multi_ref2.cpp system : <target-os>windows:<source>shell32 ; + +exe sparring_partner : sparring_partner.cpp program_options system filesystem iostreams : + <warnings>off <target-os>windows:<source>shell32 <target-os>windows:<source>Ntdll + ; + +exe exit_argc : exit_argc.cpp : + <warnings>off <target-os>windows:<source>shell32 + ; + +exe sub_launch : sub_launcher.cpp program_options iostreams system filesystem : <warnings>off <target-os>windows:<source>shell32 ; + +rule test-options ( name ) +{ + if "--boost-process-report-ci" in [ modules.peek : ARGV ] + { + return --log_sink=log_$(name).xml --log_format=XML --log_level=error --report_sink=report_$(name).xml --report_format=XML --report_level=detailed -- ; + } + else + { + return --log_level=error --report_level=detailed -- ; + } + +} + + +test-suite bare : + [ run environment.cpp system filesystem : [ test-options environment ] ] + [ run async_pipe.cpp system filesystem : [ test-options async_pipe ] ] + [ run pipe.cpp system filesystem : [ test-options pipe ] ] + [ compile no_ansi_apps.cpp ] + [ compile-fail spawn_fail.cpp ] + [ compile-fail async_system_fail.cpp ] + [ compile asio_no_deprecated.cpp ] + ; + +test-suite with-valgrind : + [ run async.cpp system thread filesystem : [ test-options async ] : sparring_partner ] + [ run async_fut.cpp system thread filesystem : [ test-options async_fut ] : sparring_partner ] + [ run args_handling.cpp system thread filesystem : [ test-options args_handling ] : exit_argc ] + [ run args_cmd.cpp system filesystem : [ test-options args_cmd ] : sparring_partner ] + [ run wargs_cmd.cpp system filesystem : [ test-options wargs_cmd ] : sparring_partner ] + [ run bind_stderr.cpp filesystem : [ test-options bind_stderr ] : sparring_partner ] + [ run bind_stdin.cpp system filesystem : [ test-options bind_stdin ] : sparring_partner ] + [ run bind_stdin_stdout.cpp system filesystem : [ test-options bind_stdin_stdout ] : sparring_partner ] + [ run bind_stdout.cpp system filesystem : [ test-options bind_stdout ] : sparring_partner ] + [ run bind_stdout_stderr.cpp system filesystem : [ test-options bind_stdout_stderr ] : sparring_partner ] + [ run pipe_fwd.cpp system filesystem : [ test-options pipe_fwd ] : sparring_partner ] + [ run cmd_test.cpp system filesystem : [ test-options cmd_test ] : sparring_partner ] + [ run close_stderr.cpp system filesystem : [ test-options close_stderr ] : sparring_partner ] + [ run close_stdin.cpp system filesystem : [ test-options close_stdin ] : sparring_partner ] + [ run close_stdout.cpp system filesystem : [ test-options close_stdout ] : sparring_partner ] + [ run error.cpp system filesystem : [ test-options error ] : sparring_partner ] + [ run exit_code.cpp program_options system filesystem : [ test-options exit_code ] : sparring_partner ] + [ run extensions.cpp system filesystem : [ test-options extensions ] : sparring_partner ] + [ run env.cpp program_options system filesystem : [ test-options env ] : sparring_partner ] + [ run group.cpp system thread filesystem : [ test-options group ] : sub_launch ] + [ run group.cpp system thread filesystem : [ test-options group ] : sub_launch : <build>no <target-os>windows:<build>yes <define>BOOST_USE_WINDOWS_H=1 : group-windows-h ] + [ run group_wait.cpp system thread filesystem : [ test-options group_wait ] : sparring_partner ] + [ run limit_fd.cpp program_options system filesystem : [ test-options limit_fd ] : sparring_partner ] + [ run run_exe.cpp filesystem : : sparring_partner ] + [ run run_exe_path.cpp filesystem : [ test-options run_exe_path ] : sparring_partner ] + [ run search_path.cpp filesystem system : [ test-options search_path ] : : <target-os>windows:<source>shell32 ] + [ run shell.cpp filesystem system : [ test-options shell ] : sparring_partner ] + [ run shell_path.cpp filesystem system : [ test-options shell_path ] ] + [ run system_test1.cpp filesystem system : [ test-options system_test1 ] : sparring_partner ] + [ run system_test2.cpp filesystem system : [ test-options system_test2 ] : sparring_partner ] + [ run spawn.cpp filesystem system : [ test-options spawn ] : sparring_partner ] + [ run start_dir.cpp filesystem system : [ test-options start_dir ] : sparring_partner ] + [ run terminate.cpp system filesystem : [ test-options terminate ] : sparring_partner ] + [ run throw_on_error.cpp system filesystem : [ test-options throw_on_error ] : sparring_partner ] + [ run wait.cpp system filesystem : [ test-options wait ] : sparring_partner ] + [ run wait_for.cpp system filesystem : [ test-options wait_for ] : sparring_partner ] + [ run on_exit.cpp system filesystem : [ test-options on_exit ] : sparring_partner ] + [ run on_exit2.cpp system filesystem : [ test-options on_exit2 ] : sparring_partner ] + [ run on_exit3.cpp system filesystem : [ test-options on_exit3 ] : sparring_partner ] + [ run posix_specific.cpp system filesystem : [ test-options posix_specific ] : sparring_partner : <build>no <target-os>linux:<build>yes ] + [ run windows_specific.cpp filesystem system : [ test-options windows_specific ] : sparring_partner : <build>no <target-os>windows:<build>yes ] + : <dependency>bare ; + +test-suite without-valgrind : + [ run async_system_future.cpp filesystem system coroutine : [ test-options async_system_future ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ] + [ run async_system_stackful.cpp filesystem system coroutine : [ test-options async_system_stackful ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ] + [ run async_system_stackful_error.cpp filesystem system coroutine : [ test-options async_system_stackful_error ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ] + [ run async_system_stackful_except.cpp filesystem system coroutine : [ test-options async_system_stackful_except ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ] + [ run async_system_stackless.cpp filesystem system coroutine : [ test-options async_system_stackless ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ] + [ run vfork.cpp system filesystem : [ test-options vfork ] : sparring_partner : <build>no <target-os>linux:<build>yes ] + ; + + diff --git a/src/boost/libs/process/test/args_cmd.cpp b/src/boost/libs/process/test/args_cmd.cpp new file mode 100644 index 000000000..11700d216 --- /dev/null +++ b/src/boost/libs/process/test/args_cmd.cpp @@ -0,0 +1,116 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD + +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/exe.hpp> +#include <boost/process/args.hpp> +#include <boost/process/cmd.hpp> +#include <boost/process/io.hpp> +#include <boost/process/error.hpp> +#include <boost/process/child.hpp> + +#include <boost/algorithm/string/predicate.hpp> + +namespace bp = boost::process; + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(args, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::ipstream is; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--echo-argv", + bp::args+={"hello thingy", "\"stuff\""}, + bp::args+=" spa ce ", + bp::std_out>is, + ec + ); + if (ec) + std::cout << "EC: " << ec.message() << std::endl; + BOOST_REQUIRE(!ec); + + std::string s; + + std::getline(is, s); + s.resize(4); + BOOST_CHECK_EQUAL(s, "test"); + + std::getline(is, s); + s.resize(11); + BOOST_CHECK_EQUAL(s, "--echo-argv"); + + std::getline(is, s); + s.resize(12); + + BOOST_CHECK_EQUAL(s, "hello thingy"); + + std::getline(is, s); + s.resize(7); + + BOOST_CHECK_EQUAL(s, "\"stuff\""); + + std::getline(is, s); + s.resize(10); + + BOOST_CHECK_EQUAL(s, " spa ce "); + +} + + +BOOST_AUTO_TEST_CASE(cmd, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::ipstream is; + + std::error_code ec; + + std::string cmd = master_test_suite().argv[1]; + cmd+= " test --echo-argv \"hello thingy\" \\\"stuff\\\" \" spa ce \""; + + bp::child c(cmd, + bp::std_out>is, + ec + ); + BOOST_REQUIRE(!ec); + + std::string s; + + std::getline(is, s); + s.resize(4); + BOOST_CHECK_EQUAL(s, "test"); + + std::getline(is, s); + s.resize(11); + BOOST_CHECK_EQUAL(s, "--echo-argv"); + + std::getline(is, s); + s.resize(12); + + BOOST_CHECK_EQUAL(s, "hello thingy"); + + std::getline(is, s); + s.resize(7); + + BOOST_CHECK_EQUAL(s, "\"stuff\""); + + std::getline(is, s); + s.resize(10); + + BOOST_CHECK_EQUAL(s, " spa ce "); +} diff --git a/src/boost/libs/process/test/args_handling.cpp b/src/boost/libs/process/test/args_handling.cpp new file mode 100644 index 000000000..699659367 --- /dev/null +++ b/src/boost/libs/process/test/args_handling.cpp @@ -0,0 +1,79 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// Copyright (c) 2018 Oxford Nanopore Technologies +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <system_error> +#include <boost/filesystem.hpp> + +#include <boost/process/cmd.hpp> +#include <boost/process/error.hpp> +#include <boost/process/child.hpp> + +namespace bp = boost::process; + + +BOOST_AUTO_TEST_CASE(implicit_args_fs_path) +{ + using boost::unit_test::framework::master_test_suite; + + boost::filesystem::path exe = master_test_suite().argv[1]; + + std::error_code ec; + bp::child c( + exe, + ec + ); + BOOST_REQUIRE(!ec); + + c.wait(ec); + BOOST_REQUIRE(!ec); + + BOOST_CHECK(c.exit_code() == 1); // should pass at least exe! +} + +BOOST_AUTO_TEST_CASE(implicit_args_cmd) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + ec + ); + BOOST_REQUIRE(!ec); + + c.wait(ec); + BOOST_REQUIRE(!ec); + + BOOST_CHECK(c.exit_code() == 1); // should pass at least exe! +} + +BOOST_AUTO_TEST_CASE(explicit_args_fs_path) +{ + using boost::unit_test::framework::master_test_suite; + + boost::filesystem::path exe = master_test_suite().argv[1]; + + std::error_code ec; + bp::child c( + exe, + "hello", + ec + ); + BOOST_REQUIRE(!ec); + + c.wait(ec); + BOOST_REQUIRE(!ec); + + BOOST_CHECK(c.exit_code() == 2); // exe + "hello" +} diff --git a/src/boost/libs/process/test/asio_no_deprecated.cpp b/src/boost/libs/process/test/asio_no_deprecated.cpp new file mode 100644 index 000000000..45136c740 --- /dev/null +++ b/src/boost/libs/process/test/asio_no_deprecated.cpp @@ -0,0 +1,13 @@ +// +// Created by kleme on 26.02.2018. +// + +#define BOOST_ASIO_NO_DEPRECATED 1 +#include <boost/process.hpp> +int main() {} + +#if defined(BOOST_POSIX_API) +#include <boost/process/posix.hpp> +#else +#include <boost/process/windows.hpp> +#endif
\ No newline at end of file diff --git a/src/boost/libs/process/test/async.cpp b/src/boost/libs/process/test/async.cpp new file mode 100644 index 000000000..6767d44d9 --- /dev/null +++ b/src/boost/libs/process/test/async.cpp @@ -0,0 +1,416 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +//#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/async.hpp> +#include <boost/process/io.hpp> +#include <boost/process/child.hpp> + +#include <boost/thread.hpp> +#include <future> + +#include <boost/system/error_code.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <boost/asio/deadline_timer.hpp> + +using namespace std; + +namespace bp = boost::process; + +#if __APPLE__ +auto abort_sig = signal(SIGALRM, +[](int){std::terminate();}); +#endif + +BOOST_AUTO_TEST_SUITE( async ); + + +BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + boost::asio::io_context io_context; + + std::error_code ec; + + bool exit_called_for_c1 = false; + int exit_code_c1 = 0; + + boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)}; + timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();}); + + bp::child c1(master_test_suite().argv[1], + "test", "--exit-code", "123", + ec, io_context, + bp::on_exit([&](int exit, const std::error_code& ec_in) + { + BOOST_CHECK(!exit_called_for_c1); + exit_code_c1 = exit; exit_called_for_c1=true; + BOOST_CHECK(!ec_in); + timeout.cancel(); + })); + BOOST_REQUIRE(!ec); + + bool exit_called_for_c2 = false; + int exit_code_c2 = 0; + bp::child c2(master_test_suite().argv[1], + "test", "--exit-code", "21", + ec, io_context, + bp::on_exit([&](int exit, const std::error_code& ec_in) + { + BOOST_CHECK(!exit_called_for_c2); + exit_code_c2 = exit; exit_called_for_c2=true; + BOOST_CHECK(!ec_in); + }) + ); + BOOST_REQUIRE(!ec); + + io_context.run(); + + BOOST_CHECK(exit_called_for_c1); + BOOST_CHECK_EQUAL(exit_code_c1, 123); + BOOST_CHECK_EQUAL(c1.exit_code(), 123); + + BOOST_CHECK(exit_called_for_c2); + BOOST_CHECK_EQUAL(exit_code_c2, 21); + BOOST_CHECK_EQUAL(c2.exit_code(), 21); +} + +BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + boost::asio::io_context io_context; + + bool exit_called = false; + int exit_code = 0; + std::error_code ec; + + boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(3)}; + timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();}); + + bp::child c1( + master_test_suite().argv[1], + "test", "--exit-code", "1", + ec + ); + BOOST_REQUIRE(!ec); + + bp::child c2( + master_test_suite().argv[1], + "test", "--exit-code", "2", "--wait", "1", + ec, + io_context, + bp::on_exit([&](int exit, const std::error_code& ec_in) + { + exit_code = exit; exit_called=true; + BOOST_CHECK(!ec_in); + timeout.cancel(); + }) + ); + BOOST_REQUIRE(!ec); + + io_context.run(); + // Regression test for #143: make sure the async SIGCHLD handler on POSIX does not reap the + // child c1 is watching (this will error if so) + c1.wait(ec); + BOOST_REQUIRE(!ec); + + BOOST_CHECK(exit_called); + BOOST_CHECK_EQUAL(exit_code, 2); + BOOST_CHECK_EQUAL(c2.exit_code(), 2); +} + +BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(10)) +{ + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + boost::asio::io_context io_context1; + boost::asio::io_context io_context2; + + boost::asio::deadline_timer timeout1{io_context1, boost::posix_time::seconds(2)}; + timeout1.async_wait([&](boost::system::error_code ec){if (!ec) io_context1.stop();}); + + boost::asio::deadline_timer timeout2{io_context2, boost::posix_time::seconds(7)}; + timeout2.async_wait([&](boost::system::error_code ec){if (!ec) io_context2.stop();}); + std::error_code ec; + + bool exit_called_for_c1 = false; + int exit_code_c1 = 0; + bp::child c1( + master_test_suite().argv[1], + "test", "--exit-code", "1", + ec, + io_context1, + bp::on_exit([&](int exit, const std::error_code& ec_in) + { + BOOST_CHECK(!exit_called_for_c1); + exit_code_c1 = exit; exit_called_for_c1=true; + BOOST_CHECK(!ec_in); + timeout1.cancel(); + }) + ); + BOOST_REQUIRE(!ec); + + bool exit_called_for_c2 = false; + int exit_code_c2 = 0; + bp::child c2( + master_test_suite().argv[1], + "test", "--exit-code", "2", "--wait", "4", + ec, + io_context2, + bp::on_exit([&](int exit, const std::error_code& ec_in) + { + BOOST_CHECK(!exit_called_for_c2); + exit_code_c2 = exit; exit_called_for_c2=true; + BOOST_CHECK(!ec_in); + timeout2.cancel(); + }) + ); + BOOST_REQUIRE(!ec); + + // Regression test for #143: make sure each io_context handles its own children + std::thread thr1{[&]{io_context1.run();}}; + std::thread thr2{[&]{io_context2.run();}}; + + thr1.join(); + thr2.join(); + c1.wait(ec); + BOOST_REQUIRE(!ec); + + BOOST_CHECK(exit_called_for_c1); + BOOST_CHECK_EQUAL(exit_code_c1, 1); + BOOST_CHECK_EQUAL(c1.exit_code(), 1); + BOOST_CHECK(exit_called_for_c2); + BOOST_CHECK_EQUAL(exit_code_c2, 2); + BOOST_CHECK_EQUAL(c2.exit_code(), 2); +} + +BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + boost::asio::io_context io_context; + + std::error_code ec; + + boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(5)}; + timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();}); + + bool exit_called = false; + int exit_code = 0; + bp::child c( + master_test_suite().argv[1], + "test", "--abort", + ec, + io_context, + bp::on_exit([&](int exit, const std::error_code& ec_in) + { + BOOST_CHECK(!exit_called); + exit_code = exit; + exit_called=true; + BOOST_TEST_MESSAGE(ec_in.message()); + BOOST_CHECK(!ec_in); + timeout.cancel(); + }) + ); + BOOST_REQUIRE(!ec); + + io_context.run(); + + BOOST_CHECK(exit_called); + BOOST_CHECK_NE(exit_code, 0); + BOOST_CHECK_EQUAL(c.exit_code(), exit_code); +} + + +BOOST_AUTO_TEST_CASE(async_future, *boost::unit_test::timeout(3)) +{ + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + boost::asio::io_context io_context; + + boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)}; + timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();}); + + std::error_code ec; + std::future<int> fut; + bp::child c( + master_test_suite().argv[1], + "test", "--exit-code", "42", + ec, + io_context, + bp::on_exit=fut + ); + + BOOST_REQUIRE(!ec); + + io_context.run(); + + BOOST_REQUIRE(fut.valid()); + BOOST_CHECK_EQUAL(fut.get(), 42); +} + + +BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context io_context; + + + std::error_code ec; + + boost::asio::streambuf buf; + + boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)}; + timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();}); + + bp::child c(master_test_suite().argv[1], + "test", "--echo-stdout", "abc", + bp::std_out > buf, + io_context, + ec); + BOOST_REQUIRE(!ec); + + io_context.run(); + + std::istream istr(&buf); + + std::string line; + std::getline(istr, line); + BOOST_REQUIRE_GE(line.size(), 3); + BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); + c.wait(); +} + + + +BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(5)) +{ + + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context io_context; + + + std::error_code ec; + + boost::asio::streambuf buf; + boost::asio::streambuf in_buf; + + + std::ostream ostr(&in_buf); + ostr << "-string" << endl ; + + boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)}; + timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();}); + + bp::child c( + master_test_suite().argv[1], + "test", "--prefix-once", "test", + bp::std_in < in_buf, + bp::std_out > buf, + io_context, + ec + ); + BOOST_REQUIRE(!ec); + + io_context.run(); + + std::istream istr(&buf); + + std::string line; + std::getline(istr, line); + + std::string val = "test-string"; + BOOST_REQUIRE_GE(line.size(), val.size()); + if (line >= val) + BOOST_CHECK(boost::algorithm::starts_with(line, val)); + + + c.wait(); +} + + +BOOST_AUTO_TEST_CASE(async_error, *boost::unit_test::timeout(3)) +{ + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + boost::asio::io_context io_context; + + boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)}; + timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();}); + + bool exit_called = false; + std::error_code ec; + bp::child c( + "doesn't exist", + ec, + io_context, + bp::on_exit([&](int exit, const std::error_code& ec_in) + { + exit_called=true; + }) + ); + + BOOST_REQUIRE(ec); + + io_context.run(); + + BOOST_CHECK(!exit_called); +} + + +/* +BOOST_AUTO_TEST_CASE(mixed_async, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + boost::asio::io_context io_context; + + boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)}; + timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();}); + + bool exit_called = false; + std::error_code ec; + + bp::child c(master_test_suite().argv[1], + "--wait", "1", "--exit-code", "42", + ec, + io_context, + bp::on_exit([&](int exit, const std::error_code& ec_in) + { + timeout.cancel(); + exit_called=true; + BOOST_CHECK_EQUAL(exit, 42); + }) + ); + + BOOST_REQUIRE(!ec); + std::thread thr([&]{c.wait();}); + io_context.run(); + + BOOST_CHECK(exit_called); + BOOST_CHECK_EQUAL(c.exit_code(), 42); + thr.join(); + +}*/ + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/async_fut.cpp b/src/boost/libs/process/test/async_fut.cpp new file mode 100644 index 000000000..71945b3ed --- /dev/null +++ b/src/boost/libs/process/test/async_fut.cpp @@ -0,0 +1,106 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/async.hpp> +#include <boost/process/io.hpp> +#include <boost/process/spawn.hpp> +#include <boost/process/child.hpp> + +#include <boost/thread.hpp> +#include <future> + +#include <boost/system/error_code.hpp> + +#include <boost/algorithm/string/predicate.hpp> + +BOOST_AUTO_TEST_SUITE( async ); + + +using namespace std; + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(async_out_future, *boost::unit_test::timeout(2)) +{ + + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context io_context; + + + std::error_code ec; + + std::future<std::string> fut; + std::future<void> fut_in; + boost::asio::streambuf in_buf; + + + std::ostream ostr(&in_buf); + ostr << "-string" << endl ; + + bp::spawn( + master_test_suite().argv[1], + "test", "--prefix-once", "test", + bp::std_in < in_buf > fut_in, + bp::std_out > fut, + io_context, + ec + ); + BOOST_REQUIRE(!ec); + + + io_context.run(); + + BOOST_REQUIRE(fut.valid()); + BOOST_REQUIRE(fut_in.valid()); + BOOST_CHECK_NO_THROW(fut_in.get()); + + std::string line; + + BOOST_CHECK_NO_THROW(line = fut.get()); + + std::string val = "test-string"; + BOOST_REQUIRE_GE(line.size(), val.size()); + if (line >= val) + BOOST_CHECK(boost::algorithm::starts_with(line, val)); +} + + +BOOST_AUTO_TEST_CASE(emtpy_out, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context io_context; + + + std::error_code ec; + std::future<std::string> fut; + + bp::spawn( + master_test_suite().argv[1], + "test", "--exit-code", "0", + bp::std_out > fut, + io_context, + ec + ); + BOOST_REQUIRE(!ec); + + + io_context.run(); + + BOOST_REQUIRE(fut.valid()); + BOOST_CHECK_EQUAL(fut.get(), ""); +} + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/async_pipe.cpp b/src/boost/libs/process/test/async_pipe.cpp new file mode 100644 index 000000000..ef6cab4be --- /dev/null +++ b/src/boost/libs/process/test/async_pipe.cpp @@ -0,0 +1,147 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#define BOOST_TEST_MAIN + +#include <boost/test/included/unit_test.hpp> +#include <iostream> +#include <thread> +#include <vector> +#include <boost/algorithm/string/predicate.hpp> + +#include <boost/process/async_pipe.hpp> +#include <boost/process/pipe.hpp> +#include <boost/asio/read.hpp> +#include <boost/asio/read_until.hpp> +#include <boost/asio/write.hpp> +#include <boost/asio/streambuf.hpp> + +using namespace std; +namespace bp = boost::process; +namespace asio = boost::asio; + +BOOST_AUTO_TEST_SUITE( async ); + + +BOOST_AUTO_TEST_CASE(plain_async, *boost::unit_test::timeout(5)) +{ + asio::io_context ios; + bp::async_pipe pipe{ios}; + + std::string st = "test-string\n"; + + asio::streambuf buf; + + asio::async_write(pipe, asio::buffer(st), [](const boost::system::error_code &, std::size_t){}); + asio::async_read_until(pipe, buf, '\n', [](const boost::system::error_code &, std::size_t){}); + + ios.run(); + + std::string line; + std::istream istr(&buf); + BOOST_CHECK(std::getline(istr, line)); + + line.resize(11); + BOOST_CHECK_EQUAL(line, "test-string"); + +} + +BOOST_AUTO_TEST_CASE(closed_transform) +{ + asio::io_context ios; + + bp::async_pipe ap{ios}; + + BOOST_CHECK(ap.is_open()); + bp::pipe p2 = static_cast<bp::pipe>(ap); + BOOST_CHECK(p2.is_open()); + + ap.close(); + BOOST_CHECK(!ap.is_open()); + + bp::pipe p = static_cast<bp::pipe>(ap); + BOOST_CHECK(!p.is_open()); + +} + +BOOST_AUTO_TEST_CASE(multithreaded_async_pipe) +{ + asio::io_context ioc; + + std::vector<std::thread> threads; + for (int i = 0; i < std::thread::hardware_concurrency(); i++) + { + threads.emplace_back([&ioc] + { + std::vector<bp::async_pipe*> pipes; + for (size_t i = 0; i < 100; i++) + pipes.push_back(new bp::async_pipe(ioc)); + for (auto &p : pipes) + delete p; + }); + } + for (auto &t : threads) + t.join(); +} + + + +BOOST_AUTO_TEST_CASE(move_pipe) +{ + asio::io_context ios; + + bp::async_pipe ap{ios}; + BOOST_TEST_CHECKPOINT("First move"); + bp::async_pipe ap2{std::move(ap)}; +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(ap.native_source(), ::boost::winapi::INVALID_HANDLE_VALUE_); + BOOST_CHECK_EQUAL(ap.native_sink (), ::boost::winapi::INVALID_HANDLE_VALUE_); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(ap.native_source(), -1); + BOOST_CHECK_EQUAL(ap.native_sink (), -1); +#endif + + BOOST_TEST_CHECKPOINT("Second move"); + ap = std::move(ap2); + + { + BOOST_TEST_CHECKPOINT("Third move, from closed"); + bp::async_pipe ap_inv{ios}; + ap_inv.close(); + ap = std::move(ap_inv); + } + + { + BOOST_TEST_CHECKPOINT("Fourth move, from closed"); + bp::async_pipe ap_inv{ios}; + ap_inv.close(); + const auto ap3 = std::move(ap_inv); + } + + { + //copy an a closed pipe + BOOST_TEST_CHECKPOINT("Copy assign"); + BOOST_TEST_CHECKPOINT("Fourth move, from closed"); + bp::async_pipe ap_inv{ios}; + ap_inv.close(); + ap = ap_inv; //copy an invalid pipe + } + + { + //copy an a closed pipe + BOOST_TEST_CHECKPOINT("Copy assign"); + BOOST_TEST_CHECKPOINT("Fourth move, from closed"); + bp::async_pipe ap_inv{ios}; + ap_inv.close(); + BOOST_TEST_CHECKPOINT("Copy construct"); + bp::async_pipe ap4{ap_inv}; + } + + +} + + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/async_system_fail.cpp b/src/boost/libs/process/test/async_system_fail.cpp new file mode 100644 index 000000000..da6fea743 --- /dev/null +++ b/src/boost/libs/process/test/async_system_fail.cpp @@ -0,0 +1,28 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + + +#include <boost/asio.hpp> +#include <boost/asio/use_future.hpp> +#include <boost/process/error.hpp> +#include <boost/process/async_system.hpp> +#include <system_error> + +namespace bp = boost::process;; + +void fail_func() +{ + boost::asio::io_context ios; + + bp::async_system(ios, boost::asio::use_future, "foo", bp::ignore_error); +} diff --git a/src/boost/libs/process/test/async_system_future.cpp b/src/boost/libs/process/test/async_system_future.cpp new file mode 100644 index 000000000..816590ce2 --- /dev/null +++ b/src/boost/libs/process/test/async_system_future.cpp @@ -0,0 +1,64 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/async.hpp> +#include <boost/process/child.hpp> +#include <boost/process/async_system.hpp> + +#include <string> +#include <boost/asio/io_context.hpp> +#include <boost/asio/spawn.hpp> +#include <boost/asio/coroutine.hpp> +#include <boost/asio/use_future.hpp> +#include <boost/asio/yield.hpp> + +#include <vector> +#include <array> + +namespace bp = boost::process; +BOOST_AUTO_TEST_SUITE( async ); + +BOOST_AUTO_TEST_CASE(future, *boost::unit_test::timeout(15)) +{ + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context ios; + + std::future<int> fut = bp::async_system( + ios, boost::asio::use_future, + master_test_suite().argv[1], + "test", "--exit-code", "42"); + + ios.run(); + + int exit_code = 0; + BOOST_CHECK_NO_THROW(exit_code = fut.get()); + + BOOST_CHECK_EQUAL(exit_code, 42); +} + +BOOST_AUTO_TEST_CASE(future_error, *boost::unit_test::timeout(15)) +{ + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context ios; + + std::future<int> fut = bp::async_system( + ios, boost::asio::use_future, + "invalid-command"); + + ios.run(); + + int exit_code = 0; + BOOST_CHECK_THROW(exit_code = fut.get(), boost::system::system_error); +} + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/async_system_stackful.cpp b/src/boost/libs/process/test/async_system_stackful.cpp new file mode 100644 index 000000000..f88db2f69 --- /dev/null +++ b/src/boost/libs/process/test/async_system_stackful.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/async.hpp> +#include <boost/process/child.hpp> +#include <boost/process/async_system.hpp> + +#include <string> +#include <boost/asio/io_context.hpp> +#include <boost/asio/post.hpp> +#include <boost/asio/spawn.hpp> +#include <boost/asio/coroutine.hpp> +#include <boost/asio/strand.hpp> +#include <boost/asio/use_future.hpp> +#include <boost/asio/yield.hpp> + +#include <vector> +#include <array> +BOOST_AUTO_TEST_SUITE( async ); + +namespace bp = boost::process; +BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15)) +{ + using boost::unit_test::framework::master_test_suite; + + bool did_something_else = false; + + boost::asio::io_context ios; + auto stackful = + [&](boost::asio::yield_context yield_) + { + int ret = + bp::async_system( + ios, yield_, + master_test_suite().argv[1], + "test", "--exit-code", "123"); + + BOOST_CHECK_EQUAL(ret, 123); + BOOST_CHECK(did_something_else); + }; + + boost::asio::io_context::strand str{ios}; + boost::asio::post(str, [&]{boost::asio::spawn(ios, stackful);}); + boost::asio::post(str, [&]{did_something_else = true;}); + + ios.run(); + BOOST_CHECK(did_something_else); +} + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/async_system_stackful_error.cpp b/src/boost/libs/process/test/async_system_stackful_error.cpp new file mode 100644 index 000000000..0a34bf07d --- /dev/null +++ b/src/boost/libs/process/test/async_system_stackful_error.cpp @@ -0,0 +1,111 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/async.hpp> +#include <boost/process/child.hpp> +#include <boost/process/async_system.hpp> + +#include <string> +#include <boost/asio/io_context.hpp> +#include <boost/asio/post.hpp> +#include <boost/asio/spawn.hpp> +#include <boost/asio/coroutine.hpp> +#include <boost/asio/use_future.hpp> +#include <boost/asio/yield.hpp> + +#include <vector> +#include <array> +BOOST_AUTO_TEST_SUITE( async ); + +namespace bp = boost::process; +BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15)) +{ + using boost::unit_test::framework::master_test_suite; + + bool did_something_else = false; + + boost::asio::io_context ios; + auto stackful = + [&](boost::asio::yield_context yield_) + { + int ret = + bp::async_system( + ios, yield_, + master_test_suite().argv[1], + "test", "--exit-code", "123"); + + BOOST_CHECK_EQUAL(ret, 123); + BOOST_CHECK(did_something_else); + }; + + boost::asio::spawn(ios, stackful); + boost::asio::post(ios.get_executor(), [&]{did_something_else = true;}); + + ios.run(); + BOOST_CHECK(did_something_else); +} + +BOOST_AUTO_TEST_CASE(stackful_except, *boost::unit_test::timeout(15)) +{ + using boost::unit_test::framework::master_test_suite; + + bool did_something_else = false; + + boost::asio::io_context ios; + auto stackful = + [&](boost::asio::yield_context yield_) + { + + BOOST_CHECK_THROW( + bp::async_system( + ios, yield_, + "none-existing-exe"), boost::system::system_error); + + BOOST_CHECK(did_something_else); + }; + + boost::asio::spawn(ios, stackful); + boost::asio::post(ios.get_executor(), [&]{did_something_else = true;}); + ios.run(); + + BOOST_CHECK(did_something_else); +} + + +BOOST_AUTO_TEST_CASE(stackful_error, *boost::unit_test::timeout(15)) +{ + using boost::unit_test::framework::master_test_suite; + + bool did_something_else = false; + + boost::asio::io_context ios; + auto stackful = + [&](boost::asio::yield_context yield_) + { + boost::system::error_code ec; + auto ret = + bp::async_system( + ios, yield_[ec], + "none-existing-exe"); + + BOOST_CHECK(ec); + BOOST_CHECK_EQUAL(ret, -1); + BOOST_CHECK(did_something_else); + }; + + boost::asio::spawn(ios, stackful); + boost::asio::post(ios.get_executor(), [&]{did_something_else = true;}); + ios.run(); + + BOOST_CHECK(did_something_else); +} + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/async_system_stackful_except.cpp b/src/boost/libs/process/test/async_system_stackful_except.cpp new file mode 100644 index 000000000..224191ad7 --- /dev/null +++ b/src/boost/libs/process/test/async_system_stackful_except.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/async.hpp> +#include <boost/process/child.hpp> +#include <boost/process/async_system.hpp> + +#include <string> +#include <boost/asio/io_context.hpp> +#include <boost/asio/post.hpp> +#include <boost/asio/spawn.hpp> +#include <boost/asio/coroutine.hpp> +#include <boost/asio/use_future.hpp> +#include <boost/asio/yield.hpp> + +#include <vector> +#include <array> +BOOST_AUTO_TEST_SUITE( async ); + +namespace bp = boost::process; +BOOST_AUTO_TEST_CASE(stackful_except, *boost::unit_test::timeout(15)) +{ + using boost::unit_test::framework::master_test_suite; + + bool did_something_else = false; + + boost::asio::io_context ios; + auto stackful = + [&](boost::asio::yield_context yield_) + { + + BOOST_CHECK_THROW( + bp::async_system( + ios, yield_, + "none-existing-exe"), boost::system::system_error); + + BOOST_CHECK(did_something_else); + }; + + boost::asio::spawn(ios, stackful); + boost::asio::post(ios.get_executor(), [&]{did_something_else = true;}); + ios.run(); + + BOOST_CHECK(did_something_else); +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/boost/libs/process/test/async_system_stackless.cpp b/src/boost/libs/process/test/async_system_stackless.cpp new file mode 100644 index 000000000..8973469e0 --- /dev/null +++ b/src/boost/libs/process/test/async_system_stackless.cpp @@ -0,0 +1,71 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/async.hpp> +#include <boost/process/child.hpp> +#include <boost/process/async_system.hpp> + +#include <string> +#include <boost/asio/io_context.hpp> +#include <boost/asio/post.hpp> +#include <boost/asio/spawn.hpp> +#include <boost/asio/coroutine.hpp> +#include <boost/asio/use_future.hpp> +#include <boost/asio/yield.hpp> + +#include <vector> +#include <array> +BOOST_AUTO_TEST_SUITE( async ); + +namespace bp = boost::process; +BOOST_AUTO_TEST_CASE(stackless, *boost::unit_test::timeout(15)) +{ + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context ios; + + bool did_something_else = false; + + struct stackless_t : boost::asio::coroutine + { + boost::asio::io_context & ios; + bool & did_something_else; + + stackless_t(boost::asio::io_context & ios_, + bool & did_something_else) + : ios(ios_), did_something_else(did_something_else) {} + void operator()( + boost::system::error_code ec = boost::system::error_code(), + std::size_t exit_code = 0) + { + if (!ec) reenter (this) + { + yield bp::async_system( + ios, *this, + master_test_suite().argv[1], + "test", "--exit-code", "42"); + + BOOST_CHECK_EQUAL(exit_code, 42); + BOOST_CHECK(did_something_else); + } + } + } stackless{ios, did_something_else}; + + boost::asio::post(ios.get_executor(), [&]{stackless();}); + boost::asio::post(ios.get_executor(), [&]{did_something_else = true;}); + + ios.run(); + + BOOST_CHECK(did_something_else); +} + + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/bind_stderr.cpp b/src/boost/libs/process/test/bind_stderr.cpp new file mode 100644 index 000000000..6f0c11d16 --- /dev/null +++ b/src/boost/libs/process/test/bind_stderr.cpp @@ -0,0 +1,155 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <system_error> + +#include <boost/asio.hpp> +#include <boost/algorithm/string/predicate.hpp> + +#include <boost/process/args.hpp> +#include <boost/process/exe.hpp> +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/child.hpp> +#include <boost/process/async_pipe.hpp> + +#include <boost/filesystem.hpp> + +#include <string> +#include <istream> +#include <iostream> +#include <cstdlib> +#if defined(BOOST_WINDOWS_API) +# include <windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <unistd.h> +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +namespace fs = boost::filesystem; +namespace bp = boost::process; +BOOST_AUTO_TEST_SUITE( bind_stderr ); + +BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + + bp::ipstream is; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::args={"test", "--echo-stderr", "hello"}, + bp::std_err>is, + ec + ); + BOOST_REQUIRE(!ec); + + std::string s; + is >> s; + BOOST_CHECK_EQUAL(s, "hello"); +} + +struct read_handler +{ + boost::asio::streambuf &buffer_; + + read_handler(boost::asio::streambuf &buffer) : buffer_(buffer) {} + + void operator()(const boost::system::error_code &ec, std::size_t size) + { + BOOST_REQUIRE(!ec); + std::istream is(&buffer_); + std::string line; + std::getline(is, line); + BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); + } +}; + +BOOST_AUTO_TEST_CASE(async_io, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + boost::asio::io_context io_context; + + bp::async_pipe p(io_context); + std::error_code ec; + bp::child c( + bp::exe=master_test_suite().argv[1], + bp::args+="test", + bp::args+={"--echo-stderr", "abc"}, + bp::std_err>p, + ec + ); + BOOST_REQUIRE(!ec); + + + boost::asio::streambuf buffer; + boost::asio::async_read_until(p, buffer, '\n', read_handler(buffer)); + + io_context.run(); +} + +BOOST_AUTO_TEST_CASE(nul, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + std::error_code ec; + bp::child c( + bp::exe(master_test_suite().argv[1]), + bp::args+={"test", "--is-nul-stderr"}, + bp::std_err>bp::null, + ec + ); + BOOST_REQUIRE(!ec); + + c.wait(); + int exit_code = c.exit_code(); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#endif +} + + +BOOST_AUTO_TEST_CASE(file_io, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + fs::path pth = + fs::path(master_test_suite().argv[1]).parent_path() / "std_err_log_file.txt"; + + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::args={"test", "--echo-stderr", "hello"}, + bp::std_err>pth, + ec + ); + BOOST_REQUIRE(!ec); + + c.wait(); + { + fs::ifstream is{pth}; + + std::string s; + is >> s; + BOOST_CHECK_EQUAL(s, "hello"); + } + boost::filesystem::remove(pth); + +} + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/bind_stdin.cpp b/src/boost/libs/process/test/bind_stdin.cpp new file mode 100644 index 000000000..6f03326e6 --- /dev/null +++ b/src/boost/libs/process/test/bind_stdin.cpp @@ -0,0 +1,260 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/child.hpp> +#include <boost/process/args.hpp> +#include <boost/process/async.hpp> + +#include <system_error> +#include <boost/system/error_code.hpp> +#include <boost/filesystem.hpp> + +#include <boost/asio.hpp> +#include <string> +#include <cstdlib> +#include <iostream> +#include <thread> + +#include <boost/config.hpp> + +BOOST_AUTO_TEST_SUITE( bind_stdin ); + +#if defined(BOOST_WINDOWS_API) +# include <windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <unistd.h> +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + + +namespace fs = boost::filesystem; +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(10)) +{ + std::cout << "sync_io" << std::endl; + using boost::unit_test::framework::master_test_suite; + + bp::opstream os; + bp::ipstream is; + + std::error_code ec; + + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--prefix", "abc"}, + bp::std_in <os, + bp::std_out>is, + ec); + + BOOST_REQUIRE(!ec); + + + + os << "hello" << std::endl; + + std::string s; + + + is >> s; + BOOST_CHECK_EQUAL(s, "abchello"); + os << 123 << std::endl; + is >> s; + BOOST_CHECK_EQUAL(s, "abc123"); + os << 3.1415 << std::endl; + is >> s; + BOOST_CHECK_EQUAL(s, "abc3.1415"); + + c.terminate(); + c.wait(); + + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + int i = -1; + is >> i; + BOOST_CHECK(is.eof()); + BOOST_CHECK(!is); +} + + +struct write_handler +{ + bp::ipstream &is_; + + write_handler(bp::ipstream &is) : is_(is) {} + + void operator()(const boost::system::error_code &ec, std::size_t size) + { + BOOST_REQUIRE_EQUAL(6u, size); + std::string s; + is_ >> s; + BOOST_CHECK_EQUAL(s, "abchello"); + } +}; + +BOOST_AUTO_TEST_CASE(async_io, *boost::unit_test::timeout(2)) +{ + std::cout << "async_io" << std::endl; + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context io_context; + + bp::async_pipe p1(io_context); + bp::ipstream is; + + boost::asio::streambuf sb; + std::ostream os(&sb); + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--prefix-once", "abc", + bp::std_in<p1, + bp::std_out>is, + ec + ); + BOOST_REQUIRE(!ec); + + os << "hello" << std::endl; + + // std::string s = "hello\n"; + boost::asio::async_write(p1, sb, + write_handler(is)); + + io_context.run(); + + c.wait(); +} + +BOOST_AUTO_TEST_CASE(nul, *boost::unit_test::timeout(2)) +{ + std::cout << "nul" << std::endl; + + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--is-nul-stdin", + bp::std_in<bp::null, + ec); + + BOOST_REQUIRE(!ec); + + c.wait(); + int exit_code = c.exit_code(); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#endif +} + + +BOOST_AUTO_TEST_CASE(file_io, *boost::unit_test::timeout(2)) +{ + std::cout << "file_io" << std::endl; + using boost::unit_test::framework::master_test_suite; + + + fs::path pth = + fs::path(master_test_suite().argv[1]).parent_path() / "std_in_log_file.txt"; + bp::ipstream is; + + { + boost::filesystem::ofstream fs(pth); + fs << 321 << std::endl; + fs << 1.2345 << std::endl; + fs << "some_string" << std::endl; + } + std::error_code ec; + + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--prefix", "abc"}, + bp::std_in <pth, + bp::std_out>is, + ec); + + BOOST_REQUIRE(!ec); + + + std::string s; + + + is >> s; + BOOST_CHECK_EQUAL(s, "abc321"); + is >> s; + BOOST_CHECK_EQUAL(s, "abc1.2345"); + is >> s; + BOOST_CHECK_EQUAL(s, "abcsome_string"); + + c.wait(); + boost::filesystem::remove(pth); +} + +BOOST_AUTO_TEST_CASE(file_io_C, *boost::unit_test::timeout(2)) +{ + //tested, since stdin also yields FILE*. + std::cout << "file_io_C" << std::endl; + using boost::unit_test::framework::master_test_suite; + + + fs::path pth = + fs::path(master_test_suite().argv[1]).parent_path() / "std_in_log_file_2.txt"; + bp::ipstream is; + + { + boost::filesystem::ofstream fs(pth); + fs << 321 << std::endl; + fs << 1.2345 << std::endl; + fs << "some_string" << std::endl; + } + + FILE * f = fopen(pth.string().c_str(), "r+"); + + BOOST_REQUIRE(f != nullptr); + std::error_code ec; + + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--prefix", "abc"}, + bp::std_in <f, + bp::std_out>is, + ec); + + fclose(f); + + BOOST_REQUIRE(!ec); + + + std::string s; + + + is >> s; + BOOST_CHECK_EQUAL(s, "abc321"); + is >> s; + BOOST_CHECK_EQUAL(s, "abc1.2345"); + is >> s; + BOOST_CHECK_EQUAL(s, "abcsome_string"); + + c.wait(); + boost::filesystem::remove(pth); +} + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/bind_stdin_stdout.cpp b/src/boost/libs/process/test/bind_stdin_stdout.cpp new file mode 100644 index 000000000..1f71e44bd --- /dev/null +++ b/src/boost/libs/process/test/bind_stdin_stdout.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/child.hpp> +#include <boost/process/args.hpp> +#include <system_error> + +#include <boost/system/error_code.hpp> +#include <string> +#include <iostream> + +namespace bp = boost::process; +BOOST_AUTO_TEST_SUITE( bind_stdin_stdout ); + +BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(10)) +{ + using boost::unit_test::framework::master_test_suite; + + + bp::opstream os; + bp::ipstream is; + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--stdin-to-stdout"}, + bp::std_in<os, + bp::std_out>is, + ec + ); + BOOST_REQUIRE(!ec); + + std::string s = "abcdefghi j"; + for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) + { + os << *it << std::flush; + char c; + is >> std::noskipws >> c; + BOOST_CHECK_EQUAL(*it, c); + } + + os.pipe().close(); + + BOOST_CHECK(c.wait_for(std::chrono::seconds(3))); +} + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/bind_stdout.cpp b/src/boost/libs/process/test/bind_stdout.cpp new file mode 100644 index 000000000..6798bea5d --- /dev/null +++ b/src/boost/libs/process/test/bind_stdout.cpp @@ -0,0 +1,171 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/system/error_code.hpp> + +#include <boost/asio.hpp> +#include <boost/algorithm/string/predicate.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/args.hpp> +#include <boost/process/child.hpp> +#include <boost/process/async_pipe.hpp> +#include <system_error> + +#include <boost/filesystem.hpp> + +#include <string> +#include <istream> +#include <cstdlib> +#if defined(BOOST_WINDOWS_API) +# include <windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <unistd.h> +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +BOOST_AUTO_TEST_SUITE( bind_stdout ); + + +namespace fs = boost::filesystem; +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::ipstream is; + std::error_code ec; + + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--echo-stdout", "hello"}, + bp::std_out > is, + ec + ); + + BOOST_CHECK(!ec); + + + std::string s; + + BOOST_TEST_CHECKPOINT("Starting read"); + is >> s; + BOOST_TEST_CHECKPOINT("Finished read"); + + BOOST_CHECK_EQUAL(s, "hello"); +} + + +struct read_handler +{ + boost::asio::streambuf &buffer_; + + read_handler(boost::asio::streambuf &buffer) : buffer_(buffer) {} + + void operator()(const boost::system::error_code &ec, std::size_t size) + { + BOOST_REQUIRE(!ec); + std::istream is(&buffer_); + std::string line; + std::getline(is, line); + BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); + } +}; + +BOOST_AUTO_TEST_CASE(async_io, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context io_context; + bp::async_pipe p(io_context); + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--echo-stdout", "abc", + bp::std_out > p, + ec + ); + BOOST_REQUIRE(!ec); + + boost::asio::streambuf buffer; + boost::asio::async_read_until(p, buffer, '\n', + read_handler(buffer)); + + io_context.run(); +} + +BOOST_AUTO_TEST_CASE(nul, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--is-nul-stdout"}, + bp::std_out>bp::null, + ec + ); + BOOST_REQUIRE(!ec); + + c.wait(); + int exit_code = c.exit_code(); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#endif +} + + + +BOOST_AUTO_TEST_CASE(file_io, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + fs::path pth = + fs::path(master_test_suite().argv[1]).parent_path() / "std_out_log_file.txt"; + + + FILE* f = fopen(pth.string().c_str(), "w"); + BOOST_REQUIRE(f != nullptr); + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::args={"test", "--echo-stdout", "hello"}, + bp::std_out>f, + ec + ); + BOOST_REQUIRE(!ec); + + fclose(f); + + c.wait(); + { + fs::ifstream is{pth}; + + std::string s; + is >> s; + BOOST_CHECK_EQUAL(s, "hello"); + } + boost::filesystem::remove(pth); + +} + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/bind_stdout_stderr.cpp b/src/boost/libs/process/test/bind_stdout_stderr.cpp new file mode 100644 index 000000000..a10f0a59b --- /dev/null +++ b/src/boost/libs/process/test/bind_stdout_stderr.cpp @@ -0,0 +1,138 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/child.hpp> +#include <boost/process/exe.hpp> +#include <boost/process/args.hpp> +#include <boost/process/async_pipe.hpp> + +#include <system_error> + +#include <boost/system/error_code.hpp> + +#include <boost/asio.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <string> +#include <istream> +#if defined(BOOST_WINDOWS_API) +# include <windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +namespace bp = boost::process; + +BOOST_AUTO_TEST_SUITE( bind_stdout_stderr ); + + +BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p1; + bp::pipe p2; + + bp::ipstream is1; + bp::ipstream is2; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--echo-stdout-stderr", "hello", + bp::std_out>is1, + bp::std_err>is2, + ec + ); + BOOST_REQUIRE(!ec); + + + + std::string s; + is1 >> s; + BOOST_CHECK_EQUAL(s, "hello"); + + is2 >> s; + BOOST_CHECK_EQUAL(s, "hello"); +} + + +struct read_handler +{ + boost::asio::streambuf &buffer_; + + read_handler(boost::asio::streambuf &buffer) : buffer_(buffer) {} + + void operator()(const boost::system::error_code &ec, std::size_t size) + { + BOOST_REQUIRE(!ec); + std::istream is(&buffer_); + std::string line; + std::getline(is, line); + BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); + } +}; + +BOOST_AUTO_TEST_CASE(async_io, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + boost::asio::io_context io_context; + + bp::async_pipe p1(io_context); + bp::async_pipe p2(io_context); + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::args={"test", "--echo-stdout-stderr", "abc"}, + bp::std_out > p1, + bp::std_err > p2, + ec + ); + BOOST_REQUIRE(!ec); + + boost::asio::streambuf buffer1; + boost::asio::async_read_until(p1, buffer1, '\n', + read_handler(buffer1)); + + boost::asio::streambuf buffer2; + boost::asio::async_read_until(p2, buffer2, '\n', + read_handler(buffer2)); + + io_context.run(); +} + +BOOST_AUTO_TEST_CASE(nul, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + std::error_code ec; + bp::child c( + bp::exe(master_test_suite().argv[1]), + bp::args+={"test", "--echo-stdout-stderr", "some string"}, + (bp::std_err & bp::std_out) > bp::null, + ec + ); + BOOST_REQUIRE(!ec); + + c.wait(); + int exit_code = c.exit_code(); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#endif +} + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/close_stderr.cpp b/src/boost/libs/process/test/close_stderr.cpp new file mode 100644 index 000000000..a2f2ac87c --- /dev/null +++ b/src/boost/libs/process/test/close_stderr.cpp @@ -0,0 +1,48 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/child.hpp> +#include <system_error> + +#include <boost/system/error_code.hpp> +#include <cstdlib> +#if defined(BOOST_POSIX_API) +# include <sys/wait.h> +#endif + +namespace bp = boost::process; + + +BOOST_AUTO_TEST_CASE(close_stderr) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--is-closed-stderr", + bp::std_err > bp::close, + ec + ); + BOOST_REQUIRE(!ec); + + c.wait(); + int exit_code = c.exit_code(); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, WEXITSTATUS(exit_code)); +#endif +} diff --git a/src/boost/libs/process/test/close_stdin.cpp b/src/boost/libs/process/test/close_stdin.cpp new file mode 100644 index 000000000..039c8d101 --- /dev/null +++ b/src/boost/libs/process/test/close_stdin.cpp @@ -0,0 +1,47 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/child.hpp> +#include <system_error> + +#include <boost/system/error_code.hpp> +#include <cstdlib> +#if defined(BOOST_POSIX_API) +# include <sys/wait.h> +#endif + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(close_stdin) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--is-closed-stdin", + bp::std_in.close(), + ec + ); + BOOST_REQUIRE(!ec); + + c.wait(); + int exit_code = c.exit_code(); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, WEXITSTATUS(exit_code)); +#endif +} diff --git a/src/boost/libs/process/test/close_stdout.cpp b/src/boost/libs/process/test/close_stdout.cpp new file mode 100644 index 000000000..75956954a --- /dev/null +++ b/src/boost/libs/process/test/close_stdout.cpp @@ -0,0 +1,47 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/child.hpp> +#include <system_error> + +#include <boost/system/error_code.hpp> +#include <cstdlib> +#if defined(BOOST_POSIX_API) +# include <sys/wait.h> +#endif + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(close_stdout) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--is-closed-stdout", + bp::std_out.close(), + ec + ); + BOOST_REQUIRE(!ec); + + c.wait(); + int exit_code = c.exit_code(); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, WEXITSTATUS(exit_code)); +#endif +} diff --git a/src/boost/libs/process/test/cmd_test.cpp b/src/boost/libs/process/test/cmd_test.cpp new file mode 100644 index 000000000..98b84df6d --- /dev/null +++ b/src/boost/libs/process/test/cmd_test.cpp @@ -0,0 +1,85 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/system.hpp> +#include <boost/process/env.hpp> +#include <boost/process/cmd.hpp> + +#include <boost/filesystem/path.hpp> +#include <boost/filesystem/operations.hpp> + +#include <system_error> + +#include <boost/algorithm/string/case_conv.hpp> + +#include <boost/system/error_code.hpp> +#include <cstdlib> + +namespace bp = boost::process; +namespace fs = boost::filesystem; + + +BOOST_AUTO_TEST_CASE(excplicit) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + + fs::path pth = master_test_suite().argv[1]; + auto env = boost::this_process::environment(); + + auto itr = std::find_if(env.begin(), env.end(), + [](const bp::native_environment::entry_type & e){return boost::to_upper_copy(e.get_name()) == "PATH";}); + + BOOST_REQUIRE(itr != env.end()); + + (*itr) += fs::canonical(fs::absolute(pth.parent_path())).string(); + + int ret = bp::system( + bp::cmd="sparring_partner --exit-code 42", + ec + ); + + BOOST_CHECK(!ec); + if (ec) + BOOST_TEST_MESSAGE(ec.message()); + BOOST_CHECK_EQUAL(ret, 42); +} + +BOOST_AUTO_TEST_CASE(implicit) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + + fs::path pth = master_test_suite().argv[1]; + auto env = boost::this_process::environment(); + + auto itr = std::find_if(env.begin(), env.end(), + [](const bp::native_environment::entry_type & e){return boost::to_upper_copy(e.get_name()) == "PATH";}); + + BOOST_REQUIRE(itr != env.end()); + + (*itr) += fs::canonical(fs::absolute(pth.parent_path())).string(); + + int ret = bp::system( + "sparring_partner --exit-code 21", + ec + ); + + BOOST_CHECK(!ec); + if (ec) + BOOST_TEST_MESSAGE(ec.message()); + BOOST_CHECK_EQUAL(ret, 21); +} diff --git a/src/boost/libs/process/test/env.cpp b/src/boost/libs/process/test/env.cpp new file mode 100644 index 000000000..93b54ce71 --- /dev/null +++ b/src/boost/libs/process/test/env.cpp @@ -0,0 +1,180 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/args.hpp> +#include <boost/process/child.hpp> +#include <boost/process/env.hpp> +#include <boost/process/environment.hpp> +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> + +#include <boost/algorithm/string/predicate.hpp> + +#include <boost/system/error_code.hpp> + +#include <boost/program_options/environment_iterator.hpp> +#include <string> +#include <stdlib.h> +#include <list> + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(inherit_env, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::ipstream st; + + std::error_code ec; + + bp::child c( + master_test_suite().argv[1], + "test", "--query", "PATH", + bp::std_out>st, + ec + ); + BOOST_REQUIRE(!ec); + + std::string s; + + std::getline(st, s); + + auto path = boost::this_process::environment()["PATH"].to_string(); + + std::cout << "Path : '" << path << "'" << std::endl; + std::cout << "Value: '" << s << "'" << std::endl; + + if(!path.empty()) + { + auto size = (path.size() < s.size()) ? path.size() : s.size(); + + BOOST_CHECK_EQUAL_COLLECTIONS( + s.begin(), s. begin() + size, + path.begin(), path.begin() + size + ); + } + else + BOOST_CHECK(boost::starts_with(s, "************** empty environment **************")); + c.wait(); +} + + +BOOST_AUTO_TEST_CASE(inherit_mod_env, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + auto ie = boost::this_process::environment(); + std::string value = "TestString"; + ie["BOOST_PROCESS_TEST_1"] = value; + + { + auto ie2 = boost::this_process::environment(); + auto val = ie2["BOOST_PROCESS_TEST_1"]; + auto st = val.to_string(); + + BOOST_CHECK_EQUAL_COLLECTIONS( + st.begin(), st.end(), + value.begin(), value.end() + ); + } + bp::ipstream st; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--query", "BOOST_PROCESS_TEST_1", + bp::std_out>st, + ec + ); + BOOST_REQUIRE(!ec); + + std::string s; + + std::getline(st, s); + + auto size = (value.size() < s.size()) ? value.size() : s.size(); + + BOOST_CHECK_EQUAL_COLLECTIONS( + s.begin(), s. begin() + size, + value.begin(), value.begin() + size + ); + c.wait(); +} + + +BOOST_AUTO_TEST_CASE(modifided_env, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::ipstream st; + + boost::process::environment env = boost::this_process::environment(); //empty env, that would fail. + std::string value = "TestString"; + env["BOOST_PROCESS_TEST_2"] = value; + + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--query", "BOOST_PROCESS_TEST_2", + bp::std_out>st, + env, + ec + ); + BOOST_REQUIRE(!ec); + BOOST_REQUIRE(boost::this_process::environment().count(value) == 0); + + std::string s; + std::getline(st, s); + + BOOST_CHECK(boost::algorithm::starts_with(s, "TestString")); + c.wait(); +} + + +BOOST_AUTO_TEST_CASE(append, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::ipstream st; + BOOST_TEST_PASSPOINT(); + bp::environment e = boost::this_process::environment(); + + std::error_code ec; + BOOST_REQUIRE_GE(e.size(), 1u); + + std::list<std::string> arg = {"test", "--query", "BOOST_PROCESS_TEST_3"}; + bp::child c( + master_test_suite().argv[1], + bp::env["BOOST_PROCESS_TEST_3"]="some_string", + bp::env=e, + bp::env["BOOST_PROCESS_TEST_3"]=boost::none, + bp::env["BOOST_PROCESS_TEST_3"]+="some_fictional_path_42", + bp::env["BOOST_PROCESS_TEST_3"]+={"other", "next"}, + bp::args=arg, + bp::std_out>st, + ec + ); + + BOOST_REQUIRE(!ec); + BOOST_WARN(c.running()); + std::string s; + + std::getline(st, s); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK(boost::starts_with(s, "some_fictional_path_42;other;next")); +#else + BOOST_CHECK(boost::starts_with(s, "some_fictional_path_42:other:next")); +#endif + c.wait(); +} diff --git a/src/boost/libs/process/test/environment.cpp b/src/boost/libs/process/test/environment.cpp new file mode 100644 index 000000000..4386844af --- /dev/null +++ b/src/boost/libs/process/test/environment.cpp @@ -0,0 +1,268 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process/environment.hpp> + +namespace bp = boost::process; + + +namespace std +{ +std::ostream & operator<<(std::ostream & str, const std::wstring & ws) +{ + str << bp::detail::convert(ws); + return str; +} +} + +BOOST_AUTO_TEST_CASE(empty, *boost::unit_test::timeout(5)) +{ + bp::environment ev ; + BOOST_CHECK(ev.empty()); + BOOST_CHECK_EQUAL(ev.size(), 0u); + BOOST_CHECK_EQUAL(ev.end() - ev.begin(), 0); + ev["Thingy"] = "My value"; + + BOOST_CHECK(!ev.empty()); + BOOST_CHECK_EQUAL(ev.size(), 1u); + BOOST_CHECK_EQUAL(ev.end() - ev.begin(), 1); + + for (auto x : ev) + { + BOOST_CHECK_EQUAL(x.to_string(), "My value"); + BOOST_CHECK_EQUAL(x.get_name(), "Thingy"); + } + + ev["Thingy"].clear(); + BOOST_CHECK(ev.empty()); + BOOST_CHECK_EQUAL(ev.size(), 0u); + BOOST_CHECK_EQUAL(ev.end() - ev.begin(), 0); + ev.clear(); +} + +BOOST_AUTO_TEST_CASE(wempty, *boost::unit_test::timeout(5)) +{ + bp::wenvironment ev ; + BOOST_CHECK(ev.empty()); + BOOST_CHECK_EQUAL(ev.size(), 0u); + BOOST_CHECK_EQUAL(ev.end() - ev.begin(), 0); + ev[L"Thingy"] = L"My value"; + + BOOST_CHECK(!ev.empty()); + BOOST_CHECK_EQUAL(ev.size(), 1u); + BOOST_CHECK_EQUAL(ev.end() - ev.begin(), 1); + + for (auto x : ev) + { + BOOST_CHECK(x.to_string() == L"My value"); + BOOST_CHECK(x.get_name() == L"Thingy"); + } + + ev[L"Thingy"].clear(); + BOOST_CHECK(ev.empty()); + BOOST_CHECK_EQUAL(ev.size(), 0u); + BOOST_CHECK_EQUAL(ev.end() - ev.begin(), 0); + ev.clear(); +} + +BOOST_AUTO_TEST_CASE(compare, *boost::unit_test::timeout(5)) +{ + auto nat = boost::this_process::environment(); + bp::environment env = nat; + + { + BOOST_CHECK_EQUAL(nat.size(), env.size()); + auto ni = nat.begin(); + auto ei = env.begin(); + + while ((ni != nat.end()) &&(ei != env.end())) + { + BOOST_CHECK_EQUAL(ni->get_name(), ei->get_name()); + BOOST_CHECK_EQUAL(ni->to_string(), ei->to_string()); + ni++; ei++; + } + } + + //ok check if I can convert it. + bp::wenvironment wenv{env}; + auto wnat = boost::this_process::wenvironment(); + BOOST_CHECK_EQUAL(wenv.size(), env.size()); + BOOST_CHECK_EQUAL(wnat.size(), nat.size()); + { + BOOST_CHECK_EQUAL(wnat.size(), wenv.size()); + auto ni = wnat.begin(); + auto ei = wenv.begin(); + + while ((ni != wnat.end()) && (ei != wenv.end())) + { + BOOST_CHECK_EQUAL(ni->get_name() , ei->get_name()); + BOOST_CHECK_EQUAL(ni->to_string(), ei->to_string()); + ni++; ei++; + } + + BOOST_CHECK(ni == wnat.end()); + } + BOOST_TEST_PASSPOINT(); + env.clear(); + BOOST_TEST_PASSPOINT(); + wenv.clear(); + BOOST_TEST_PASSPOINT(); +} + +BOOST_AUTO_TEST_CASE(wcompare, *boost::unit_test::timeout(5)) +{ + auto nat = boost::this_process::wenvironment(); + bp::wenvironment env = nat; + + { + BOOST_CHECK_EQUAL(nat.size(), env.size()); + auto ni = nat.begin(); + auto ei = env.begin(); + + while ((ni != nat.end()) &&(ei != env.end())) + { + BOOST_CHECK_EQUAL(ni->get_name(), ei->get_name()); + BOOST_CHECK_EQUAL(ni->to_string(), ei->to_string()); + ni++; ei++; + } + } + + BOOST_TEST_PASSPOINT(); + env.clear(); + BOOST_TEST_PASSPOINT(); +} + +BOOST_AUTO_TEST_CASE(insert_remove, *boost::unit_test::timeout(5)) +{ + bp::environment env(boost::this_process::environment()); + + auto sz = env.size(); + BOOST_REQUIRE_GE(sz, 1u); + BOOST_REQUIRE_EQUAL(env.count("BOOST_TEST_VAR"), 0u); + + env["BOOST_TEST_VAR"] = {"some string", "badabumm"}; + +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(env["BOOST_TEST_VAR"].to_string(), "some string;badabumm"); +#else + BOOST_CHECK_EQUAL(env["BOOST_TEST_VAR"].to_string(), "some string:badabumm"); +#endif + BOOST_CHECK_EQUAL(sz +1, env.size()); + + env["BOOST_TEST_VAR"].clear(); + + BOOST_CHECK_EQUAL(env.size(), sz); + + env.clear(); + +} + +BOOST_AUTO_TEST_CASE(clear_empty_my, *boost::unit_test::timeout(5)) +{ + bp::native_environment env; + + bp::environment e = env; + + const std::size_t sz = env.size(); + + BOOST_TEST_MESSAGE("Current native size: " << sz); + + BOOST_REQUIRE_EQUAL(env.count("BOOST_PROCESS_TEST_VAR_a"), 0u); + BOOST_REQUIRE_EQUAL(env.count("BOOST_PROCESS_TEST_VAR_b"), 0u); + BOOST_REQUIRE_EQUAL(env.count("BOOST_PROCESS_TEST_VAR_c"), 0u); + + env["BOOST_PROCESS_TEST_VAR_a"] = "1"; + env["BOOST_PROCESS_TEST_VAR_b"] = "2"; + BOOST_CHECK(env.emplace("BOOST_PROCESS_TEST_VAR_c", "3").second); + + BOOST_CHECK_EQUAL(env.count("BOOST_PROCESS_TEST_VAR_a"), 1u); + BOOST_CHECK_EQUAL(env.count("BOOST_PROCESS_TEST_VAR_b"), 1u); + BOOST_CHECK_EQUAL(env.count("BOOST_PROCESS_TEST_VAR_c"), 1u); + + BOOST_CHECK_EQUAL(env.at("BOOST_PROCESS_TEST_VAR_a").to_string(), "1"); + BOOST_CHECK_EQUAL(env.at("BOOST_PROCESS_TEST_VAR_b").to_string(), "2"); + BOOST_CHECK_EQUAL(env.at("BOOST_PROCESS_TEST_VAR_c").to_string(), "3"); + BOOST_CHECK_EQUAL(env.size(), sz + 3u); + BOOST_CHECK_EQUAL(std::distance(env.begin(), env.end()), sz + 3); + BOOST_CHECK_EQUAL(std::distance(env.cbegin(), env.cend()), sz + 3); + + env.erase("BOOST_PROCESS_TEST_VAR_a"); + BOOST_CHECK_EQUAL(env.size(), sz + 2u); + BOOST_CHECK_EQUAL(env.count("BOOST_PROCESS_TEST_VAR_a"), 0u); + BOOST_CHECK_EQUAL(env.at ("BOOST_PROCESS_TEST_VAR_b").to_string(), "2"); + BOOST_CHECK_EQUAL(env.at ("BOOST_PROCESS_TEST_VAR_c").to_string(), "3"); + + BOOST_CHECK_EQUAL(std::distance(env.begin(), env.end()), sz + 2); + BOOST_CHECK_EQUAL(std::distance(env.cbegin(), env.cend()), sz + 2); + + env.erase("BOOST_PROCESS_TEST_VAR_b"); + BOOST_CHECK_EQUAL(env.size(), sz + 1u); + BOOST_CHECK_EQUAL(env.count("BOOST_PROCESS_TEST_VAR_a"), 0u); + BOOST_CHECK_EQUAL(env.count("BOOST_PROCESS_TEST_VAR_b"), 0u); + BOOST_CHECK_EQUAL(env.at ("BOOST_PROCESS_TEST_VAR_c").to_string(), "3"); + + BOOST_CHECK_EQUAL(std::distance(env.begin(), env.end()), sz + 1); + BOOST_CHECK_EQUAL(std::distance(env.cbegin(), env.cend()), sz + 1); + + env.clear(); + //note: windows puts an entry without a name into the list, so it might not be empty after clear. + BOOST_CHECK_LE(env.size(), sz); + + BOOST_CHECK_LE(std::distance(env.begin(), env.end()), sz); + BOOST_CHECK_LE(std::distance(env.cbegin(), env.cend()), sz); + + for (auto && ee : e) + env.emplace(ee.get_name(), ee.to_string()); +} + +BOOST_AUTO_TEST_CASE(clear_empty, *boost::unit_test::timeout(5)) +{ + bp::environment env; + BOOST_CHECK(env.empty()); + BOOST_CHECK_EQUAL(env.size(), 0u); + env["a"] = "1"; + env["b"] = "2"; + env["c"] = "3"; + + BOOST_CHECK_EQUAL(env.at("a").to_string(), "1"); + BOOST_CHECK_EQUAL(env.at("b").to_string(), "2"); + BOOST_CHECK_EQUAL(env.at("c").to_string(), "3"); + BOOST_CHECK_EQUAL(env.size(), 3u); + BOOST_CHECK_EQUAL(std::distance(env.begin(), env.end()), 3u); + BOOST_CHECK_EQUAL(std::distance(env.cbegin(), env.cend()), 3u); + + env.erase("c"); + BOOST_CHECK_EQUAL(env.size(), 2u); + BOOST_CHECK_EQUAL(env.at("a").to_string(), "1"); + BOOST_CHECK_EQUAL(env.at("b").to_string(), "2"); + BOOST_CHECK_EQUAL(env.count("c"), 0u); + + BOOST_CHECK_EQUAL(std::distance(env.begin(), env.end()), 2u); + BOOST_CHECK_EQUAL(std::distance(env.cbegin(), env.cend()), 2u); + + env.erase("b"); + BOOST_CHECK_EQUAL(env.size(), 1u); + BOOST_CHECK_EQUAL(env.at("a").to_string(), "1"); + BOOST_CHECK_EQUAL(env.count("b"), 0u); + BOOST_CHECK_EQUAL(env.count("c"), 0u); + + BOOST_CHECK_EQUAL(std::distance(env.begin(), env.end()), 1u); + BOOST_CHECK_EQUAL(std::distance(env.cbegin(), env.cend()), 1u); + + env.clear(); + BOOST_CHECK(env.empty()); + BOOST_CHECK_EQUAL(env.size(), 0u); + + BOOST_CHECK_EQUAL(std::distance(env.begin(), env.end()), 0u); + BOOST_CHECK_EQUAL(std::distance(env.cbegin(), env.cend()), 0u); + +} diff --git a/src/boost/libs/process/test/error.cpp b/src/boost/libs/process/test/error.cpp new file mode 100644 index 000000000..a1c3007f3 --- /dev/null +++ b/src/boost/libs/process/test/error.cpp @@ -0,0 +1,115 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/child.hpp> +#include <boost/process/extend.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <system_error> + + + +namespace bp = boost::process; + +struct err_set +{ + std::error_code ec; + const char* msg = ""; + + template<typename Exec> + void operator()(Exec& exec) + { + exec.set_error(ec, msg); + } + + template<typename Exec> + void operator()(Exec& exec, const std::error_code &) + { + exec.set_error(ec, msg); + } +}; + +BOOST_AUTO_TEST_CASE(setup_error) +{ + using boost::unit_test::framework::master_test_suite; + + err_set es; + + { + es.ec.assign(42, std::system_category()); + std::error_code ec; + bp::child c(master_test_suite().argv[1], ec, bp::extend::on_setup(es)); + + BOOST_CHECK(!c.running()); + BOOST_CHECK(ec); + BOOST_CHECK_EQUAL(ec.value(), 42); + } + bool has_thrown = false; + try + { + es.ec.assign(24, std::system_category()); + es.msg = "MyMessage"; + bp::child c(master_test_suite().argv[1], bp::extend::on_setup(es)); + + } + catch( bp::process_error & se) + { + has_thrown = true; + BOOST_CHECK_EQUAL(se.code().value(), 24); + BOOST_CHECK(boost::starts_with(se.what(), "MyMessage")); + } + BOOST_CHECK(has_thrown); +} + +BOOST_AUTO_TEST_CASE(success_error) +{ + using boost::unit_test::framework::master_test_suite; + + err_set es; + + { + es.ec.assign(22, std::system_category()); + std::error_code ec; + bp::child c(master_test_suite().argv[1], ec, bp::extend::on_success(es)); + + + BOOST_CHECK(!c.running()); + BOOST_CHECK(ec); + BOOST_CHECK_EQUAL(ec.value(), 22); + std::cout << "Value: " << ec.value() << std::endl; + } + bool has_thrown = false; + try + { + es.ec.assign(23, std::system_category()); + es.msg = "MyMessage"; + bp::child c(master_test_suite().argv[1], bp::extend::on_success(es)); + + + } + catch( bp::process_error & se) + { + has_thrown = true; + BOOST_CHECK_EQUAL(se.code().value(), 23); + BOOST_CHECK(boost::starts_with(se.what(), "MyMessage")); + } + BOOST_CHECK(has_thrown); +} + +BOOST_AUTO_TEST_CASE(ignore_error) +{ + + { + BOOST_CHECK_NO_THROW(bp::child c("doesnt-exit", bp::ignore_error)); + } +} diff --git a/src/boost/libs/process/test/exit_argc.cpp b/src/boost/libs/process/test/exit_argc.cpp new file mode 100644 index 000000000..2cf6ec37a --- /dev/null +++ b/src/boost/libs/process/test/exit_argc.cpp @@ -0,0 +1,14 @@ +// Copyright (c) 2018 Oxford Nanopore Technologies +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <iostream> + +int main(int argc, char *argv[]) +{ + for (int i = 0; i < argc; ++i) { + std::cout << argv[i] << '\n'; + } + return argc; +} diff --git a/src/boost/libs/process/test/exit_code.cpp b/src/boost/libs/process/test/exit_code.cpp new file mode 100644 index 000000000..31f6990cb --- /dev/null +++ b/src/boost/libs/process/test/exit_code.cpp @@ -0,0 +1,159 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN + +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/async.hpp> +#include <boost/process/child.hpp> + +#include <boost/system/error_code.hpp> +#include <boost/asio.hpp> +#if defined(BOOST_WINDOWS_API) +# include <windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <signal.h> +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(sync_wait) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--exit-code", "123", + ec + ); + BOOST_REQUIRE(!ec); + c.wait(); + int exit_code = c.exit_code(); + + + BOOST_CHECK_EQUAL(123, exit_code); + + c.wait(); +} + +BOOST_AUTO_TEST_CASE(sync_wait_abort) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--abort", + ec + ); + BOOST_REQUIRE(!ec); + c.wait(); + int exit_code = c.exit_code(); + + + BOOST_CHECK(exit_code != 0); + + c.wait(); +} + +#if defined(BOOST_WINDOWS_API) +struct wait_handler +{ + HANDLE handle_; + bool &called_; + wait_handler(HANDLE handle, bool &called) : handle_(handle), called_(called) {} + + void operator()(const boost::system::error_code &ec) + { + called_ = true; + BOOST_REQUIRE(!ec); + DWORD exit_code; + BOOST_REQUIRE(GetExitCodeProcess(handle_, &exit_code)); + BOOST_CHECK_EQUAL(123, exit_code); + } +}; +#elif defined(BOOST_POSIX_API) +struct wait_handler +{ + bool &called_; + + wait_handler (bool & called) : called_(called) {} + + void operator()(const boost::system::error_code &ec, int signal) + { + called_ = true; + BOOST_REQUIRE(!ec); + BOOST_REQUIRE_EQUAL(SIGCHLD, signal); + int status; + wait(&status); + BOOST_CHECK_EQUAL(123, WEXITSTATUS(status)); + } +}; +#endif + +BOOST_AUTO_TEST_CASE(async_wait) +{ + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + boost::asio::io_context io_context; + + boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(3)}; + timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();}); + + + bool wh_called = false; +#if defined(BOOST_POSIX_API) + signal_set set(io_context, SIGCHLD); + set.async_wait(wait_handler(wh_called)); +#endif + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--exit-code", "123", + ec + ); + BOOST_REQUIRE(!ec); + +#if defined(BOOST_WINDOWS_API) + windows::object_handle handle(io_context.get_executor(), c.native_handle()); + handle.async_wait(wait_handler(handle.native_handle(), wh_called)); +#endif + io_context.run(); + BOOST_CHECK_MESSAGE(wh_called, "Wait handler not called"); +} + + + +BOOST_AUTO_TEST_CASE(async_nowait) +{ + // No need to call wait when passing an io_context + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + std::error_code ec; + boost::asio::io_context io_context; + bp::child c( + master_test_suite().argv[1], + "test", "--exit-code", "221", + ec, + bp::on_exit=[](int exit_code, std::error_code) mutable {}, + io_context + ); + BOOST_REQUIRE(!ec); + io_context.run(); + BOOST_CHECK_EQUAL(221, c.exit_code()); +}
\ No newline at end of file diff --git a/src/boost/libs/process/test/extensions.cpp b/src/boost/libs/process/test/extensions.cpp new file mode 100644 index 000000000..88c38e1ff --- /dev/null +++ b/src/boost/libs/process/test/extensions.cpp @@ -0,0 +1,101 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process/error.hpp> +#include <system_error> +#include <boost/bind.hpp> +#include <boost/ref.hpp> +#include <boost/process/child.hpp> +#include <boost/process/extend.hpp> + + +namespace bp = boost::process; + + +struct run_exe +{ + std::string exe; + template<typename T> + void operator()(T &e) const + { + e.exe = exe.c_str(); + } + +}; + +struct set_on_error +{ + mutable std::error_code ec; + template<typename T> + void operator()(T &, const std::error_code & ec) const + { + this->ec = ec; + } +}; + +BOOST_AUTO_TEST_CASE(extensions) +{ + using boost::unit_test::framework::master_test_suite; + + run_exe re; + + re.exe = master_test_suite().argv[1]; + + set_on_error se; + std::error_code ec; + bp::child c( + "Wrong-Command", + "test", + bp::extend::on_setup=re, + bp::extend::on_error=se, + bp::ignore_error + ); + BOOST_CHECK(!se.ec); +} + + +namespace ex = boost::process::extend; + + +std::string st = "not called"; + +struct overload_handler : ex::handler +{ + template <class Char, class Sequence> + void on_setup(ex::windows_executor<Char, Sequence>& exec) const + { + st = "windows"; + const char* env = exec.env; + } + template <class Sequence> + void on_setup(ex::posix_executor<Sequence>& exec) const + { + st = "posix"; + char** env = exec.env; + } +}; + +BOOST_AUTO_TEST_CASE(overload) +{ + bp::child c( + overload_handler(), + bp::ignore_error + ); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(st, "windows"); +#else + BOOST_CHECK_EQUAL(st, "posix"); +#endif +} + + + diff --git a/src/boost/libs/process/test/group.cpp b/src/boost/libs/process/test/group.cpp new file mode 100644 index 000000000..fb2c5510a --- /dev/null +++ b/src/boost/libs/process/test/group.cpp @@ -0,0 +1,191 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/system/error_code.hpp> + +#include <boost/asio.hpp> +#include <boost/algorithm/string/predicate.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/args.hpp> +#include <boost/process/child.hpp> +#include <boost/process/group.hpp> +#include <system_error> + +#include <string> +#include <thread> +#include <istream> +#include <iostream> +#include <cstdlib> + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(group_test, *boost::unit_test::timeout(5)) +{ + std::cout << "group_test" << std::endl; + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::group g; + + + bp::child c( + master_test_suite().argv[1], + g, + ec + ); + BOOST_CHECK(c.running()); + + BOOST_REQUIRE(!ec); + BOOST_REQUIRE(c.in_group()); + BOOST_CHECK(c); + BOOST_CHECK(c.running()); + + BOOST_REQUIRE_NO_THROW(g.terminate()); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + + BOOST_CHECK(!c.running()); + if (c.running()) + c.terminate(); + + std::cout << "group_test out" << std::endl; + +} + +BOOST_AUTO_TEST_CASE(attached, *boost::unit_test::timeout(5)) +{ + std::cout << "attached" << std::endl; + + using boost::unit_test::framework::master_test_suite; + + bp::ipstream is; + + bp::group g; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::args+={"--launch-attached"}, + bp::std_out>is, + g, + ec + ); + BOOST_REQUIRE(!ec); + BOOST_REQUIRE(c.in_group(ec)); + BOOST_CHECK(c); + + + + bp::pid_t pid; + is >> pid; + bp::child sub_c(pid); + is >> pid; //invalid pid. + + + BOOST_REQUIRE(sub_c); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); //just to be sure. + + +#if defined( BOOST_POSIX_API ) + ::waitpid(sub_c.id(), nullptr, WNOHANG); + BOOST_CHECK(kill(sub_c.id(), 0) == 0); +#else + BOOST_CHECK(sub_c.running()); +#endif + + BOOST_REQUIRE_NO_THROW(g.terminate()); + + BOOST_CHECK(sub_c); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); //just to be sure. + + BOOST_CHECK(!c.running()); + +#if defined( BOOST_POSIX_API ) + errno = 0; + ::waitpid(sub_c.id(), nullptr, WNOHANG); + bool still_runs = (kill(sub_c.id(), 0) == 0) && (errno != ECHILD) && (errno != ESRCH); +#else + bool still_runs = sub_c.running(); +#endif + BOOST_CHECK_MESSAGE(!still_runs, boost::process::detail::get_last_error().message()); + + if (still_runs) + sub_c.terminate(); + BOOST_CHECK(!c.running()); + if (c.running()) + c.terminate(); + + std::cout << "attached out" << std::endl; + +} + + + +BOOST_AUTO_TEST_CASE(detached, *boost::unit_test::timeout(5)) +{ + std::cerr << "detached" << std::endl; + + using boost::unit_test::framework::master_test_suite; + + bp::ipstream is; + + bp::group g; + + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::args+={"--launch-detached"}, + bp::std_out>is, + g, + ec + ); + + BOOST_REQUIRE(!ec); + BOOST_CHECK(c); + + bp::pid_t pid; + is >> pid; + is >> pid; + bp::child sub_c(pid); + + std::this_thread::sleep_for(std::chrono::milliseconds(50)); //just to be sure. + +#if defined( BOOST_POSIX_API ) + BOOST_CHECK(kill(sub_c.id(), 0) == 0); +#else + BOOST_CHECK(sub_c.running()); +#endif + + BOOST_REQUIRE_NO_THROW(g.terminate()); + + BOOST_CHECK(sub_c); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); //just to be sure. + +#if defined( BOOST_POSIX_API ) + bool still_runs = kill(sub_c.id(), 0) == 0; +#else + bool still_runs = sub_c.running(); +#endif + + BOOST_CHECK(still_runs); + if (still_runs) + sub_c.terminate(); + + BOOST_CHECK(!c.running()); + if (c.running()) + c.terminate(); + + std::cerr << "detached out" << std::endl; +} diff --git a/src/boost/libs/process/test/group_wait.cpp b/src/boost/libs/process/test/group_wait.cpp new file mode 100644 index 000000000..5f6c55730 --- /dev/null +++ b/src/boost/libs/process/test/group_wait.cpp @@ -0,0 +1,135 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <fstream> +#include <boost/system/error_code.hpp> + +#include <boost/asio.hpp> +#include <boost/algorithm/string/predicate.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/args.hpp> +#include <boost/process/child.hpp> +#include <boost/process/group.hpp> +#include <system_error> + +#include <string> +#include <thread> +#include <istream> +#include <iostream> +#include <cstdlib> + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(wait_group_test, *boost::unit_test::timeout(5)) +{ + std::atomic<bool> done{false}; + std::thread thr{ + [&] + { + for (int i = 0; i < 50 && !done.load(); i++) + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + BOOST_REQUIRE(done.load()); + }}; + + + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::group g; + + + bp::child c1( + master_test_suite().argv[1], + "--wait", "2", + g, + ec + ); + + bp::child c2( + master_test_suite().argv[1], + "--wait", "2", + g, + ec + ); + + BOOST_CHECK(c1.running()); + BOOST_CHECK(c2.running()); + + BOOST_REQUIRE(!ec); + BOOST_REQUIRE(c1.in_group(ec)); + BOOST_CHECK_MESSAGE(!ec, ec.message()); + BOOST_REQUIRE(c2.in_group(ec)); + BOOST_CHECK_MESSAGE(!ec, ec.message()); + g.wait(); + + BOOST_CHECK(!c1.running()); + BOOST_CHECK(!c2.running()); + + done.store(true); + thr.join(); +} + + +BOOST_AUTO_TEST_CASE(wait_group_test_timeout, *boost::unit_test::timeout(15)) +{ + using boost::unit_test::framework::master_test_suite; + + std::atomic<bool> done{false}; + std::thread thr{ + [&] + { + for (int i = 0; i < 150 && !done.load(); i++) + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + BOOST_REQUIRE(done.load()); + }}; + + std::error_code ec; + bp::group g; + + + bp::child c1( + master_test_suite().argv[1], + "--wait", "1", + g, + ec + ); + + bp::child c2( + master_test_suite().argv[1], + "--wait", "4", + g, + ec + ); + + BOOST_CHECK(c1.running()); + BOOST_CHECK(c2.running()); + + BOOST_REQUIRE(!ec); + BOOST_REQUIRE(c1.in_group()); + BOOST_REQUIRE(c2.in_group()); + + BOOST_CHECK(!g.wait_for(std::chrono::seconds(2), ec)); + + BOOST_CHECK_MESSAGE(!ec, std::to_string(ec.value()) + " == " + ec.message()); + BOOST_CHECK(!c1.running()); + BOOST_CHECK(c2.running()); + + BOOST_CHECK(g.wait_for(std::chrono::seconds(5), ec)); + BOOST_CHECK_MESSAGE(!ec, std::to_string(ec.value()) + " == " + ec.message()); + BOOST_CHECK(!c1.running()); + BOOST_CHECK(!c2.running()); + + done.store(true); + thr.join(); +}
\ No newline at end of file diff --git a/src/boost/libs/process/test/limit_fd.cpp b/src/boost/libs/process/test/limit_fd.cpp new file mode 100644 index 000000000..a1558338c --- /dev/null +++ b/src/boost/libs/process/test/limit_fd.cpp @@ -0,0 +1,179 @@ +// Copyright (c) 2019 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <iostream> + +#include <boost/process.hpp> +#include <boost/process/handles.hpp> +#include <boost/process/pipe.hpp> +#include <boost/process/io.hpp> +#include <boost/process/async_pipe.hpp> +#include <boost/process/extend.hpp> + +#include <boost/filesystem.hpp> + +#include <system_error> +#include <string> + +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/ip/udp.hpp> + +#if defined(BOOST_WINDOWS_API) +#include <boost/winapi/get_current_thread.hpp> +#include <boost/winapi/get_current_process.hpp> +#endif + +namespace fs = boost::filesystem; +namespace bp = boost::process; +namespace bt = boost::this_process; + +BOOST_AUTO_TEST_CASE(leak_test, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + +#if defined(BOOST_WINDOWS_API) + const auto get_handle = [](FILE * f) {return reinterpret_cast<bt::native_handle_type>(_get_osfhandle(_fileno(f)));}; + const auto socket_to_handle = [](::boost::winapi::UINT_PTR_ sock){return reinterpret_cast<::boost::winapi::HANDLE_>(sock);}; +#else + const auto get_handle = [](FILE * f) {return fileno(f);}; + const auto socket_to_handle = [](int i){ return i;}; +#endif + + std::error_code ec; + auto fd_list = bt::get_handles(ec); + + BOOST_CHECK_EQUAL(std::count(fd_list.begin(), fd_list.end(), get_handle(stdin)), 1); + BOOST_CHECK_EQUAL(std::count(fd_list.begin(), fd_list.end(), get_handle(stdout)), 1); + BOOST_CHECK_EQUAL(std::count(fd_list.begin(), fd_list.end(), get_handle(stderr)), 1); + + BOOST_CHECK(bt::is_stream_handle(get_handle(stdin), ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); + BOOST_CHECK(bt::is_stream_handle(get_handle(stdout), ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); + BOOST_CHECK(bt::is_stream_handle(get_handle(stderr), ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); + + + BOOST_CHECK_GE(fd_list.size(), 3); + BOOST_CHECK_GE(bt::get_handles(ec).size(), fd_list.size()); + + bp::pipe p; + + { + + auto fd_list_new = bt::get_handles(ec); + BOOST_CHECK_MESSAGE(!ec, ec); + BOOST_CHECK_LE(fd_list.size() + 2, fd_list_new.size()); + fd_list = std::move(fd_list_new); + } + + + + BOOST_CHECK_EQUAL(std::count(fd_list.begin(), fd_list.end(), p.native_source()), 1); + BOOST_CHECK_EQUAL(std::count(fd_list.begin(), fd_list.end(), p.native_sink()), 1); + + BOOST_CHECK(bt::is_stream_handle(p.native_source(), ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); + BOOST_CHECK(bt::is_stream_handle(p.native_sink(), ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); + + + p.close(); + fd_list = bt::get_handles(ec); + + BOOST_CHECK_EQUAL(std::count(fd_list.begin(), fd_list.end(), p.native_source()), 0); + BOOST_CHECK_EQUAL(std::count(fd_list.begin(), fd_list.end(), p.native_sink()), 0); + +#if defined( BOOST_WINDOWS_API ) + std::thread thr([]{}); + BOOST_CHECK(!bt::is_stream_handle(thr.native_handle(), ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); + thr.join(); +#else +# if defined(TFD_CLOEXEC) //check timer + int timer_fd = ::timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + BOOST_CHECK(!bt::is_stream_handle(timer_fd , ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); +#endif +# if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) + int event_fd =::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + BOOST_CHECK(!bt::is_stream_handle(event_fd , ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); +#endif + int dir_fd = ::dirfd(::opendir(".")); + BOOST_CHECK(!bt::is_stream_handle(dir_fd , ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); +#endif + + + boost::asio::io_context ioc; + boost::asio::ip::tcp::socket tcp_socket(ioc); + boost::asio::ip::udp::socket udp_socket(ioc); + bp::async_pipe ap(ioc); + + tcp_socket.open(boost::asio::ip::tcp::v4()); + udp_socket.open(boost::asio::ip::udp::v4()); + + BOOST_CHECK(bt::is_stream_handle(socket_to_handle(tcp_socket.native_handle()), ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); + BOOST_CHECK(bt::is_stream_handle(socket_to_handle(udp_socket.native_handle()), ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); + BOOST_CHECK(bt::is_stream_handle(std::move(ap).sink(). native_handle(), ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); + BOOST_CHECK(bt::is_stream_handle(std::move(ap).source().native_handle(), ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); +} + +struct on_setup_t +{ + std::vector<bt::native_handle_type> &res; + + on_setup_t(std::vector<bt::native_handle_type> & res) : res(res) {} + template<typename Executor> + void operator()(Executor & e) + { + bp::extend::foreach_used_handle(e, [this](bt::native_handle_type handle) + { + res.push_back(handle); + std::cout << "Pushing " << handle << std::endl; + }); + } +}; + +BOOST_AUTO_TEST_CASE(iterate_handles, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + + std::vector<bt::native_handle_type> res; + + bp::pipe p_in; + bp::pipe p_out; + + auto source = p_in.native_source(); + auto sink = p_out.native_sink(); + std::error_code ec; + + BOOST_WARN_NE(source, sink); //Sanity check + + const auto ret = bp::system(master_test_suite().argv[1], "--exit-code" , "42", + bp::std_in < p_out, + bp::std_out > p_in, + bp::extend::on_setup(on_setup_t(res)), ec); + + BOOST_CHECK_MESSAGE(!ec, ec.message()); + + BOOST_CHECK_EQUAL(ret, 42); + BOOST_CHECK_EQUAL(std::count(res.begin(), res.end(), p_in. native_sink()), 0); + BOOST_CHECK_EQUAL(std::count(res.begin(), res.end(), p_out.native_source()), 0); +} + +BOOST_AUTO_TEST_CASE(limit_fd, *boost::unit_test::timeout(5)) +{ +#if defined(BOOST_WINDOWS_API) + const auto get_handle = [](FILE * f){return std::to_string(_get_osfhandle(_fileno(f)));}; +#else + const auto get_handle = [](FILE * f){return std::to_string(fileno(f));}; +#endif + + using boost::unit_test::framework::master_test_suite; + BOOST_CHECK_EQUAL(bp::system(master_test_suite().argv[1], "--has-handle", get_handle(stdout), bp::std_err > stderr), EXIT_SUCCESS); + BOOST_CHECK_EQUAL(bp::system(master_test_suite().argv[1], "--has-handle", get_handle(stderr), bp::std_err > stderr), EXIT_SUCCESS); + + + BOOST_CHECK_EQUAL(bp::system(master_test_suite().argv[1], "--has-handle", get_handle(stdout), bp::std_err > stderr, bp::limit_handles), EXIT_FAILURE); + BOOST_CHECK_EQUAL(bp::system(master_test_suite().argv[1], "--has-handle", get_handle(stderr), bp::std_err > stderr, bp::limit_handles), EXIT_SUCCESS); + +}
\ No newline at end of file diff --git a/src/boost/libs/process/test/multi_ref1.cpp b/src/boost/libs/process/test/multi_ref1.cpp new file mode 100644 index 000000000..9ba9027d7 --- /dev/null +++ b/src/boost/libs/process/test/multi_ref1.cpp @@ -0,0 +1,7 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#include <boost/process.hpp> diff --git a/src/boost/libs/process/test/multi_ref2.cpp b/src/boost/libs/process/test/multi_ref2.cpp new file mode 100644 index 000000000..450ed5b5e --- /dev/null +++ b/src/boost/libs/process/test/multi_ref2.cpp @@ -0,0 +1,6 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> diff --git a/src/boost/libs/process/test/no_ansi_apps.cpp b/src/boost/libs/process/test/no_ansi_apps.cpp new file mode 100644 index 000000000..fcd09dd8c --- /dev/null +++ b/src/boost/libs/process/test/no_ansi_apps.cpp @@ -0,0 +1,10 @@ +// Copyright (c) 2018 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/system/api_config.hpp> +#if defined(BOOST_WINDOWS_API) +#define BOOST_NO_ANSI_APIS 1 +#endif +#include <boost/process.hpp>
\ No newline at end of file diff --git a/src/boost/libs/process/test/on_exit.cpp b/src/boost/libs/process/test/on_exit.cpp new file mode 100644 index 000000000..e46e2ea84 --- /dev/null +++ b/src/boost/libs/process/test/on_exit.cpp @@ -0,0 +1,52 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/asio.hpp> +#include <chrono> +#include <thread> + +BOOST_AUTO_TEST_CASE(single_ios, *boost::unit_test::timeout(6)) +{ + using boost::unit_test::framework::master_test_suite; + + if (master_test_suite().argc > 2 && strcmp(master_test_suite().argv[1], "sleep") == 0) + { + auto s = atoi(master_test_suite().argv[2]); + std::this_thread::sleep_for(std::chrono::seconds(s)); + return; + } + + namespace bp = boost::process; + boost::asio::io_context ios; + std::chrono::steady_clock::time_point p1, p2; + + // launch a child that will sleep for 2s + auto c1 = bp::child(master_test_suite().argv[0], "sleep", "2", ios, + bp::on_exit([&p1](int, const std::error_code&) + { p1 = std::chrono::steady_clock::now(); })); + + // wait a bit, make sure the child launch for my test + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + // launch a child that will sleep for 4s + auto c2 = bp::child(master_test_suite().argv[0], "sleep", "4", ios, + bp::on_exit([&p2](int, const std::error_code&) + { p2 = std::chrono::steady_clock::now(); })); + + // wait for the notifications + while (!ios.stopped()) + ios.run_one(); + + BOOST_REQUIRE((p2 - p1) > std::chrono::seconds(1)); +} + diff --git a/src/boost/libs/process/test/on_exit2.cpp b/src/boost/libs/process/test/on_exit2.cpp new file mode 100644 index 000000000..20d401bb5 --- /dev/null +++ b/src/boost/libs/process/test/on_exit2.cpp @@ -0,0 +1,50 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/asio.hpp> +#include <chrono> +#include <thread> + +BOOST_AUTO_TEST_CASE(double_ios, *boost::unit_test::timeout(6)) +{ + using boost::unit_test::framework::master_test_suite; + + if (master_test_suite().argc > 2 && strcmp(master_test_suite().argv[1], "sleep") == 0) + { + auto s = atoi(master_test_suite().argv[2]); + std::this_thread::sleep_for(std::chrono::seconds(s)); + return; + } + + namespace bp = boost::process; + boost::asio::io_context ios; + std::chrono::steady_clock::time_point p1, p2; + + // launch a child that will sleep for 2s + auto c1 = bp::child(master_test_suite().argv[0], "sleep", "2", ios, + bp::on_exit([&p1](int, const std::error_code&) + { p1 = std::chrono::steady_clock::now(); })); + + // wait a bit, make sure the child launch for my test + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + // launch a child that will sleep for 4s + auto c2 = bp::child(master_test_suite().argv[0], "sleep", "4", ios, + bp::on_exit([&p2](int, const std::error_code&) + { p2 = std::chrono::steady_clock::now(); })); + + + ios.run(); + BOOST_REQUIRE((p2 - p1) > std::chrono::seconds(1)); +} + diff --git a/src/boost/libs/process/test/on_exit3.cpp b/src/boost/libs/process/test/on_exit3.cpp new file mode 100644 index 000000000..84fe6845c --- /dev/null +++ b/src/boost/libs/process/test/on_exit3.cpp @@ -0,0 +1,51 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/asio.hpp> +#include <chrono> +#include <thread> + +BOOST_AUTO_TEST_CASE(double_ios_threaded, *boost::unit_test::timeout(6)) +{ + using boost::unit_test::framework::master_test_suite; + + if (master_test_suite().argc > 2 && strcmp(master_test_suite().argv[1], "sleep") == 0) + { + auto s = atoi(master_test_suite().argv[2]); + std::this_thread::sleep_for(std::chrono::seconds(s)); + return; + } + + namespace bp = boost::process; + boost::asio::io_context ios; + std::chrono::steady_clock::time_point p1, p2; + + // launch a child that will sleep for 2s + auto c1 = bp::child(master_test_suite().argv[0], "sleep", "2", ios, + bp::on_exit([&p1](int, const std::error_code&) + { p1 = std::chrono::steady_clock::now(); })); + + // wait a bit, make sure the child launch for my test + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + // launch a child that will sleep for 4s + auto c2 = bp::child(master_test_suite().argv[0], "sleep", "4", ios, + bp::on_exit([&p2](int, const std::error_code&) + { p2 = std::chrono::steady_clock::now(); })); + + // wait for the notifications + std::thread ([&ios] { ios.run(); }).join(); + + BOOST_REQUIRE((p2 - p1) > std::chrono::seconds(1)); +} + diff --git a/src/boost/libs/process/test/pipe.cpp b/src/boost/libs/process/test/pipe.cpp new file mode 100644 index 000000000..cb0caf8dc --- /dev/null +++ b/src/boost/libs/process/test/pipe.cpp @@ -0,0 +1,375 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#define BOOST_TEST_MAIN + +#include <boost/test/included/unit_test.hpp> +#include <iostream> +#include <thread> + +#include <boost/process/pipe.hpp> +#include <boost/process/environment.hpp> + +using namespace std; +namespace bp = boost::process; + +BOOST_AUTO_TEST_SUITE( pipe_tests ); + + +BOOST_AUTO_TEST_CASE(plain, *boost::unit_test::timeout(2)) +{ + bp::pipe pipe; + + std::string in = "test"; + pipe.write(in.c_str(), in.size()); + + std::string out; + out.resize(4); + pipe.read(&out.front(), out.size()); + + BOOST_CHECK_EQUAL(out, in); +} + +BOOST_AUTO_TEST_CASE(named, *boost::unit_test::timeout(2)) +{ + +#if defined( BOOST_WINDOWS_API ) + bp::pipe pipe("\\\\.\\pipe\\pipe_name"); +#elif defined( BOOST_POSIX_API ) + const auto home_path = boost::this_process::environment()["HOME"].to_string(); + bp::pipe pipe(home_path + "/.boost_process_test_pipe"); +#endif + + std::string in = "xyz"; + pipe.write(in.c_str(), in.size()); + + + std::string out; + out.resize(3); + pipe.read(&out.front(), out.size()); + + + BOOST_CHECK_EQUAL(out, in); +} + +BOOST_AUTO_TEST_CASE(copy_pipe, *boost::unit_test::timeout(2)) +{ + bp::pipe pipe; + + std::string in = "test"; + pipe.write(in.c_str(), in.size()); + + std::string out; + out.resize(4); + auto p2 = pipe; + p2.read(&out.front(), out.size()); + + BOOST_CHECK_EQUAL(out, in); +} + +BOOST_AUTO_TEST_CASE(move_pipe, *boost::unit_test::timeout(2)) +{ + bp::pipe pipe; + + std::string in = "test"; + pipe.write(in.c_str(), in.size()); + + std::string out; + out.resize(4); + auto p2 = std::move(pipe); + p2.read(&out.front(), out.size()); + + BOOST_CHECK_EQUAL(out, in); +} + +BOOST_AUTO_TEST_CASE(stream, *boost::unit_test::timeout(2)) +{ + + bp::pipe pipe; + + bp::pstream os(pipe); + bp::ipstream is(pipe); + + int i = 42, j = 0; + + os << i << std::endl; + os << std::endl; + is >> j; + + BOOST_CHECK_EQUAL(i, j); +} + +BOOST_AUTO_TEST_CASE(stream_move, *boost::unit_test::timeout(2)) +{ + + bp::pipe pipe; + + bp::pstream os(pipe); + bp::ipstream is(pipe); + + int i = 42, j = 0, k = 0; + + os << i << std::endl; + os << std::endl; + is >> j; + + BOOST_CHECK_EQUAL(i, j); + + bp::pstream os2 = std::move(os); + bp::ipstream is2 = std::move(is); + os2 << i << std::endl; + os2 << std::endl; + is2 >> k; + + BOOST_CHECK_EQUAL(i, k); +} + +BOOST_AUTO_TEST_CASE(ostream_move, *boost::unit_test::timeout(2)) +{ + + bp::pipe pipe; + + bp::opstream os(pipe); + bp::ipstream is(pipe); + + int i = 42, j = 0, k = 0; + + os << i << std::endl; + os << std::endl; + is >> j; + + BOOST_CHECK_EQUAL(i, j); + + bp::opstream os2 = std::move(os); + bp::ipstream is2 = std::move(is); + os2 << i << std::endl; + os2 << std::endl; + is2 >> k; + + BOOST_CHECK_EQUAL(i, k); +} + +BOOST_AUTO_TEST_CASE(stream_move_assignment, *boost::unit_test::timeout(2)) +{ + + bp::pipe pipe; + + bp::pstream os(pipe); + bp::ipstream is(pipe); + + int i = 42, j = 0, k = 0; + + os << i << std::endl; + os << std::endl; + is >> j; + + BOOST_CHECK_EQUAL(i, j); + + bp::pstream os2; + os2 = std::move(os); + bp::ipstream is2; + is2 = std::move(is); + os2 << i << std::endl; + os2 << std::endl; + is2 >> k; + + BOOST_CHECK_EQUAL(i, k); +} + +BOOST_AUTO_TEST_CASE(ostream_move_assignment, *boost::unit_test::timeout(2)) +{ + + bp::pipe pipe; + + bp::opstream os(pipe); + bp::ipstream is(pipe); + + int i = 42, j = 0, k = 0; + + os << i << std::endl; + os << std::endl; + is >> j; + + BOOST_CHECK_EQUAL(i, j); + + bp::opstream os2; + os2 = std::move(os); + bp::ipstream is2; + is2 = std::move(is); + os2 << i << std::endl; + os2 << std::endl; + is2 >> k; + + BOOST_CHECK_EQUAL(i, k); +} + +BOOST_AUTO_TEST_CASE(stream_line, *boost::unit_test::timeout(2)) +{ + + bp::pstream os; + + std::string s = "My Test String"; + + std::string out; + + os << s << std::endl; + + std::getline(os, out); + + auto size = (out.size() < s.size()) ? out.size() : s.size(); + + + BOOST_CHECK_EQUAL_COLLECTIONS( + s.begin(), s. begin() + size, + out.begin(), out.begin() + size + ); +} + + +BOOST_AUTO_TEST_CASE(large_data, *boost::unit_test::timeout(20)) +{ + bp::pipe pipe; + + bp::pipebuf is_buf(pipe); + bp::pipebuf os_buf(std::move(pipe)); + + std::istream is(&is_buf); + std::ostream os(&os_buf); + + std::string in(1000000, '0'); + std::string out; + + int cnt = 0; + for (auto & c: in) + c = (cnt++ % 26) + 'A'; + + std::thread th([&]{os << in << std::endl;}); + + is >> out; + BOOST_REQUIRE_EQUAL_COLLECTIONS(out.begin(), out.end(), in.begin(), in.end()); + th.join(); +} + +BOOST_AUTO_TEST_CASE(closed, *boost::unit_test::timeout(2)) +{ + bp::opstream os; + bp::ipstream is; + + os.pipe().close(); + is.pipe().close(); + + int i; + + BOOST_CHECK(!(os << 42 << endl)); + BOOST_CHECK(!(is >> i)); +} + + +BOOST_AUTO_TEST_CASE(coverage, *boost::unit_test::timeout(5)) +{ + //more of a syntax check, since template. + { + bp::pipe p1; + bp::ipstream is1(p1); + bp::ipstream is2(std::move(p1)); + + is2.pipe(is1.pipe()); + + bp::pipe p2_; + bp::pipe p2 = p2_; + BOOST_REQUIRE_NO_THROW(p2_ == p2); + BOOST_CHECK(p2_ == p2); + + bp::opstream os1(p2); + bp::opstream os2(std::move(p2)); + + os2.pipe(os1.pipe()); + + bp::pipe p3; + is1 = p3; + is2 = std::move(p3); + + bp::pipe p4_; + bp::pipe p4 = std::move(p4_); + + bp::pipe p5; + BOOST_REQUIRE_NO_THROW(p4_ != p4); + BOOST_CHECK(p4_ != p4); + + BOOST_REQUIRE_NO_THROW(p5 != p4); + BOOST_CHECK(p4 != p5); + + is1 = p4; + is2 = std::move(p4); + } + { + bp::wpipe p; + bp::wpstream ws1(p); + bp::wpstream ws2(std::move(p)); + + ws2.pipe(std::move(ws1.pipe())); + + bp::wpipe p2; + + ws1 = p2; + ws2 = std::move(p2); + + const bp::wpstream & ws2c = ws2; + ws1.pipe(ws2c.pipe()); + } + + { + bp::wpipe p; + bp::wpipebuf ws1(p); + bp::wpipebuf ws2(std::move(p)); + + ws2.pipe(std::move(ws1.pipe())); + + bp::wpipe p2; + + ws1 = p2; + ws2 = std::move(p2); + + const bp::wpipebuf & ws2c = ws2; + ws1.pipe(ws2c.pipe()); + + } +} + + +BOOST_AUTO_TEST_CASE(stream_close, *boost::unit_test::timeout(5)) +{ + bp::pipe p; + int i = 1234, j = 0; + bp::opstream op{p}; + bp::ipstream ip{p}; + p.close(); + + op << i << " "; + op.close(); + + ip >> j; + + BOOST_CHECK_EQUAL(i, j); +} + +BOOST_AUTO_TEST_CASE(stream_close_scope, *boost::unit_test::timeout(5)) +{ + bp::pipe p; + int i = 1234, j = 0; + bp::ipstream ip; + + { + bp::opstream op{ip.pipe()}; + op << i << " "; + } + ip >> j; + + BOOST_CHECK_EQUAL(i, j); +} + + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/boost/libs/process/test/pipe_fwd.cpp b/src/boost/libs/process/test/pipe_fwd.cpp new file mode 100644 index 000000000..9cdc73948 --- /dev/null +++ b/src/boost/libs/process/test/pipe_fwd.cpp @@ -0,0 +1,80 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <system_error> + +#include <boost/asio.hpp> +#include <boost/algorithm/string/predicate.hpp> + +#include <boost/process/args.hpp> +#include <boost/process/exe.hpp> +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/child.hpp> + + +#include <string> +#include <istream> +#include <iostream> +#include <cstdlib> + +BOOST_AUTO_TEST_SUITE( pipe_tests ); + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + + + bp::ipstream is; + bp::opstream os; + + bp::pipe p; + + std::error_code ec; + bp::child c1( + master_test_suite().argv[1], + bp::args={"test", "--prefix-once", "dear "}, + bp::std_in<os, + bp::std_out>p, + ec + ); + BOOST_REQUIRE(!ec); + + BOOST_TEST_INFO("Launching child 2"); + + bp::child c2( + master_test_suite().argv[1], + bp::args={"test", "--prefix-once", "hello "}, + bp::std_in<p, + bp::std_out>is, + ec + ); + BOOST_REQUIRE(!ec); + + os << "boost-user!" << std::endl; + + + std::string s; + std::getline(is, s); + + std::string cmp = "hello dear boost-user!"; + + s.resize(cmp.size()); + + BOOST_CHECK_EQUAL_COLLECTIONS(s.cbegin(), s.cend(),cmp.cbegin(), cmp.cend()); + + +} + +BOOST_AUTO_TEST_SUITE_END();
\ No newline at end of file diff --git a/src/boost/libs/process/test/posix_specific.cpp b/src/boost/libs/process/test/posix_specific.cpp new file mode 100644 index 000000000..b37cc9294 --- /dev/null +++ b/src/boost/libs/process/test/posix_specific.cpp @@ -0,0 +1,168 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process.hpp> +#include <boost/process/posix.hpp> + +#include <boost/filesystem.hpp> + +#include <system_error> + + +#include <string> +#include <sys/wait.h> +#include <errno.h> + +namespace fs = boost::filesystem; +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(bind_fd, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--posix-echo-one", "3", "hello", + bp::posix::fd.bind(3, p.native_sink()), + ec + ); + BOOST_CHECK(!ec); + + + bp::ipstream is(std::move(p)); + + std::string s; + is >> s; + BOOST_CHECK_EQUAL(s, "hello"); +} + +BOOST_AUTO_TEST_CASE(bind_fds, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p1; + bp::pipe p2; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test","--posix-echo-two","3","hello","99","bye", + bp::posix::fd.bind(3, p1.native_sink()), + bp::posix::fd.bind(99, p2.native_sink()), + ec + ); + BOOST_CHECK(!ec); + + bp::ipstream is1(std::move(p1)); + bp::ipstream is2(std::move(p2)); + + std::string s1; + is1 >> s1; + BOOST_CHECK_EQUAL(s1, "hello"); + + std::string s2; + is2 >> s2; + BOOST_CHECK_EQUAL(s2, "bye"); +} + +BOOST_AUTO_TEST_CASE(execve_set_on_error, *boost::unit_test::timeout(2)) +{ + std::error_code ec; + bp::spawn( + "doesnt-exist", + ec + ); + BOOST_CHECK(ec); + BOOST_CHECK_EQUAL(ec.value(), ENOENT); +} + +BOOST_AUTO_TEST_CASE(execve_throw_on_error, *boost::unit_test::timeout(2)) +{ + try + { + bp::spawn("doesnt-exist"); + BOOST_CHECK(false); + } + catch (bp::process_error &e) + { + BOOST_CHECK(e.code()); + BOOST_CHECK_EQUAL(e.code().value(), ENOENT); + } +} + +BOOST_AUTO_TEST_CASE(leak_test, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + + const auto pid = boost::this_process::get_id(); + const auto fd_path = fs::path("/proc") / std::to_string(pid) / "fd"; + + auto get_fds = [&]{ + std::vector<int> fds; + for (auto && fd : fs::directory_iterator(fd_path)) + fds.push_back(std::stoi(fd.path().filename().string())); + return fds; + }; + + std::vector<int> fd_list = get_fds(); + if (fd_list.empty()) //then there's no /proc in the current linux distribution. + return; + + + BOOST_CHECK(std::find(fd_list.begin(), fd_list.end(), STDOUT_FILENO) != fd_list.end()); + BOOST_CHECK(std::find(fd_list.begin(), fd_list.end(), STDIN_FILENO) != fd_list.end()); + BOOST_CHECK(std::find(fd_list.begin(), fd_list.end(), STDERR_FILENO) != fd_list.end()); + + bp::pipe p; //should add two descriptors. + + auto fd_list_new = get_fds(); + + BOOST_CHECK_EQUAL(fd_list_new.size(), fd_list.size() + 2); + fd_list.push_back(p.native_source()); + fd_list.push_back(p.native_sink()); + + + BOOST_CHECK_EQUAL( + bp::system( + master_test_suite().argv[1], + "test", "--exit-code", "123", ec), 123); + + fd_list_new = get_fds(); + BOOST_CHECK_EQUAL(fd_list.size(), fd_list_new.size()); + + + const int native_source = p.native_source(); + BOOST_CHECK_EQUAL( + bp::system( + master_test_suite().argv[1], + bp::std_in < p, + "test", "--exit-code", "123", ec), 123); + + BOOST_CHECK(!ec); + + ////now, p.source should be closed, so we remove it from fd_list + + const auto itr = std::find(fd_list.begin(), fd_list.end(), native_source); + if (itr != fd_list.end()) + fd_list.erase(itr); + + fd_list_new = get_fds(); + + BOOST_CHECK_EQUAL(fd_list.size(), fd_list_new.size()); + +}
\ No newline at end of file diff --git a/src/boost/libs/process/test/run_exe.cpp b/src/boost/libs/process/test/run_exe.cpp new file mode 100644 index 000000000..3de05bb20 --- /dev/null +++ b/src/boost/libs/process/test/run_exe.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/core/lightweight_test.hpp> +#include <iostream> + + +#include <boost/process/cmd.hpp> +#include <boost/process/error.hpp> +#include <boost/process/child.hpp> + +namespace bp = boost::process; + +int main(int argc, char* argv[]) +{ + std::error_code ec; + BOOST_TEST(!ec); + + bp::child c(argv[1], ec); + BOOST_TEST(!ec); + + if (ec) + std::cerr << ec.message() << std::endl; + + auto c2 = bp::child("doesnt-exist", ec); + BOOST_TEST(ec); + + + try + { + bp::child c("doesnt-exist"); + BOOST_TEST(false); + } + catch(bp::process_error & se) + { + BOOST_TEST(true); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/process/test/run_exe_path.cpp b/src/boost/libs/process/test/run_exe_path.cpp new file mode 100644 index 000000000..118fda7dc --- /dev/null +++ b/src/boost/libs/process/test/run_exe_path.cpp @@ -0,0 +1,50 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <system_error> +#include <boost/filesystem.hpp> + +#include <boost/process/cmd.hpp> +#include <boost/process/error.hpp> +#include <boost/process/child.hpp> + +namespace bp = boost::process; + + +BOOST_AUTO_TEST_CASE(run_exe_success) +{ + using boost::unit_test::framework::master_test_suite; + + boost::filesystem::path exe = master_test_suite().argv[1]; + + std::error_code ec; + bp::child c( + exe, + ec + ); + BOOST_CHECK(!ec); +} + +#if defined(BOOST_WINDOWS_API) +BOOST_AUTO_TEST_CASE(run_exe_error) +{ + boost::filesystem::path exe = "doesnt-exist"; + + std::error_code ec; + bp::child c( + exe, + ec + ); + BOOST_CHECK(ec); +} +#endif diff --git a/src/boost/libs/process/test/search_path.cpp b/src/boost/libs/process/test/search_path.cpp new file mode 100644 index 000000000..2dfc6fa75 --- /dev/null +++ b/src/boost/libs/process/test/search_path.cpp @@ -0,0 +1,39 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#include <boost/test/included/unit_test.hpp> +#include <boost/process/search_path.hpp> +#include <boost/filesystem/path.hpp> +#include <string> + +namespace bp = boost::process; +namespace fs = boost::filesystem; + +BOOST_AUTO_TEST_CASE(search_path) +{ +#if defined(BOOST_WINDOWS_API) + std::string filename = "cmd"; +#elif defined(BOOST_POSIX_API) + fs::path filename = "ls"; +#endif + + BOOST_CHECK(!bp::search_path(filename).empty()); + auto fs = bp::search_path(filename); + + std::cout << fs << std::endl; + +#if defined(BOOST_WINDOWS_API) + std::vector<fs::path> path = {"C:\\Windows","C:\\Windows\\System32"}; +#elif defined(BOOST_POSIX_API) + std::vector<fs::path> path = {"/usr/local/bin","/usr/bin","/bin"}; +#endif + + BOOST_CHECK(!bp::search_path(filename, path).empty()); +} diff --git a/src/boost/libs/process/test/shell.cpp b/src/boost/libs/process/test/shell.cpp new file mode 100644 index 000000000..ed4e48a3e --- /dev/null +++ b/src/boost/libs/process/test/shell.cpp @@ -0,0 +1,63 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <iostream> + + +#include <boost/process/cmd.hpp> +#include <boost/process/args.hpp> +#include <boost/process/pipe.hpp> +#include <boost/process/io.hpp> +#include <boost/process/error.hpp> +#include <boost/process/child.hpp> +#include <boost/process/shell.hpp> + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(shell_simple, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + BOOST_CHECK(!ec); + + bp::ipstream p; + + bp::child c(master_test_suite().argv[1], + bp::shell, + bp::args+={"test", "--echo-stdout", "hello"}, + ec, + bp::std_out > p); + BOOST_CHECK(!ec); + + if (ec) + std::cerr << ec.message() << std::endl; + std::string s; + + BOOST_TEST_CHECKPOINT("Starting read"); + p >> s; + BOOST_TEST_CHECKPOINT("Finished read"); + + BOOST_CHECK_EQUAL(s, "hello"); +} + +BOOST_AUTO_TEST_CASE(shell_error, *boost::unit_test::timeout(5)) +{ + std::error_code ec; + + + auto c2 = bp::child("doesnt-exist", bp::shell, ec); + BOOST_CHECK(!ec); + + c2.wait(); + BOOST_CHECK(c2.exit_code() != 0); +} diff --git a/src/boost/libs/process/test/shell_path.cpp b/src/boost/libs/process/test/shell_path.cpp new file mode 100644 index 000000000..dce7cdeb2 --- /dev/null +++ b/src/boost/libs/process/test/shell_path.cpp @@ -0,0 +1,30 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#include <boost/test/included/unit_test.hpp> +#include <boost/process/shell.hpp> +#include <boost/filesystem.hpp> +#include <system_error> + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(shell_set_on_error) +{ + std::error_code ec; + boost::filesystem::path p = bp::shell(ec); + BOOST_CHECK(!ec); + BOOST_CHECK(boost::filesystem::exists(p)); +} + +BOOST_AUTO_TEST_CASE(shell_throw_on_error) +{ + BOOST_CHECK_NO_THROW(bp::shell()); + BOOST_CHECK(boost::filesystem::exists(bp::shell())); +} diff --git a/src/boost/libs/process/test/sparring_partner.cpp b/src/boost/libs/process/test/sparring_partner.cpp new file mode 100644 index 000000000..c628832a1 --- /dev/null +++ b/src/boost/libs/process/test/sparring_partner.cpp @@ -0,0 +1,239 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_USE_WINDOWS_H + +#include <boost/program_options.hpp> +#include <boost/filesystem.hpp> +#include <boost/algorithm/string/join.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/range/algorithm/transform.hpp> +#include <boost/range/algorithm_ext/push_back.hpp> +#include <boost/lambda/lambda.hpp> +#include <boost/process/environment.hpp> +#include <boost/process/handles.hpp> +#include <vector> +#include <string> +#include <iterator> +#include <iostream> +#include <cstdlib> +#if defined(BOOST_POSIX_API) +# include <boost/lexical_cast.hpp> +# include <boost/iostreams/device/file_descriptor.hpp> +# include <boost/iostreams/stream.hpp> +# include <unistd.h> +#elif defined(BOOST_WINDOWS_API) +# include <windows.h> +#endif + + +using namespace boost::program_options; + +int main(int argc, char *argv[]) +{ + options_description desc; + desc.add_options() + ("echo-stdout", value<std::string>()) + ("echo-stderr", value<std::string>()) + ("echo-stdout-stderr", value<std::string>()) + ("echo-argv", bool_switch()) + ("exit-code", value<int>()) + ("wait", value<int>()) + ("is-closed-stdin", bool_switch()) + ("is-closed-stdout", bool_switch()) + ("is-closed-stderr", bool_switch()) + ("is-nul-stdin", bool_switch()) + ("is-nul-stdout", bool_switch()) + ("is-nul-stderr", bool_switch()) + ("loop", bool_switch()) + ("abort", bool_switch()) + ("prefix", value<std::string>()) + ("prefix-once", value<std::string>()) + ("pwd", bool_switch()) + ("query", value<std::string>()) + ("stdin-to-stdout", bool_switch()) + ("has-handle", value<std::uintptr_t>()) +#if defined(BOOST_POSIX_API) + ("posix-echo-one", value<std::vector<std::string> >()->multitoken()) + ("posix-echo-two", value<std::vector<std::string> >()->multitoken()); +#elif defined(BOOST_WINDOWS_API) + ("windows-print-showwindow", bool_switch()) + ("windows-print-flags", bool_switch()); +#endif + variables_map vm; + command_line_parser parser(argc, argv); + store(parser.options(desc).allow_unregistered().run(), vm); + notify(vm); + + if (vm.count("echo-stdout")) + { + std::cout << vm["echo-stdout"].as<std::string>() << std::endl; + } + else if (vm.count("echo-stderr")) + { + std::cerr << vm["echo-stderr"].as<std::string>() << std::endl; + } + else if (vm.count("echo-stdout-stderr")) + { + std::cout << vm["echo-stdout-stderr"].as<std::string>() << std::endl; + std::cerr << vm["echo-stdout-stderr"].as<std::string>() << std::endl; + } + else if (vm["echo-argv"].as<bool>()) + { + std::vector<char*> args(argv+1, argv + argc); + for (auto & arg : args) + std::cout << arg << std::endl; + } + else if (vm.count("exit-code")) + { + return vm["exit-code"].as<int>(); + } + else if (vm.count("wait")) + { + int sec = vm["wait"].as<int>(); +#if defined(BOOST_POSIX_API) + sleep(sec); +#elif defined(BOOST_WINDOWS_API) + Sleep(sec * 1000); +#endif + } + else if (vm["is-closed-stdin"].as<bool>()) + { + std::string s; + std::cin >> s; + return std::cin.eof() ? EXIT_SUCCESS : EXIT_FAILURE; + } + else if (vm["is-closed-stdout"].as<bool>()) + { + std::cout << "foo" << std::endl; + return std::cout.bad() ? EXIT_SUCCESS : EXIT_FAILURE; + } + else if (vm["is-closed-stderr"].as<bool>()) + { + std::cerr << "foo" << std::endl; + return std::cerr.bad() ? EXIT_SUCCESS : EXIT_FAILURE; + } + else if (vm["is-nul-stdin"].as<bool>()) + { +#if defined(BOOST_POSIX_API) + char buffer[1]; + int res = read(STDIN_FILENO, buffer, 1); + return res != -1 ? EXIT_SUCCESS : EXIT_FAILURE; +#elif defined(BOOST_WINDOWS_API) + HANDLE h = GetStdHandle(STD_INPUT_HANDLE); + if (h == INVALID_HANDLE_VALUE) + return EXIT_FAILURE; + char buffer[1]; + DWORD read; + BOOL res = ReadFile(h, buffer, 1, &read, NULL); + CloseHandle(h); + return res ? EXIT_SUCCESS : EXIT_FAILURE; +#endif + } + else if (vm["is-nul-stdout"].as<bool>()) + { + std::cout << "foo" << std::endl; + return std::cout.bad() ? EXIT_FAILURE : EXIT_SUCCESS; + } + else if (vm["is-nul-stderr"].as<bool>()) + { + std::cerr << "foo" << std::endl; + return std::cerr.bad() ? EXIT_FAILURE : EXIT_SUCCESS; + } + else if (vm["loop"].as<bool>()) + { + while (true); + } + else if (vm["abort"].as<bool>()) + { + std::abort(); + } + else if (vm.count("prefix")) + { + std::string line; + while (std::getline(std::cin, line)) + std::cout << vm["prefix"].as<std::string>() << line << std::endl; + } + else if (vm.count("prefix-once")) + { + std::string line; + + std::getline(std::cin, line); + + std::cout << vm["prefix-once"].as<std::string>() << line << std::endl; + } + else if (vm["pwd"].as<bool>()) + { + std::cout << boost::filesystem::current_path().string() << std::endl; + } + else if (vm.count("query")) + { + auto key = vm["query"].as<std::string>(); + auto env = boost::this_process::environment(); + auto val = env[key]; + if (val.empty()) + std::cout << "************** empty environment **************" << std::endl; + else + std::cout << val.to_string() << std::endl; + } + else if (vm["stdin-to-stdout"].as<bool>()) + { + char ch; + while (std::cin >> std::noskipws >> ch) + std::cout << ch << std::flush; + } +#if defined(BOOST_POSIX_API) + else if (vm.count("posix-echo-one")) + { + using namespace boost::iostreams; + std::vector<std::string> v = vm["posix-echo-one"].as<std::vector<std::string> >(); + int fd = boost::lexical_cast<int>(v[0]); + file_descriptor_sink sink(fd, close_handle); + stream<file_descriptor_sink> os(sink); + os << v[1] << std::endl; + } + else if (vm.count("posix-echo-two")) + { + using namespace boost::iostreams; + std::vector<std::string> v = vm["posix-echo-two"].as<std::vector<std::string> >(); + int fd1 = boost::lexical_cast<int>(v[0]); + file_descriptor_sink sink1(fd1, close_handle); + stream<file_descriptor_sink> os1(sink1); + os1 << v[1] << std::endl; + int fd2 = boost::lexical_cast<int>(v[2]); + file_descriptor_sink sink2(fd2, close_handle); + stream<file_descriptor_sink> os2(sink2); + os2 << v[3] << std::endl; + } +#elif defined(BOOST_WINDOWS_API) + else if (vm["windows-print-showwindow"].as<bool>()) + { + STARTUPINFO si; + GetStartupInfo(&si); + std::cout << si.wShowWindow << std::endl; + } + else if (vm["windows-print-flags"].as<bool>()) + { + STARTUPINFO si; + GetStartupInfo(&si); + std::cout << si.dwFlags << std::endl; + } +#endif + else if (vm.count("has-handle")) + { +#if defined(BOOST_WINDOWS_API) + const auto handle = reinterpret_cast<boost::this_process::native_handle_type>(vm["has-handle"].as<std::uintptr_t>()); +#else + const auto handle = static_cast<boost::this_process::native_handle_type>(vm["has-handle"].as<std::uintptr_t>()); +#endif + auto all_handles = boost::this_process::get_handles(); + return (std::find(all_handles.begin(), all_handles.end(), handle) != all_handles.end()) ? EXIT_SUCCESS : EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/src/boost/libs/process/test/spawn.cpp b/src/boost/libs/process/test/spawn.cpp new file mode 100644 index 000000000..25a2ecb3f --- /dev/null +++ b/src/boost/libs/process/test/spawn.cpp @@ -0,0 +1,109 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/system/error_code.hpp> + +#include <boost/asio.hpp> +#include <boost/algorithm/string/predicate.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/args.hpp> +#include <boost/process/spawn.hpp> +#include <boost/process/async_pipe.hpp> +#include <boost/process/async.hpp> +#include <system_error> + +#include <boost/filesystem.hpp> + +#include <string> +#include <istream> +#include <cstdlib> +#if defined(BOOST_WINDOWS_API) +# include <windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <unistd.h> +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +namespace fs = boost::filesystem; +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(sync_spawn, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::ipstream is; + std::error_code ec; + + bp::spawn( + master_test_suite().argv[1], + bp::args+={"test", "--echo-stdout", "hello"}, + bp::std_out > is, + ec + ); + + BOOST_CHECK(!ec); + + + std::string s; + + BOOST_TEST_CHECKPOINT("Starting read"); + is >> s; + BOOST_TEST_CHECKPOINT("Finished read"); + + BOOST_CHECK_EQUAL(s, "hello"); +} + + +struct read_handler +{ + boost::asio::streambuf &buffer_; + + read_handler(boost::asio::streambuf &buffer) : buffer_(buffer) {} + + void operator()(const boost::system::error_code &ec, std::size_t size) + { + std::istream is(&buffer_); + std::string line; + std::getline(is, line); + BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); + } +}; + +BOOST_AUTO_TEST_CASE(async_spawn, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context io_context; + bp::async_pipe p(io_context); + + std::error_code ec; + bp::spawn( + master_test_suite().argv[1], + "test", "--echo-stdout", "abc", + bp::std_out > p, + ec + ); + BOOST_REQUIRE(!ec); + + boost::asio::streambuf buffer; + boost::asio::async_read_until(p, buffer, '\n', + read_handler(buffer)); + + io_context.run(); +} + + diff --git a/src/boost/libs/process/test/spawn_fail.cpp b/src/boost/libs/process/test/spawn_fail.cpp new file mode 100644 index 000000000..3fa963ef8 --- /dev/null +++ b/src/boost/libs/process/test/spawn_fail.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/system/error_code.hpp> + +#include <boost/asio.hpp> +#include <boost/algorithm/string/predicate.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/args.hpp> +#include <boost/process/spawn.hpp> +#include <boost/process/async_pipe.hpp> +#include <boost/process/async.hpp> +#include <system_error> + +#include <boost/filesystem.hpp> + +#include <string> +#include <istream> +#include <cstdlib> +#if defined(BOOST_WINDOWS_API) +# include <windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <unistd.h> +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +namespace fs = boost::filesystem; +namespace bp = boost::process; + +int main() +{ + std::error_code ec; + + boost::asio::io_context ios; + + bp::spawn( + "dummy", + bp::on_exit([](int, const std::error_code&){}), + ios, + ec + ); +} + + + diff --git a/src/boost/libs/process/test/start_dir.cpp b/src/boost/libs/process/test/start_dir.cpp new file mode 100644 index 000000000..706c511c9 --- /dev/null +++ b/src/boost/libs/process/test/start_dir.cpp @@ -0,0 +1,64 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/filesystem.hpp> +#include <boost/algorithm/string/compare.hpp> +#include <string> +#include <iostream> + +namespace bp = boost::process; + + +struct test_dir +{ + std::string s_; + test_dir(const std::string &s) : s_(s) + { BOOST_REQUIRE_NO_THROW(boost::filesystem::create_directory(s)); } + ~test_dir() { boost::filesystem::remove(s_); } +}; + +BOOST_AUTO_TEST_CASE(start_in_dir) +{ + using boost::unit_test::framework::master_test_suite; + + test_dir dir("start_in_dir_test"); + + bp::ipstream is; + + std::error_code ec; + bp::child c( + bp::exe=boost::filesystem::absolute(master_test_suite().argv[1]).string(), + bp::args +={"test", "--pwd"}, + bp::start_dir = dir.s_, + bp::std_out>is, + ec + ); + BOOST_REQUIRE(!ec); + + + std::string s; + std::getline(is, s); + auto path_read = boost::filesystem::absolute(boost::filesystem::path(s)).string(); + auto path_set = boost::filesystem::absolute(dir.s_).string(); + + if (path_read.size() > path_set.size()) + path_read.resize(path_set.size()); + else if (path_read.size() < path_set.size()) + path_set.resize(path_read.size()); + + BOOST_CHECK_EQUAL_COLLECTIONS(path_read.begin(), path_read.end(), + path_set.begin(), path_set.end()); + + BOOST_REQUIRE_NO_THROW(c.wait()); +} diff --git a/src/boost/libs/process/test/sub_launcher.cpp b/src/boost/libs/process/test/sub_launcher.cpp new file mode 100644 index 000000000..c36490132 --- /dev/null +++ b/src/boost/libs/process/test/sub_launcher.cpp @@ -0,0 +1,83 @@ +// Copyright (c) 2015 Klemens D. Morgenstern +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> +#include <boost/program_options.hpp> + +#include <vector> +#include <string> + +#include <iostream> +#include <cstdint> + +#include <fstream> + +#include <chrono> + + +int main(int argc, char *argv[]) +{ + using namespace std; + using namespace boost::program_options; + using namespace boost::process; + + bool launch_detached = false; + bool launch_attached = false; + + options_description desc; + desc.add_options() + ("launch-detached", bool_switch(&launch_detached)) + ("launch-attached", bool_switch(&launch_attached)) + ; + + variables_map vm; + command_line_parser parser(argc, argv); + store(parser.options(desc).allow_unregistered().run(), vm); + notify(vm); + + child c1; + child c2; + + std::error_code ec; + + if (launch_attached) + { + c1 = child(argv[0], ec, std_out > null, std_err > null, std_in < null); + if (ec) + { + cout << -1 << endl; + cerr << ec.message() << endl; + return 1; + } + + cout << c1.id() << endl; + } + else + cout << -1 << endl; + + if (launch_detached) + { + group g; + + c2 = child(argv[0], ec, g, std_out > null, std_err > null, std_in < null); + if (ec) + { + cout << -1 << endl; + cerr << ec.message() << endl; + return 1; + } + else + cout << c2.id() << endl; + + g.detach(); + } + else + cout << -1 << endl; + + + this_thread::sleep_for(chrono::seconds(10)); + + + return 0; +} diff --git a/src/boost/libs/process/test/system_test1.cpp b/src/boost/libs/process/test/system_test1.cpp new file mode 100644 index 000000000..71aedd33f --- /dev/null +++ b/src/boost/libs/process/test/system_test1.cpp @@ -0,0 +1,81 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/system/error_code.hpp> + +#include <iostream> + +#include <boost/asio.hpp> +#include <boost/chrono.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <boost/asio/steady_timer.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/args.hpp> +#include <boost/process/system.hpp> +#include <boost/process/async_pipe.hpp> +#include <boost/process/async.hpp> +#include <system_error> + +#include <boost/filesystem.hpp> + +#include <string> +#include <chrono> +#include <istream> +#include <cstdlib> +#if defined(BOOST_WINDOWS_API) +# include <windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <unistd.h> +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +namespace fs = boost::filesystem; +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(system_exit_code, *boost::unit_test::timeout(5)) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + //I need to spawn a thread for that to work + + BOOST_CHECK_EQUAL( + bp::system( + master_test_suite().argv[1], + "test", "--exit-code", "123", ec), 123); + + BOOST_CHECK(!ec); +} + +BOOST_AUTO_TEST_CASE(implicit_async_io, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + std::future<std::string> fut; + std::error_code ec; + int res = bp::system( + master_test_suite().argv[1], + "test", "--echo-stdout", "abc", + bp::std_out > fut, + ec + ); + BOOST_REQUIRE(!ec); + BOOST_REQUIRE(fut.valid()); + BOOST_CHECK_EQUAL(res, 0); + BOOST_CHECK(boost::starts_with( + fut.get(), "abc")); +} diff --git a/src/boost/libs/process/test/system_test2.cpp b/src/boost/libs/process/test/system_test2.cpp new file mode 100644 index 000000000..e5d670233 --- /dev/null +++ b/src/boost/libs/process/test/system_test2.cpp @@ -0,0 +1,95 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/system/error_code.hpp> + +#include <iostream> + +#include <boost/asio.hpp> +#include <boost/chrono.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <boost/asio/steady_timer.hpp> +#include <boost/asio/deadline_timer.hpp> + +#include <boost/process/error.hpp> +#include <boost/process/io.hpp> +#include <boost/process/args.hpp> +#include <boost/process/system.hpp> +#include <boost/process/async_pipe.hpp> +#include <boost/process/async.hpp> +#include <system_error> + +#include <boost/filesystem.hpp> + +#include <atomic> +#include <string> +#include <chrono> +#include <istream> +#include <cstdlib> + +namespace fs = boost::filesystem; +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(explicit_async_io, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context ios; + + std::future<std::string> fut; + + std::error_code ec; + bp::system( + master_test_suite().argv[1], + "test", "--echo-stdout", "abc", + bp::std_out > fut, + ios, + ec + ); + BOOST_REQUIRE(!ec); + + BOOST_REQUIRE(fut.valid()); + BOOST_REQUIRE(boost::starts_with(fut.get(), "abc")); +} + +BOOST_AUTO_TEST_CASE(explicit_async_io_running, *boost::unit_test::timeout(10)) +{ + using boost::unit_test::framework::master_test_suite; + + boost::asio::io_context ios; + std::future<std::string> fut; + std::error_code ec; + + boost::asio::post( + ios.get_executor(), + [&] { + bp::system( + master_test_suite().argv[1], + "test", "--echo-stdout", "abc", + bp::std_out > fut, + ios, + ec + ); + BOOST_REQUIRE(!ec); + } + ); + + + ios.run(); + + BOOST_REQUIRE(fut.valid()); + BOOST_REQUIRE(boost::starts_with( + fut.get(), "abc")); + + +} diff --git a/src/boost/libs/process/test/terminate.cpp b/src/boost/libs/process/test/terminate.cpp new file mode 100644 index 000000000..0e9ce722b --- /dev/null +++ b/src/boost/libs/process/test/terminate.cpp @@ -0,0 +1,95 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + + + +#include <boost/process/error.hpp> +#include <boost/process/exe.hpp> +#include <boost/process/child.hpp> +#include <boost/process/args.hpp> +#include <system_error> +#include <thread> + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(terminate_set_on_error, *boost::unit_test::timeout(5)) +{ + std::atomic<bool> done{false}; + std::thread thr{ + [&] + { + for (int i = 0; i < 50 && !done.load(); i++) + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + BOOST_REQUIRE(done.load()); + }}; + + using boost::unit_test::framework::master_test_suite; + std::error_code ec; + bp::child c( + bp::exe(master_test_suite().argv[1]), + bp::args+={"test", "--loop"}, + ec + ); + BOOST_REQUIRE(!ec); + + BOOST_CHECK(c.valid()); + BOOST_CHECK(c.running(ec)); + + BOOST_CHECK(!c.wait_for(std::chrono::milliseconds(100), ec)); + BOOST_CHECK(c.running(ec)); + BOOST_CHECK(c.valid()); + + c.terminate(ec); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + BOOST_CHECK(!c.running(ec)); + BOOST_CHECK(!ec); + + done.store(true); + thr.join(); +} + +BOOST_AUTO_TEST_CASE(terminate_throw_on_error, *boost::unit_test::timeout(5)) +{ + std::atomic<bool> done{false}; + std::thread thr{ + [&] + { + for (int i = 0; i < 50 && !done.load(); i++) + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + BOOST_REQUIRE(done.load()); + }}; + + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::args+="test", + bp::args+="--loop", + ec + ); + BOOST_REQUIRE(!ec); + BOOST_CHECK(c.valid()); + BOOST_CHECK(c.running()); + + BOOST_CHECK(!c.wait_for(std::chrono::milliseconds(100), ec)); + BOOST_CHECK(c.running(ec)); + BOOST_CHECK(c.valid()); + + c.terminate(); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + BOOST_CHECK(!c.running()); + + done.store(true); + thr.join(); +} diff --git a/src/boost/libs/process/test/throw_on_error.cpp b/src/boost/libs/process/test/throw_on_error.cpp new file mode 100644 index 000000000..88f3e29ca --- /dev/null +++ b/src/boost/libs/process/test/throw_on_error.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/core/lightweight_test.hpp> + +#include <boost/process.hpp> +#include <boost/process/cmd.hpp> +#include <system_error> + +namespace bp = boost::process; + +int main(int argc, char* argv[]) +{ + bool thrown = false; + try { + bp::child c( + bp::cmd="doesnt-exist", + bp::throw_on_error + ); + thrown = false; + } + catch(bp::process_error & ) + { + thrown = true; + } + BOOST_TEST(thrown); + return boost::report_errors(); +} + diff --git a/src/boost/libs/process/test/vfork.cpp b/src/boost/libs/process/test/vfork.cpp new file mode 100644 index 000000000..b376d582d --- /dev/null +++ b/src/boost/libs/process/test/vfork.cpp @@ -0,0 +1,80 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> + +#include <boost/process.hpp> +#include <boost/process/posix.hpp> + +#include <system_error> + + +#include <string> +#include <sys/wait.h> +#include <errno.h> + +namespace bp = boost::process; + +#if defined(BOOST_POSIX_HAS_VFORK) + +BOOST_AUTO_TEST_CASE(bind_fd, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--posix-echo-one", "3", "hello", + bp::posix::fd.bind(3, p.native_sink()), + bp::posix::use_vfork, + ec + ); + BOOST_CHECK(!ec); + + + bp::ipstream is(std::move(p)); + + std::string s; + is >> s; + BOOST_CHECK_EQUAL(s, "hello"); +} + +BOOST_AUTO_TEST_CASE(execve_set_on_error, *boost::unit_test::timeout(2)) +{ + std::error_code ec; + bp::spawn( + "doesnt-exist", + bp::posix::use_vfork, + ec + ); + BOOST_CHECK(ec); + BOOST_CHECK_EQUAL(ec.value(), ENOENT); +} + +BOOST_AUTO_TEST_CASE(execve_throw_on_error, *boost::unit_test::timeout(2)) +{ + try + { + bp::spawn("doesnt-exist", bp::posix::use_vfork); + BOOST_CHECK(false); + } + catch (std::system_error &e) + { + BOOST_CHECK(e.code()); + BOOST_CHECK_EQUAL(e.code().value(), ENOENT); + } +} + +#else +BOOST_AUTO_TEST_CASE(dummy) {} +#endif diff --git a/src/boost/libs/process/test/wait.cpp b/src/boost/libs/process/test/wait.cpp new file mode 100644 index 000000000..d8e6b391a --- /dev/null +++ b/src/boost/libs/process/test/wait.cpp @@ -0,0 +1,75 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN + +#include <boost/test/included/unit_test.hpp> +#include <boost/process/error.hpp> +#include <boost/process/child.hpp> +#include <boost/process/args.hpp> +#include <boost/process/async.hpp> +#include <thread> +#include <atomic> +#include <system_error> +#include <boost/asio.hpp> +#if defined(BOOST_POSIX_API) +# include <signal.h> +#endif + +namespace bp = boost::process; + +BOOST_AUTO_TEST_SUITE( wait_test ); + + +BOOST_AUTO_TEST_CASE(sync_wait, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--wait", "1"}, + ec + ); + BOOST_REQUIRE(!ec); + + c.wait(); + +} + +BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(4)) +{ + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + boost::asio::io_context io_context; + + std::error_code ec; + bool called = false; + + boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(3)}; + timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();}); + + + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--wait", "1"}, + ec, + io_context, + bp::on_exit([&](int, const std::error_code&){called = true;}) + + ); + BOOST_REQUIRE(!ec); + + io_context.run(); + BOOST_CHECK(called); + +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/boost/libs/process/test/wait_for.cpp b/src/boost/libs/process/test/wait_for.cpp new file mode 100644 index 000000000..9ee58e495 --- /dev/null +++ b/src/boost/libs/process/test/wait_for.cpp @@ -0,0 +1,136 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +//#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process/error.hpp> +#include <boost/process/child.hpp> +#include <boost/process/args.hpp> +#include <thread> +#include <atomic> +#include <system_error> +#include <boost/asio.hpp> +#if defined(BOOST_POSIX_API) +# include <signal.h> +#endif + +namespace bp = boost::process; +BOOST_AUTO_TEST_SUITE( wait_test); + +BOOST_AUTO_TEST_CASE(wait_for) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + + auto launch_time = std::chrono::system_clock::now(); + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--wait", "1"}, + ec + ); + BOOST_REQUIRE(!ec); + + + BOOST_CHECK(!c.wait_for(std::chrono::milliseconds(200))); + BOOST_CHECK( c.wait_for(std::chrono::milliseconds(1000))); + + auto timeout_t = std::chrono::system_clock::now(); + + BOOST_CHECK_LE(std::chrono::duration_cast<std::chrono::seconds>(timeout_t - launch_time).count(), 5); //should be less +} + +BOOST_AUTO_TEST_CASE(wait_for_ec) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--wait", "1"}, + ec + ); + BOOST_REQUIRE(!ec); + + BOOST_CHECK(!c.wait_for(std::chrono::milliseconds(400),ec)); + BOOST_CHECK( c.wait_for(std::chrono::milliseconds(1000),ec)); + + BOOST_CHECK_MESSAGE(!ec, ec.message()); +} + + +BOOST_AUTO_TEST_CASE(wait_until) +{ + using boost::unit_test::framework::master_test_suite; + std::error_code ec; + + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--wait", "1"}, + ec + ); + BOOST_REQUIRE(!ec); + + auto now = std::chrono::system_clock::now(); + + auto t1 = now + std::chrono::milliseconds(400); + auto t2 = now + std::chrono::milliseconds(1200); + + BOOST_CHECK(!c.wait_until(t1)); + BOOST_CHECK( c.wait_until(t2)); + +} + +BOOST_AUTO_TEST_CASE(wait_until_ec) +{ + using boost::unit_test::framework::master_test_suite; + std::error_code ec; + + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--wait", "1"}, + ec + ); + BOOST_REQUIRE(!ec); + + auto now = std::chrono::system_clock::now(); + + auto t1 = now + std::chrono::milliseconds(400); + auto t2 = now + std::chrono::milliseconds(1200); + + BOOST_CHECK(!c.wait_until(t1, ec)); + BOOST_CHECK( c.wait_until(t2, ec)); + + BOOST_CHECK_MESSAGE(!ec, ec.message()); +} + +BOOST_AUTO_TEST_CASE(wait_for_exit_before_timeout) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + + auto launch_time = std::chrono::system_clock::now(); + bp::child c( + master_test_suite().argv[1], + bp::args+={"test", "--wait", "1"}, + ec + ); + BOOST_REQUIRE(!ec); + + BOOST_CHECK(c.wait_for(std::chrono::seconds(20))); + + auto timeout_t = std::chrono::system_clock::now(); + + // check that we didn't wait the entire timeout period + BOOST_CHECK_LT(std::chrono::duration_cast<std::chrono::seconds>(timeout_t - launch_time).count(), 20); +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/boost/libs/process/test/wargs_cmd.cpp b/src/boost/libs/process/test/wargs_cmd.cpp new file mode 100644 index 000000000..76dad6f43 --- /dev/null +++ b/src/boost/libs/process/test/wargs_cmd.cpp @@ -0,0 +1,115 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD + +#include <boost/test/included/unit_test.hpp> + +#include <boost/process/exe.hpp> +#include <boost/process/args.hpp> +#include <boost/process/cmd.hpp> +#include <boost/process/io.hpp> +#include <boost/process/error.hpp> +#include <boost/process/child.hpp> + +#include <boost/algorithm/string/predicate.hpp> + +namespace bp = boost::process; + + +BOOST_AUTO_TEST_CASE(wargs, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::ipstream is; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + L"test", "--echo-argv", L"hello thingy", "\"stuff\"", static_cast<const wchar_t*>(L" spa ce "), + bp::std_out>is, + ec + ); + if (ec) + std::cout << "EC: " << ec.message() << std::endl; + BOOST_REQUIRE(!ec); + + std::string s; + + std::getline(is, s); + s.resize(4); + BOOST_CHECK_EQUAL(s, "test"); + + std::getline(is, s); + s.resize(11); + BOOST_CHECK_EQUAL(s, "--echo-argv"); + + std::getline(is, s); + s.resize(12); + + BOOST_CHECK_EQUAL(s, "hello thingy"); + + std::getline(is, s); + s.resize(7); + + BOOST_CHECK_EQUAL(s, "\"stuff\""); + + std::getline(is, s); + s.resize(10); + + BOOST_CHECK_EQUAL(s, " spa ce "); + +} + + +BOOST_AUTO_TEST_CASE(wcmd, *boost::unit_test::timeout(2)) +{ + using boost::unit_test::framework::master_test_suite; + + bp::ipstream is; + + std::error_code ec; + + std::wstring cmd = + bp::detail::convert(master_test_suite().argv[1]); + cmd+= L" test --echo-argv \"hello thingy\" \\\"stuff\\\" \" spa ce \""; + + bp::child c(cmd, + bp::std_out>is, + ec + ); + BOOST_REQUIRE(!ec); + + std::string s; + + std::getline(is, s); + s.resize(4); + BOOST_CHECK_EQUAL(s, "test"); + + std::getline(is, s); + s.resize(11); + BOOST_CHECK_EQUAL(s, "--echo-argv"); + + std::getline(is, s); + s.resize(12); + + BOOST_CHECK_EQUAL(s, "hello thingy"); + + std::getline(is, s); + s.resize(7); + + BOOST_CHECK_EQUAL(s, "\"stuff\""); + + std::getline(is, s); + s.resize(10); + + BOOST_CHECK_EQUAL(s, " spa ce "); +} + diff --git a/src/boost/libs/process/test/windows_specific.cpp b/src/boost/libs/process/test/windows_specific.cpp new file mode 100644 index 000000000..f8842030e --- /dev/null +++ b/src/boost/libs/process/test/windows_specific.cpp @@ -0,0 +1,92 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/process/windows.hpp> +#include <boost/process/extend.hpp> +#include <boost/system/error_code.hpp> + +#include <string> + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(show_window) +{ + using boost::unit_test::framework::master_test_suite; + + bp::ipstream is; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + "test", "--windows-print-showwindow", + bp::windows::show_normal, + bp::std_out>is, + ec + ); + BOOST_REQUIRE(!ec); + + int i; + is >> i; + BOOST_CHECK_EQUAL(i, SW_SHOWNORMAL); +} + + +#if ( BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 ) + +struct set_startup_info +{ + int &cnt; + template<typename T> + void operator()(T &e) const + { + cnt++; + BOOST_CHECK_EQUAL(e.startup_info.cb, sizeof(::boost::winapi::STARTUPINFOA_)); + e.set_startup_info_ex(); + } + +}; + +struct check_startup_info +{ + int &cnt; + template<typename T> + void operator()(T &e) const + { + cnt++; + BOOST_CHECK(e.creation_flags & ::boost::winapi::EXTENDED_STARTUPINFO_PRESENT_); + BOOST_CHECK_EQUAL(e.startup_info.cb, sizeof(::boost::winapi::STARTUPINFOEXA_)); + } + +}; + +BOOST_AUTO_TEST_CASE(startup_info_ex) +{ + using boost::unit_test::framework::master_test_suite; + + bp::ipstream is; + + int cnt = 0; + + std::error_code ec; + bp::child c( + master_test_suite().argv[1], + bp::extend::on_setup(set_startup_info{cnt}), + bp::extend::on_success(check_startup_info{cnt}), + bp::std_out>is, + ec + ); + BOOST_REQUIRE(!ec); + BOOST_CHECK_EQUAL(cnt, 2); +} + +#endif |