async_pipe.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. #define BOOST_TEST_MAIN
  6. #include <boost/test/included/unit_test.hpp>
  7. #include <iostream>
  8. #include <thread>
  9. #include <vector>
  10. #include <boost/algorithm/string/predicate.hpp>
  11. #include <boost/process/async_pipe.hpp>
  12. #include <boost/process/pipe.hpp>
  13. #include <boost/asio/read.hpp>
  14. #include <boost/asio/read_until.hpp>
  15. #include <boost/asio/write.hpp>
  16. #include <boost/asio/streambuf.hpp>
  17. using namespace std;
  18. namespace bp = boost::process;
  19. namespace asio = boost::asio;
  20. BOOST_AUTO_TEST_SUITE( async );
  21. BOOST_AUTO_TEST_CASE(plain_async, *boost::unit_test::timeout(5))
  22. {
  23. asio::io_context ios;
  24. bp::async_pipe pipe{ios};
  25. std::string st = "test-string\n";
  26. asio::streambuf buf;
  27. asio::async_write(pipe, asio::buffer(st), [](const boost::system::error_code &, std::size_t){});
  28. asio::async_read_until(pipe, buf, '\n', [](const boost::system::error_code &, std::size_t){});
  29. ios.run();
  30. std::string line;
  31. std::istream istr(&buf);
  32. BOOST_CHECK(std::getline(istr, line));
  33. line.resize(11);
  34. BOOST_CHECK_EQUAL(line, "test-string");
  35. }
  36. BOOST_AUTO_TEST_CASE(closed_transform)
  37. {
  38. asio::io_context ios;
  39. bp::async_pipe ap{ios};
  40. BOOST_CHECK(ap.is_open());
  41. bp::pipe p2 = static_cast<bp::pipe>(ap);
  42. BOOST_CHECK(p2.is_open());
  43. ap.close();
  44. BOOST_CHECK(!ap.is_open());
  45. bp::pipe p = static_cast<bp::pipe>(ap);
  46. BOOST_CHECK(!p.is_open());
  47. }
  48. BOOST_AUTO_TEST_CASE(multithreaded_async_pipe)
  49. {
  50. asio::io_context ioc;
  51. std::vector<std::thread> threads;
  52. for (int i = 0; i < std::thread::hardware_concurrency(); i++)
  53. {
  54. threads.emplace_back([&ioc]
  55. {
  56. std::vector<bp::async_pipe*> pipes;
  57. for (size_t i = 0; i < 100; i++)
  58. pipes.push_back(new bp::async_pipe(ioc));
  59. for (auto &p : pipes)
  60. delete p;
  61. });
  62. }
  63. for (auto &t : threads)
  64. t.join();
  65. }
  66. BOOST_AUTO_TEST_CASE(move_pipe)
  67. {
  68. asio::io_context ios;
  69. bp::async_pipe ap{ios};
  70. BOOST_TEST_CHECKPOINT("First move");
  71. bp::async_pipe ap2{std::move(ap)};
  72. BOOST_CHECK_EQUAL(ap.native_source(), ::boost::winapi::INVALID_HANDLE_VALUE_);
  73. BOOST_CHECK_EQUAL(ap.native_sink (), ::boost::winapi::INVALID_HANDLE_VALUE_);
  74. BOOST_TEST_CHECKPOINT("Second move");
  75. ap = std::move(ap2);
  76. {
  77. BOOST_TEST_CHECKPOINT("Third move, from closed");
  78. bp::async_pipe ap_inv{ios};
  79. ap_inv.close();
  80. ap = std::move(ap_inv);
  81. }
  82. {
  83. BOOST_TEST_CHECKPOINT("Fourth move, from closed");
  84. bp::async_pipe ap_inv{ios};
  85. ap_inv.close();
  86. const auto ap3 = std::move(ap_inv);
  87. }
  88. {
  89. //copy an a closed pipe
  90. BOOST_TEST_CHECKPOINT("Copy assign");
  91. BOOST_TEST_CHECKPOINT("Fourth move, from closed");
  92. bp::async_pipe ap_inv{ios};
  93. ap_inv.close();
  94. ap = ap_inv; //copy an invalid pipe
  95. }
  96. {
  97. //copy an a closed pipe
  98. BOOST_TEST_CHECKPOINT("Copy assign");
  99. BOOST_TEST_CHECKPOINT("Fourth move, from closed");
  100. bp::async_pipe ap_inv{ios};
  101. ap_inv.close();
  102. BOOST_TEST_CHECKPOINT("Copy construct");
  103. bp::async_pipe ap4{ap_inv};
  104. }
  105. }
  106. BOOST_AUTO_TEST_SUITE_END();