summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/process/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/process/test
parentInitial commit. (diff)
downloadceph-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')
-rw-r--r--src/boost/libs/process/test/Jamfile.jam134
-rw-r--r--src/boost/libs/process/test/args_cmd.cpp116
-rw-r--r--src/boost/libs/process/test/args_handling.cpp79
-rw-r--r--src/boost/libs/process/test/asio_no_deprecated.cpp13
-rw-r--r--src/boost/libs/process/test/async.cpp416
-rw-r--r--src/boost/libs/process/test/async_fut.cpp106
-rw-r--r--src/boost/libs/process/test/async_pipe.cpp147
-rw-r--r--src/boost/libs/process/test/async_system_fail.cpp28
-rw-r--r--src/boost/libs/process/test/async_system_future.cpp64
-rw-r--r--src/boost/libs/process/test/async_system_stackful.cpp58
-rw-r--r--src/boost/libs/process/test/async_system_stackful_error.cpp111
-rw-r--r--src/boost/libs/process/test/async_system_stackful_except.cpp55
-rw-r--r--src/boost/libs/process/test/async_system_stackless.cpp71
-rw-r--r--src/boost/libs/process/test/bind_stderr.cpp155
-rw-r--r--src/boost/libs/process/test/bind_stdin.cpp260
-rw-r--r--src/boost/libs/process/test/bind_stdin_stdout.cpp58
-rw-r--r--src/boost/libs/process/test/bind_stdout.cpp171
-rw-r--r--src/boost/libs/process/test/bind_stdout_stderr.cpp138
-rw-r--r--src/boost/libs/process/test/close_stderr.cpp48
-rw-r--r--src/boost/libs/process/test/close_stdin.cpp47
-rw-r--r--src/boost/libs/process/test/close_stdout.cpp47
-rw-r--r--src/boost/libs/process/test/cmd_test.cpp85
-rw-r--r--src/boost/libs/process/test/env.cpp180
-rw-r--r--src/boost/libs/process/test/environment.cpp268
-rw-r--r--src/boost/libs/process/test/error.cpp115
-rw-r--r--src/boost/libs/process/test/exit_argc.cpp14
-rw-r--r--src/boost/libs/process/test/exit_code.cpp159
-rw-r--r--src/boost/libs/process/test/extensions.cpp101
-rw-r--r--src/boost/libs/process/test/group.cpp191
-rw-r--r--src/boost/libs/process/test/group_wait.cpp135
-rw-r--r--src/boost/libs/process/test/limit_fd.cpp179
-rw-r--r--src/boost/libs/process/test/multi_ref1.cpp7
-rw-r--r--src/boost/libs/process/test/multi_ref2.cpp6
-rw-r--r--src/boost/libs/process/test/no_ansi_apps.cpp10
-rw-r--r--src/boost/libs/process/test/on_exit.cpp52
-rw-r--r--src/boost/libs/process/test/on_exit2.cpp50
-rw-r--r--src/boost/libs/process/test/on_exit3.cpp51
-rw-r--r--src/boost/libs/process/test/pipe.cpp375
-rw-r--r--src/boost/libs/process/test/pipe_fwd.cpp80
-rw-r--r--src/boost/libs/process/test/posix_specific.cpp168
-rw-r--r--src/boost/libs/process/test/run_exe.cpp46
-rw-r--r--src/boost/libs/process/test/run_exe_path.cpp50
-rw-r--r--src/boost/libs/process/test/search_path.cpp39
-rw-r--r--src/boost/libs/process/test/shell.cpp63
-rw-r--r--src/boost/libs/process/test/shell_path.cpp30
-rw-r--r--src/boost/libs/process/test/sparring_partner.cpp239
-rw-r--r--src/boost/libs/process/test/spawn.cpp109
-rw-r--r--src/boost/libs/process/test/spawn_fail.cpp55
-rw-r--r--src/boost/libs/process/test/start_dir.cpp64
-rw-r--r--src/boost/libs/process/test/sub_launcher.cpp83
-rw-r--r--src/boost/libs/process/test/system_test1.cpp81
-rw-r--r--src/boost/libs/process/test/system_test2.cpp95
-rw-r--r--src/boost/libs/process/test/terminate.cpp95
-rw-r--r--src/boost/libs/process/test/throw_on_error.cpp35
-rw-r--r--src/boost/libs/process/test/vfork.cpp80
-rw-r--r--src/boost/libs/process/test/wait.cpp75
-rw-r--r--src/boost/libs/process/test/wait_for.cpp136
-rw-r--r--src/boost/libs/process/test/wargs_cmd.cpp115
-rw-r--r--src/boost/libs/process/test/windows_specific.cpp92
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