1 // Copyright (c) 2016 Klemens D. Morgenstern
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6
7 #define BOOST_TEST_MAIN
8
9 #include <boost/test/included/unit_test.hpp>
10 #include <iostream>
11 #include <thread>
12 #include <vector>
13 #include <boost/algorithm/string/predicate.hpp>
14
15 #include <boost/process/async_pipe.hpp>
16 #include <boost/process/pipe.hpp>
17 #include <boost/asio/read.hpp>
18 #include <boost/asio/read_until.hpp>
19 #include <boost/asio/write.hpp>
20 #include <boost/asio/streambuf.hpp>
21
22 using namespace std;
23 namespace bp = boost::process;
24 namespace asio = boost::asio;
25
26 BOOST_AUTO_TEST_SUITE( async );
27
28
29 BOOST_AUTO_TEST_CASE(plain_async, *boost::unit_test::timeout(5))
30 {
31 asio::io_context ios;
32 bp::async_pipe pipe{ios};
33
34 std::string st = "test-string\n";
35
36 asio::streambuf buf;
37
__anon82464aaf0102(const boost::system::error_code &, std::size_t)38 asio::async_write(pipe, asio::buffer(st), [](const boost::system::error_code &, std::size_t){});
__anon82464aaf0202(const boost::system::error_code &, std::size_t)39 asio::async_read_until(pipe, buf, '\n', [](const boost::system::error_code &, std::size_t){});
40
41 ios.run();
42
43 std::string line;
44 std::istream istr(&buf);
45 BOOST_CHECK(std::getline(istr, line));
46
47 line.resize(11);
48 BOOST_CHECK_EQUAL(line, "test-string");
49
50 }
51
BOOST_AUTO_TEST_CASE(closed_transform)52 BOOST_AUTO_TEST_CASE(closed_transform)
53 {
54 asio::io_context ios;
55
56 bp::async_pipe ap{ios};
57
58 BOOST_CHECK(ap.is_open());
59 bp::pipe p2 = static_cast<bp::pipe>(ap);
60 BOOST_CHECK(p2.is_open());
61
62 ap.close();
63 BOOST_CHECK(!ap.is_open());
64
65 bp::pipe p = static_cast<bp::pipe>(ap);
66 BOOST_CHECK(!p.is_open());
67
68 }
69
BOOST_AUTO_TEST_CASE(multithreaded_async_pipe)70 BOOST_AUTO_TEST_CASE(multithreaded_async_pipe)
71 {
72 asio::io_context ioc;
73
74 std::vector<std::thread> threads;
75 for (int i = 0; i < std::thread::hardware_concurrency(); i++)
76 {
77 threads.emplace_back([&ioc]
78 {
79 std::vector<bp::async_pipe*> pipes;
80 for (size_t i = 0; i < 100; i++)
81 pipes.push_back(new bp::async_pipe(ioc));
82 for (auto &p : pipes)
83 delete p;
84 });
85 }
86 for (auto &t : threads)
87 t.join();
88 }
89
90
91
BOOST_AUTO_TEST_CASE(move_pipe)92 BOOST_AUTO_TEST_CASE(move_pipe)
93 {
94 asio::io_context ios;
95
96 bp::async_pipe ap{ios};
97 BOOST_TEST_CHECKPOINT("First move");
98 bp::async_pipe ap2{std::move(ap)};
99 #if defined(BOOST_WINDOWS_API)
100 BOOST_CHECK_EQUAL(ap.native_source(), ::boost::winapi::INVALID_HANDLE_VALUE_);
101 BOOST_CHECK_EQUAL(ap.native_sink (), ::boost::winapi::INVALID_HANDLE_VALUE_);
102 #elif defined(BOOST_POSIX_API)
103 BOOST_CHECK_EQUAL(ap.native_source(), -1);
104 BOOST_CHECK_EQUAL(ap.native_sink (), -1);
105 #endif
106
107 BOOST_TEST_CHECKPOINT("Second move");
108 ap = std::move(ap2);
109
110 {
111 BOOST_TEST_CHECKPOINT("Third move, from closed");
112 bp::async_pipe ap_inv{ios};
113 ap_inv.close();
114 ap = std::move(ap_inv);
115 }
116
117 {
118 BOOST_TEST_CHECKPOINT("Fourth move, from closed");
119 bp::async_pipe ap_inv{ios};
120 ap_inv.close();
121 const auto ap3 = std::move(ap_inv);
122 }
123
124 {
125 //copy an a closed pipe
126 BOOST_TEST_CHECKPOINT("Copy assign");
127 BOOST_TEST_CHECKPOINT("Fourth move, from closed");
128 bp::async_pipe ap_inv{ios};
129 ap_inv.close();
130 ap = ap_inv; //copy an invalid pipe
131 }
132
133 {
134 //copy an a closed pipe
135 BOOST_TEST_CHECKPOINT("Copy assign");
136 BOOST_TEST_CHECKPOINT("Fourth move, from closed");
137 bp::async_pipe ap_inv{ios};
138 ap_inv.close();
139 BOOST_TEST_CHECKPOINT("Copy construct");
140 bp::async_pipe ap4{ap_inv};
141 }
142
143
144 }
145
146
147 BOOST_AUTO_TEST_SUITE_END();