early-access version 3088

This commit is contained in:
pineappleEA
2022-11-05 15:35:56 +01:00
parent 4e4fc25ce3
commit b601909c6d
35519 changed files with 5996896 additions and 860 deletions

View File

@@ -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 ]
;

View File

@@ -0,0 +1,78 @@
# Use, modification, and distribution are
# subject to 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)
#
# Copyright Antony Polukhin 2016.
#
# See https://svn.boost.org/trac/boost/wiki/TravisCoverals for description of this file
# and how it can be used with Boost libraries.
#
# File revision #1
init:
- set BRANCH_TO_TEST=%APPVEYOR_REPO_BRANCH%
- set BOOST_REMOVE=process
- set BOOST_TEST_LOG_LEVEL=success
os: Visual Studio 2015
configuration: Debug
platform: x64
build: off
###############################################################################################################
# From this point and below code is same for all the Boost libs
###############################################################################################################
version: 1.69.{build}-{branch}
# branches to build
branches:
except:
- gh-pages
skip_tags: true
before_build:
# Set this to the name of the library
- set PROJECT_TO_TEST=%APPVEYOR_PROJECT_NAME%
- echo "Testing %PROJECT_TO_TEST%"
# Cloning Boost libraries (fast nondeep cloning)
- if %BRANCH_TO_TEST%==master ( set BOOST_BRANCH=master ) else ( set BOOST_BRANCH=develop )
- set BOOST=C:/boost-local
- git init %BOOST%
- cd %BOOST%
- git remote add --no-tags -t %BOOST_BRANCH% origin https://github.com/boostorg/boost.git
- git fetch --depth=1
- git checkout %BOOST_BRANCH%
- git submodule update --init --merge
- git remote set-branches --add origin %BOOST_BRANCH%
- git pull --recurse-submodules
- git submodule update --init
- git checkout %BOOST_BRANCH%
#- git submodule foreach "git reset --quiet --hard"
#- git submodule foreach "git clean -fxd"
- git reset --hard
- git clean -fxd
- git status
- rm -rf %BOOST%/libs/%BOOST_REMOVE%
- mv %APPVEYOR_BUILD_FOLDER% %BOOST%/libs/%PROJECT_TO_TEST%
- set TRAVIS_BUILD_DIR=%BOOST%/libs/%PROJECT_TO_TEST%
build_script:
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
- bootstrap.bat
- b2.exe headers
- cd %BOOST%/libs/%PROJECT_TO_TEST%/test
after_build:
before_test:
test_script:
- ..\..\..\b2.exe address-model=64 architecture=x86 cxxflags="-DBOOST_TRAVISCI_BUILD" -sBOOST_BUILD_PATH=. --boost-process-report-ci
after_test:
on_success:
on_failure:
on_finish:
- curl -s https://report.ci/upload.py | python - --name "Windows test run" --root_dir=%BOOST%

View File

@@ -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 ");
}

View File

@@ -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"
}

View File

@@ -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

View File

@@ -0,0 +1,417 @@
// 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{[&]() noexcept {io_context1.run();}};
std::thread thr2{[&]() noexcept {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", "exit-code", "42",
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, 42);
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(), 3u);
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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -0,0 +1,63 @@
// 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();
BOOST_CHECK_THROW(fut.get(), boost::system::system_error);
}
BOOST_AUTO_TEST_SUITE_END();

View File

@@ -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", "--wait", "1");
BOOST_CHECK_EQUAL(ret, 0);
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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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, 42u);
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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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));
}
}

View File

@@ -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;
}

View File

@@ -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());
}

View File

@@ -0,0 +1,98 @@
// 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";
}
template <class Sequence>
void on_setup(ex::posix_executor<Sequence>& exec) const
{
st = "posix";
}
};
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
}

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -0,0 +1,180 @@
// 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(), 3u);
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() + 2u, 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()), 1u);
BOOST_CHECK_EQUAL(std::count(fd_list.begin(), fd_list.end(), p.native_sink()), 1u);
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()), 0u);
BOOST_CHECK_EQUAL(std::count(fd_list.begin(), fd_list.end(), p.native_sink()), 0u);
#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);
});
}
};
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, 42u);
BOOST_CHECK_EQUAL(std::count(res.begin(), res.end(), p_in. native_sink()), 0u);
BOOST_CHECK_EQUAL(std::count(res.begin(), res.end(), p_out.native_source()), 0u);
}
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
auto p = fopen("./test-file", "w");
using boost::unit_test::framework::master_test_suite;
BOOST_CHECK_EQUAL(bp::system(master_test_suite().argv[1], "--has-handle", bp::limit_handles, get_handle(p), bp::std_in < p), EXIT_SUCCESS);
BOOST_CHECK_EQUAL(bp::system(master_test_suite().argv[1], "--has-handle", bp::limit_handles, get_handle(p), bp::std_err > p), EXIT_SUCCESS);
BOOST_CHECK_EQUAL(bp::system(master_test_suite().argv[1], "--has-handle", bp::limit_handles, get_handle(p), bp::std_out > p), EXIT_SUCCESS);
BOOST_CHECK_EQUAL(bp::system(master_test_suite().argv[1], "--has-handle", bp::limit_handles, get_handle(p)), EXIT_FAILURE);
fclose(p);
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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));
}

View File

@@ -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));
}

View File

@@ -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));
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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());
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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());
}

View File

@@ -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);
}

View File

@@ -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()));
}

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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
);
}

View File

@@ -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());
}

View File

@@ -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;
}

View File

@@ -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"));
}

View File

@@ -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"));
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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();

View File

@@ -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();

View File

@@ -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(11);
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 ");
}

View File

@@ -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