]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/test/beast/core/basic_stream.cpp
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
);