• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
2 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
3 // Copyright (c) 2009 Boris Schaeling
4 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
5 // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 
10 #define BOOST_TEST_MAIN
11 #define BOOST_TEST_IGNORE_SIGCHLD
12 #include <boost/test/included/unit_test.hpp>
13 
14 #include <boost/process.hpp>
15 #include <boost/process/posix.hpp>
16 
17 #include <boost/filesystem.hpp>
18 
19 #include <system_error>
20 
21 
22 #include <string>
23 #include <sys/wait.h>
24 #include <errno.h>
25 
26 namespace fs = boost::filesystem;
27 namespace bp = boost::process;
28 
29 BOOST_AUTO_TEST_CASE(bind_fd, *boost::unit_test::timeout(2))
30 {
31     using boost::unit_test::framework::master_test_suite;
32 
33     bp::pipe p;
34 
35     std::error_code ec;
36     bp::child c(
37         master_test_suite().argv[1],
38         "test", "--posix-echo-one", "3", "hello",
39         bp::posix::fd.bind(3, p.native_sink()),
40         ec
41     );
42     BOOST_CHECK(!ec);
43 
44 
45     bp::ipstream is(std::move(p));
46 
47     std::string s;
48     is >> s;
49     BOOST_CHECK_EQUAL(s, "hello");
50 }
51 
52 BOOST_AUTO_TEST_CASE(bind_fds, *boost::unit_test::timeout(2))
53 {
54     using boost::unit_test::framework::master_test_suite;
55 
56     bp::pipe p1;
57     bp::pipe p2;
58 
59     std::error_code ec;
60     bp::child c(
61         master_test_suite().argv[1],
62         "test","--posix-echo-two","3","hello","99","bye",
63         bp::posix::fd.bind(3,  p1.native_sink()),
64         bp::posix::fd.bind(99, p2.native_sink()),
65         ec
66     );
67     BOOST_CHECK(!ec);
68 
69     bp::ipstream is1(std::move(p1));
70     bp::ipstream is2(std::move(p2));
71 
72     std::string s1;
73     is1 >> s1;
74     BOOST_CHECK_EQUAL(s1, "hello");
75 
76     std::string s2;
77     is2 >> s2;
78     BOOST_CHECK_EQUAL(s2, "bye");
79 }
80 
81 BOOST_AUTO_TEST_CASE(execve_set_on_error, *boost::unit_test::timeout(2))
82 {
83     std::error_code ec;
84     bp::spawn(
85         "doesnt-exist",
86         ec
87     );
88     BOOST_CHECK(ec);
89     BOOST_CHECK_EQUAL(ec.value(), ENOENT);
90 }
91 
92 BOOST_AUTO_TEST_CASE(execve_throw_on_error, *boost::unit_test::timeout(2))
93 {
94     try
95     {
96         bp::spawn("doesnt-exist");
97         BOOST_CHECK(false);
98     }
99     catch (bp::process_error &e)
100     {
101         BOOST_CHECK(e.code());
102         BOOST_CHECK_EQUAL(e.code().value(), ENOENT);
103     }
104 }
105 
106 BOOST_AUTO_TEST_CASE(leak_test, *boost::unit_test::timeout(5))
107 {
108     using boost::unit_test::framework::master_test_suite;
109 
110     std::error_code ec;
111 
112     const auto pid = boost::this_process::get_id();
113     const auto  fd_path = fs::path("/proc") / std::to_string(pid) / "fd";
114 
__anondf27bc370102null115     auto get_fds = [&]{
116         std::vector<int> fds;
117         for (auto && fd : fs::directory_iterator(fd_path))
118             fds.push_back(std::stoi(fd.path().filename().string()));
119         return fds;
120     };
121 
122     std::vector<int> fd_list = get_fds();
123     if (fd_list.empty()) //then there's no /proc in the current linux distribution.
124         return;
125 
126 
127     BOOST_CHECK(std::find(fd_list.begin(), fd_list.end(), STDOUT_FILENO) != fd_list.end());
128     BOOST_CHECK(std::find(fd_list.begin(), fd_list.end(),  STDIN_FILENO) != fd_list.end());
129     BOOST_CHECK(std::find(fd_list.begin(), fd_list.end(), STDERR_FILENO) != fd_list.end());
130 
131     bp::pipe p; //should add two descriptors.
132 
133     auto fd_list_new = get_fds();
134 
135     BOOST_CHECK_EQUAL(fd_list_new.size(), fd_list.size() + 2);
136     fd_list.push_back(p.native_source());
137     fd_list.push_back(p.native_sink());
138 
139 
140     BOOST_CHECK_EQUAL(
141             bp::system(
142                     master_test_suite().argv[1],
143                     "test", "--exit-code", "123",  ec), 123);
144 
145     fd_list_new = get_fds();
146     BOOST_CHECK_EQUAL(fd_list.size(), fd_list_new.size());
147 
148 
149     const int native_source = p.native_source();
150     BOOST_CHECK_EQUAL(
151             bp::system(
152                     master_test_suite().argv[1],
153                     bp::std_in < p,
154                     "test", "--exit-code", "123",  ec), 123);
155 
156     BOOST_CHECK(!ec);
157 
158    ////now, p.source should be closed, so we remove it from fd_list
159 
160    const auto itr = std::find(fd_list.begin(), fd_list.end(), native_source);
161    if (itr != fd_list.end())
162        fd_list.erase(itr);
163 
164     fd_list_new = get_fds();
165 
166     BOOST_CHECK_EQUAL(fd_list.size(), fd_list_new.size());
167 
168 }