2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // Official repository: https://github.com/boostorg/beast
10 // Test that header file is self-contained.
11 #include <boost/beast/core/basic_stream.hpp>
13 #include "stream_tests.hpp"
15 #include <boost/beast/_experimental/unit_test/suite.hpp>
16 #include <boost/beast/core/flat_buffer.hpp>
17 #include <boost/beast/core/stream_traits.hpp>
18 #include <boost/beast/core/string.hpp>
19 #include <boost/beast/core/tcp_stream.hpp>
20 #include <boost/beast/http/message.hpp>
21 #include <boost/beast/http/empty_body.hpp>
22 #include <boost/beast/http/read.hpp>
23 #include <boost/beast/http/string_body.hpp>
24 #include <boost/beast/http/write.hpp>
25 #include <boost/asio/ip/tcp.hpp>
26 #include <boost/asio/spawn.hpp>
27 #include <boost/asio/strand.hpp>
28 #include <boost/asio/write.hpp>
29 #include <boost/optional.hpp>
37 template class basic_stream<
40 unlimited_rate_policy>;
42 template class basic_stream<
50 template<class Executor = net::io_context::executor_type>
54 // VFALCO These need to be atomic or something
70 state(Executor const& ex_)
76 std::shared_ptr<state> sp_;
79 test_executor(test_executor const&) = default;
80 test_executor& operator=(test_executor const&) = default;
83 test_executor(Executor const& ex)
84 : sp_(std::make_shared<state>(ex))
88 decltype(sp_->ex.context())
89 context() const noexcept
91 return sp_->ex.context();
101 operator->() noexcept
107 on_work_started() const noexcept
113 on_work_finished() const noexcept
117 template<class F, class A>
119 dispatch(F&& f, A const& a)
121 ++sp_->info_.dispatch;
124 std::forward<F>(f), a);
127 template<class F, class A>
129 post(F&& f, A const& a)
134 std::forward<F>(f), a);
137 template<class F, class A>
139 defer(F&& f, A const& a)
144 std::forward<F>(f), a);
151 net::ip::tcp::acceptor a;
152 net::ip::tcp::endpoint ep;
156 , ep(net::ip::make_address_v4("127.0.0.1"), 0)
158 a.open(ep.protocol());
160 net::socket_base::reuse_address(true));
162 a.listen(net::socket_base::max_listen_connections);
163 ep = a.local_endpoint();
165 [](error_code, net::ip::tcp::socket)
175 net::io_context ioc_;
176 net::ip::tcp::acceptor acceptor_;
177 net::ip::tcp::socket socket_;
181 fail(error_code const& ec, string_view what)
183 if(ec != net::error::operation_aborted)
184 log_ << what << ": " << ec.message() << "\n";
190 net::ip::tcp::endpoint ep,
198 boost::system::error_code ec;
200 acceptor_.open(ep.protocol(), ec);
207 acceptor_.set_option(
208 net::socket_base::reuse_address(true), ec);
211 fail(ec, "set_option");
215 acceptor_.bind(ep, ec);
223 net::socket_base::max_listen_connections, ec);
230 acceptor_.async_accept(socket_,
231 [this](error_code ec)
249 net::ip::tcp::endpoint
250 local_endpoint() const noexcept
252 return acceptor_.local_endpoint();
257 : public std::enable_shared_from_this<session>
260 net::ip::tcp::socket socket_;
265 net::ip::tcp::socket sock,
268 , socket_(std::move(sock))
277 net::socket_base::wait_read,
280 shared_from_this()));
284 net::const_buffer(s_.data(), s_.size()),
287 shared_from_this()));
292 on_read(error_code const&)
297 on_write(error_code const&, std::size_t)
303 on_accept(error_code const& ec)
305 if(! acceptor_.is_open())
310 std::make_shared<session>(
311 s_, std::move(socket_), log_)->run();
312 acceptor_.async_accept(socket_,
313 [this](error_code ec)
322 class basic_stream_test
323 : public beast::unit_test::suite
326 using tcp = net::ip::tcp;
327 using strand = net::io_context::strand;
328 using executor = net::io_context::executor_type;
330 //--------------------------------------------------------------------------
337 // net::io_context::executor_type
340 auto ex = ioc.get_executor();
341 basic_stream<tcp, executor> s1(ioc);
342 basic_stream<tcp, executor> s2(ex);
343 basic_stream<tcp, executor> s3(ioc, tcp::v4());
344 basic_stream<tcp, executor> s4(std::move(s1));
346 net::basic_stream_socket<tcp, executor>(ioc);
347 BEAST_EXPECT(s1.get_executor() == ex);
348 BEAST_EXPECT(s2.get_executor() == ex);
349 BEAST_EXPECT(s3.get_executor() == ex);
350 BEAST_EXPECT(s4.get_executor() == ex);
352 BEAST_EXPECT((! static_cast<
353 basic_stream<tcp, executor> const&>(
354 s2).socket().is_open()));
358 tcp, net::io_context::executor_type>>();
362 tcp, net::io_context::executor_type>>();
365 // net::io_context::strand
368 auto ex = strand{ioc};
369 basic_stream<tcp, strand> s1(ex);
370 basic_stream<tcp, strand> s2(ex, tcp::v4());
371 basic_stream<tcp, strand> s3(std::move(s1));
373 s2.socket() = net::basic_stream_socket<
376 BEAST_EXPECT(s1.get_executor() == ex);
377 BEAST_EXPECT(s2.get_executor() == ex);
378 BEAST_EXPECT(s3.get_executor() == ex);
381 BEAST_EXPECT((! static_cast<
382 basic_stream<tcp, strand> const&>(
383 s2).socket().is_open()));
388 tcp, net::io_context::strand>>();
392 tcp, net::io_context::strand>>();
395 // construction from existing socket
399 tcp::socket sock(ioc);
400 basic_stream<tcp, executor> stream(std::move(sock));
404 tcp::socket sock(ioc);
405 basic_stream<tcp, strand> stream(std::move(sock));
412 net::socket_base::keep_alive opt;
414 s.socket().open(tcp::v4());
415 s.socket().get_option(opt);
416 BEAST_EXPECT(! opt.value());
418 s.socket().set_option(opt);
420 BEAST_EXPECT(! opt.value());
427 net::io_context::executor_type,
428 simple_rate_policy> s(ioc);
433 net::io_context::executor_type,
434 simple_rate_policy> s(
435 simple_rate_policy{}, ioc);
440 net::io_context::executor_type,
441 unlimited_rate_policy> s(ioc);
446 net::io_context::executor_type,
447 unlimited_rate_policy> s(
448 unlimited_rate_policy{}, ioc);
454 boost::optional<error_code> ec_;
458 handler(error_code ec, std::size_t n)
464 handler(handler&& other)
466 , n_(boost::exchange(other.n_,
467 (std::numeric_limits<std::size_t>::max)()))
474 n_ == (std::numeric_limits<std::size_t>::max)());
478 operator()(error_code const& ec, std::size_t n)
480 BEAST_EXPECTS(ec == ec_, ec.message());
481 BEAST_EXPECT(n == n_);
482 n_ = (std::numeric_limits<std::size_t>::max)();
489 using stream_type = basic_stream<tcp,
490 net::io_context::executor_type>;
494 std::memset(buf, 0, sizeof(buf));
495 net::mutable_buffer mb(buf, sizeof(buf));
496 auto const ep = net::ip::tcp::endpoint(
497 net::ip::make_address("127.0.0.1"), 0);
503 stream_type s(ioc, tcp::v4());
504 BEAST_EXPECT(s.read_some(net::mutable_buffer{}) == 0);
505 BEAST_EXPECT(s.read_some(net::mutable_buffer{}, ec) == 0);
506 BEAST_EXPECTS(! ec, ec.message());
513 test_server srv("*", ep, log);
515 s.socket().connect(srv.local_endpoint());
517 s.async_read_some(mb, handler({}, 1));
523 // success, with timeout
524 test_server srv("*", ep, log);
526 s.socket().connect(srv.local_endpoint());
527 s.expires_after(std::chrono::seconds(30));
528 s.async_read_some(mb, handler({}, 1));
535 test_server srv("*", ep, log);
537 s.socket().connect(srv.local_endpoint());
540 net::mutable_buffer{}, handler({}, 0));
546 // empty buffer, timeout
547 test_server srv("*", ep, log);
549 s.socket().connect(srv.local_endpoint());
550 s.expires_after(std::chrono::seconds(0));
551 s.async_read_some(net::mutable_buffer{},
552 handler(error::timeout, 0));
559 test_server srv("", ep, log);
561 s.socket().connect(srv.local_endpoint());
562 s.expires_after(std::chrono::seconds(0));
563 s.async_read_some(mb, handler(error::timeout, 0));
570 test_server srv("", ep, log);
572 s.socket().connect(srv.local_endpoint());
573 s.expires_at(std::chrono::steady_clock::now());
574 s.async_read_some(mb, handler(error::timeout, 0));
581 test_server srv("", ep, log);
584 s.socket().connect(srv.local_endpoint());
585 s.expires_after(std::chrono::seconds(0));
586 s.async_read_some(mb,
587 [](error_code, std::size_t)
599 s.expires_after(std::chrono::milliseconds(50));
600 s.async_read_some(mb,
601 [](error_code, std::size_t)
604 std::this_thread::sleep_for(
605 std::chrono::milliseconds(100));
610 // abandoned operation
613 s.async_read_some(net::mutable_buffer{},
614 [](error_code, std::size_t)
624 using stream_type = basic_stream<tcp,
625 net::io_context::executor_type>;
629 std::memset(buf, 0, sizeof(buf));
630 net::const_buffer cb(buf, sizeof(buf));
631 auto const ep = net::ip::tcp::endpoint(
632 net::ip::make_address("127.0.0.1"), 0);
638 stream_type s(ioc, tcp::v4());
639 BEAST_EXPECT(s.write_some(net::const_buffer{}) == 0);
640 BEAST_EXPECT(s.write_some(net::const_buffer{}, ec) == 0);
641 BEAST_EXPECTS(! ec, ec.message());
648 test_server srv("*", ep, log);
650 s.socket().connect(srv.local_endpoint());
652 s.async_write_some(cb, handler({}, 4));
658 // success, with timeout
659 test_server srv("*", ep, log);
661 s.socket().connect(srv.local_endpoint());
662 s.expires_after(std::chrono::seconds(30));
663 s.async_write_some(cb, handler({}, 4));
670 test_server srv("*", ep, log);
672 s.socket().connect(srv.local_endpoint());
675 net::const_buffer{}, handler({}, 0));
681 // empty buffer, timeout
682 test_server srv("*", ep, log);
684 s.socket().connect(srv.local_endpoint());
685 s.expires_after(std::chrono::seconds(0));
686 s.async_write_some(net::const_buffer{},
687 handler(error::timeout, 0));
692 // abandoned operation
695 s.async_write_some(cb,
696 [](error_code, std::size_t)
706 using stream_type = basic_stream<tcp,
707 net::io_context::executor_type>;
714 tcp::endpoint const*;
716 // VFALCO This is here because asio mistakenly requires it
717 using const_iterator =
718 tcp::endpoint const*;
720 iterator begin() const noexcept
725 // VFALCO need to use const_iterator to silence
726 // warning about unused types
727 const_iterator end() const noexcept
733 class connect_handler
736 boost::optional<error_code> expected_ = {};
745 : expected_(error_code{})
750 connect_handler(error_code expected)
751 : expected_(expected)
756 connect_handler(boost::none_t)
760 connect_handler(connect_handler&& other)
761 : pass_(boost::exchange(other.pass_, true))
762 , expected_(other.expected_)
766 void operator()(error_code ec)
771 ec == expected_, ec.message());
779 range_handler() = default;
781 range_handler(range_handler&& other)
782 : pass(boost::exchange(other.pass, true))
791 void operator()(error_code ec, tcp::endpoint)
794 BEAST_EXPECTS(! ec, ec.message());
798 struct iterator_handler
802 iterator_handler() = default;
804 iterator_handler(iterator_handler&& other)
805 : pass(boost::exchange(other.pass, true))
814 void operator()(error_code ec, tcp::endpoint const*)
817 BEAST_EXPECTS(! ec, ec.message());
821 struct connect_condition
823 bool operator()(error_code, tcp::endpoint) const
831 connect_condition cond;
842 BEAST_EXPECTS(! ec, ec.message());
855 BEAST_EXPECTS(! ec, ec.message());
865 s.connect(r, cond, ec);
866 BEAST_EXPECTS(! ec, ec.message());
874 s.connect(r.begin(), r.end());
876 s.connect(r.begin(), r.end(), ec);
877 BEAST_EXPECTS(! ec, ec.message());
885 s.connect(r.begin(), r.end(), cond);
887 s.connect(r.begin(), r.end(), cond, ec);
888 BEAST_EXPECTS(! ec, ec.message());
891 // async_connect (member)
897 s.async_connect(a.ep, connect_handler{});
901 s.expires_after(std::chrono::seconds(30));
902 s.async_connect(a.ep, connect_handler{});
914 s.async_connect(r, range_handler{});
918 s.expires_after(std::chrono::seconds(30));
919 s.async_connect(r, range_handler{});
929 s.async_connect(r, cond, range_handler{});
933 s.expires_after(std::chrono::seconds(30));
934 s.async_connect(r, cond, range_handler{});
944 s.async_connect(r.begin(), r.end(),
949 s.expires_after(std::chrono::seconds(30));
950 s.async_connect(r.begin(), r.end(),
961 s.async_connect(r.begin(), r.end(), cond,
966 s.expires_after(std::chrono::seconds(30));
967 s.async_connect(r.begin(), r.end(), cond,
975 BEAST_EXPECT(static_cast<std::future<
976 tcp::endpoint>(*)(stream_type&,
977 std::array<tcp::endpoint, 2> const&,
978 net::use_future_t<>&&)>(
979 &beast::async_connect));
981 BEAST_EXPECT(static_cast<std::future<
982 tcp::endpoint>(*)(stream_type&,
983 std::array<tcp::endpoint, 2> const&,
984 connect_condition const&,
985 net::use_future_t<>&&)>(
986 &beast::async_connect));
988 BEAST_EXPECT(static_cast<std::future<
989 tcp::endpoint const*>(*)(stream_type&,
990 tcp::endpoint const*,
991 tcp::endpoint const*,
992 net::use_future_t<>&&)>(
993 &beast::async_connect));
995 BEAST_EXPECT(static_cast<std::future<
996 tcp::endpoint const*>(*)(stream_type&,
997 tcp::endpoint const*,
998 tcp::endpoint const*,
999 connect_condition const&,
1000 net::use_future_t<>&&)>(
1001 &beast::async_connect));
1005 BEAST_EXPECT(static_cast<
1006 tcp::endpoint(*)(stream_type&,
1007 std::array<tcp::endpoint, 2> const&,
1008 net::yield_context&&)>(
1009 &beast::async_connect));
1011 BEAST_EXPECT(static_cast<
1012 tcp::endpoint(*)(stream_type&,
1013 std::array<tcp::endpoint, 2> const&,
1014 connect_condition const&,
1015 net::yield_context&&)>(
1016 &beast::async_connect));
1018 BEAST_EXPECT(static_cast<
1019 tcp::endpoint const*(*)(stream_type&,
1020 tcp::endpoint const*,
1021 tcp::endpoint const*,
1022 net::yield_context&&)>(
1023 &beast::async_connect));
1025 BEAST_EXPECT(static_cast<
1026 tcp::endpoint const*(*)(stream_type&,
1027 tcp::endpoint const*,
1028 tcp::endpoint const*,
1029 connect_condition const&,
1030 net::yield_context&&)>(
1031 &beast::async_connect));
1035 // async_connect timeout
1040 // Requires timeout happen before ECONNREFUSED
1042 auto const ep = net::ip::tcp::endpoint(
1044 // This address _should_ be unconnectible
1045 net::ip::make_address("72.5.65.111"), 1);
1047 // On Travis ECONNREFUSED happens before the timeout
1048 net::ip::make_address("127.0.0.1"), 1);
1050 s.expires_after(std::chrono::seconds(0));
1051 s.async_connect(ep, connect_handler{error::timeout});
1052 ioc.run_for(std::chrono::seconds(1));
1060 auto const ep = net::ip::tcp::endpoint(
1061 net::ip::make_address("127.0.0.1"), 1);
1062 s.expires_after(std::chrono::seconds(0));
1063 s.async_connect(ep, connect_handler{boost::none});
1073 s.expires_after(std::chrono::milliseconds(50));
1074 s.async_connect(a.ep, connect_handler{});
1075 std::this_thread::sleep_for(
1076 std::chrono::milliseconds(100));
1081 // abandoned operation
1084 net::ip::tcp::endpoint ep(
1085 net::ip::make_address_v4("127.0.0.1"), 1);
1097 using stream_type = basic_stream<tcp,
1098 net::io_context::executor_type>;
1103 boost::optional<error_code> expected_ = {};
1108 BEAST_EXPECT(pass_);
1112 : expected_(error_code{})
1117 handler(error_code expected)
1118 : expected_(expected)
1123 handler(boost::none_t)
1127 handler(handler&& other)
1128 : pass_(boost::exchange(other.pass_, true))
1129 , expected_(other.expected_)
1133 void operator()(error_code ec, std::size_t)
1138 ec == expected_, ec.message());
1142 auto const ep = net::ip::tcp::endpoint(
1143 net::ip::make_address("127.0.0.1"), 0);
1146 net::io_context ioc;
1147 auto mb = net::buffer(buf);
1148 std::memset(buf, 0, sizeof(buf));
1153 test_server srv("", ep, log);
1155 s.connect(srv.local_endpoint());
1157 s.socket().async_read_some(mb, handler(
1158 net::error::operation_aborted));
1167 test_server srv("", ep, log);
1169 s.connect(srv.local_endpoint());
1171 s.socket().async_read_some(mb,
1172 handler(boost::none));
1181 test_server srv("", ep, log);
1184 s.connect(srv.local_endpoint());
1186 s.socket().async_read_some(mb,
1187 handler(boost::none));
1193 // customization points
1197 beast::close_socket(s);
1203 teardown(role_type::client, s, ec);
1208 async_teardown(role_type::server, s,
1215 //--------------------------------------------------------------------------
1217 http::response<http::string_body>
1218 make_response(http::request<http::empty_body>)
1222 void process_http_1 (tcp_stream& stream, net::yield_context yield)
1225 http::request<http::empty_body> req;
1227 // Read the request, with a 15 second timeout
1228 stream.expires_after(std::chrono::seconds(15));
1229 http::async_read(stream, buffer, req, yield);
1231 // Calculate the response
1232 http::response<http::string_body> res = make_response(req);
1234 // Send the response, with a 30 second timeout.
1235 stream.expires_after (std::chrono::seconds(30));
1236 http::async_write (stream, res, yield);
1239 void process_http_2 (tcp_stream& stream, net::yield_context yield)
1242 http::request<http::empty_body> req;
1244 // Require that the read and write combined take no longer than 30 seconds
1245 stream.expires_after(std::chrono::seconds(30));
1247 http::async_read(stream, buffer, req, yield);
1249 http::response<http::string_body> res = make_response(req);
1250 http::async_write (stream, res, yield);
1256 BEAST_EXPECT(&basic_stream_test::process_http_1);
1257 BEAST_EXPECT(&basic_stream_test::process_http_2);
1260 //--------------------------------------------------------------------------
1265 net::io_context ioc;
1267 // the timer needlessly used polymorphic executor
1270 net::io_context::executor_type>{ioc};
1272 // make sure strands work
1276 net::io_context::executor_type>>{
1277 net::make_strand(ioc)};
1279 // address the problem in the issue
1281 net::basic_stream_socket<
1284 net::io_context::executor_type>
1285 > sock(net::make_strand(ioc));
1289 net::io_context::executor_type>,
1290 unlimited_rate_policy> stream(std::move(sock));
1291 BOOST_STATIC_ASSERT(
1292 std::is_convertible<
1293 decltype(sock)::executor_type,
1294 decltype(stream)::executor_type>::value);
1298 //--------------------------------------------------------------------------
1303 testSpecialMembers();
1313 BEAST_DEFINE_TESTSUITE(beast,core,basic_stream);