diff --git a/CHANGELOG.md b/CHANGELOG.md index d9d40113..b25d3c31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ Version XXX: +* Test websocket with use_awaitable +* Test http write with use_awaitable +* Test http read with use_awaitable +* Fix use buffered_read_stream with use_awaitable +* Implement is_completion_token_for trait +* Test use_awaitable with basic_stream * Fix async_detect_ssl with use_awaitable * Add clang coroutines-ts to circleci config diff --git a/include/boost/beast/core/detail/is_invocable.hpp b/include/boost/beast/core/detail/is_invocable.hpp index 65f1b6c8..56d95a23 100644 --- a/include/boost/beast/core/detail/is_invocable.hpp +++ b/include/boost/beast/core/detail/is_invocable.hpp @@ -10,6 +10,8 @@ #ifndef BOOST_BEAST_DETAIL_IS_INVOCABLE_HPP #define BOOST_BEAST_DETAIL_IS_INVOCABLE_HPP +#include +#include #include #include @@ -51,6 +53,26 @@ struct is_invocable }; /** @} */ +template +struct is_completion_token_for : std::false_type +{ +}; + +struct any_initiation +{ + template + void operator()(AnyArgs&&...); +}; + +template +struct is_completion_token_for< + CompletionToken, R(Args...), boost::void_t( + any_initiation(), std::declval()) + )>> : std::true_type +{ +}; + } // detail } // beast } // boost diff --git a/include/boost/beast/core/impl/buffered_read_stream.hpp b/include/boost/beast/core/impl/buffered_read_stream.hpp index cea0dcb9..21e23f71 100644 --- a/include/boost/beast/core/impl/buffered_read_stream.hpp +++ b/include/boost/beast/core/impl/buffered_read_stream.hpp @@ -110,7 +110,7 @@ struct run_read_op operator()( ReadHandler&& h, buffered_read_stream* s, - Buffers const& b) + Buffers const* b) { // If you get an error on the following line it means // that your handler does not meet the documented type @@ -124,7 +124,7 @@ struct run_read_op read_op< Buffers, typename std::decay::type>( - std::forward(h), *s, b); + std::forward(h), *s, *b); } }; @@ -153,7 +153,7 @@ async_write_some( static_assert(net::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence type requirements not met"); - static_assert(detail::is_invocable::value, "WriteHandler type requirements not met"); return next_layer_.async_write_some(buffers, @@ -233,7 +233,7 @@ async_read_some( typename ops::run_read_op{}, handler, this, - buffers); + &buffers); } } // beast diff --git a/test/beast/core/basic_stream.cpp b/test/beast/core/basic_stream.cpp index 4b64c79b..4cbe1b15 100644 --- a/test/beast/core/basic_stream.cpp +++ b/test/beast/core/basic_stream.cpp @@ -30,6 +30,13 @@ #include #include +#if BOOST_ASIO_HAS_CO_AWAIT +#include +#include +#include +#endif + + namespace boost { namespace beast { @@ -258,7 +265,7 @@ private: { string_view s_; net::ip::tcp::socket socket_; - + public: session( string_view s, @@ -1297,6 +1304,52 @@ public: //-------------------------------------------------------------------------- +#if BOOST_ASIO_HAS_CO_AWAIT + void testAwaitableCompilation( + basic_stream& stream, + net::mutable_buffer outbuf, + net::const_buffer inbuf, + net::ip::tcp::resolver::results_type resolve_results) + { + static_assert(std::is_same_v< + net::awaitable, decltype( + stream.async_read_some(outbuf, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + stream.async_write_some(inbuf, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + stream.async_connect( + resolve_results.begin(), + resolve_results.end(), + net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + stream.async_connect( + resolve_results, + net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + stream.async_connect( + resolve_results.begin()->endpoint(), + net::use_awaitable))>); + + auto comparison_function = [](error_code&, net::ip::tcp::endpoint) { return true; }; + + static_assert(std::is_same_v< + net::awaitable, decltype( + stream.async_connect( + resolve_results.begin(), + resolve_results.end(), + comparison_function, + net::use_awaitable))>); + } +#endif + void run() { @@ -1307,6 +1360,11 @@ public: testMembers(); testJavadocs(); testIssue1589(); + +#if BOOST_ASIO_HAS_CO_AWAIT + // test for compilation success only + boost::ignore_unused(&basic_stream_test::testAwaitableCompilation); +#endif } }; diff --git a/test/beast/core/buffered_read_stream.cpp b/test/beast/core/buffered_read_stream.cpp index c24abf56..daf76bbf 100644 --- a/test/beast/core/buffered_read_stream.cpp +++ b/test/beast/core/buffered_read_stream.cpp @@ -21,6 +21,9 @@ #include #include #include +#if BOOST_ASIO_HAS_CO_AWAIT +#include +#endif namespace boost { namespace beast { @@ -211,6 +214,22 @@ public: } }; +#if BOOST_ASIO_HAS_CO_AWAIT + void testAwaitableCompiles( + buffered_read_stream& stream, + net::mutable_buffer rxbuf, + net::const_buffer txbuf) + { + static_assert(std::is_same_v< + net::awaitable, decltype( + stream.async_read_some(rxbuf, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + stream.async_write_some(txbuf, net::use_awaitable))>); + } +#endif + void run() override { testSpecialMembers(); @@ -221,6 +240,10 @@ public: }); testAsyncLoop(); + +#if BOOST_ASIO_HAS_CO_AWAIT + boost::ignore_unused(&buffered_read_stream_test::testAwaitableCompiles); +#endif } }; diff --git a/test/beast/core/flat_stream.cpp b/test/beast/core/flat_stream.cpp index d2ce65fa..f6b18ecb 100644 --- a/test/beast/core/flat_stream.cpp +++ b/test/beast/core/flat_stream.cpp @@ -17,6 +17,9 @@ #include #include #include +#if BOOST_ASIO_HAS_CO_AWAIT +#include +#endif namespace boost { namespace beast { @@ -208,11 +211,30 @@ public: check({1,2,3,4}, 3, 3, true); } +#if BOOST_ASIO_HAS_CO_AWAIT + void testAwaitableCompiles( + flat_stream& stream, + net::mutable_buffer rxbuf, + net::const_buffer txbuf) + { + static_assert(std::is_same_v< + net::awaitable, decltype( + stream.async_read_some(rxbuf, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + stream.async_write_some(txbuf, net::use_awaitable))>); + } +#endif + void run() override { testMembers(); testSplit(); +#if BOOST_ASIO_HAS_CO_AWAIT + boost::ignore_unused(&flat_stream_test::testAwaitableCompiles); +#endif } }; diff --git a/test/beast/http/read.cpp b/test/beast/http/read.cpp index 8446894b..04e862a1 100644 --- a/test/beast/http/read.cpp +++ b/test/beast/http/read.cpp @@ -25,6 +25,9 @@ #include #include #include +#if BOOST_ASIO_HAS_CO_AWAIT +#include +#endif namespace boost { namespace beast { @@ -529,6 +532,49 @@ public: } } +#if BOOST_ASIO_HAS_CO_AWAIT + void testAwaitableCompiles( + test::stream& stream, + flat_buffer& dynbuf, + parser& request_parser, + request& request, + parser& response_parser, + response& response) + { + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_read(stream, dynbuf, request, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_read(stream, dynbuf, request_parser, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_read(stream, dynbuf, response, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_read(stream, dynbuf, response_parser, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_read_some(stream, dynbuf, request_parser, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_read_some(stream, dynbuf, response_parser, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_read_header(stream, dynbuf, request_parser, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_read_header(stream, dynbuf, response_parser, net::use_awaitable))>); + } +#endif + void run() override { @@ -552,6 +598,9 @@ public: testRegression430(); testReadGrind(); testAsioHandlerInvoke(); +#if BOOST_ASIO_HAS_CO_AWAIT + boost::ignore_unused(&read_test::testAwaitableCompiles); +#endif } }; diff --git a/test/beast/http/write.cpp b/test/beast/http/write.cpp index f6cfadea..2a4ac999 100644 --- a/test/beast/http/write.cpp +++ b/test/beast/http/write.cpp @@ -26,6 +26,9 @@ #include #include #include +#if BOOST_ASIO_HAS_CO_AWAIT +#include +#endif namespace boost { namespace beast { @@ -994,6 +997,59 @@ public: } } +#if BOOST_ASIO_HAS_CO_AWAIT + void testAwaitableCompiles( + test::stream& stream, + serializer& request_serializer, + request& req, + request const& creq, + serializer& response_serializer, + response& resp, + response const& cresp) + { + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_write(stream, request_serializer, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_write(stream, response_serializer, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_write(stream, req, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_write(stream, creq, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_write(stream, resp, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_write(stream, cresp, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_write_some(stream, request_serializer, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_write_some(stream, response_serializer, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_write_header(stream, request_serializer, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + http::async_write_header(stream, response_serializer, net::use_awaitable))>); + } +#endif + + void run() override { @@ -1017,6 +1073,9 @@ public: }); testAsioHandlerInvoke(); testBodyWriters(); +#if BOOST_ASIO_HAS_CO_AWAIT + boost::ignore_unused(&write_test::testAwaitableCompiles); +#endif } }; diff --git a/test/beast/websocket/accept.cpp b/test/beast/websocket/accept.cpp index 9c1e58bf..4b4ae751 100644 --- a/test/beast/websocket/accept.cpp +++ b/test/beast/websocket/accept.cpp @@ -14,7 +14,9 @@ #include #include #include "test.hpp" - +#if BOOST_ASIO_HAS_CO_AWAIT +#include +#endif namespace boost { namespace beast { namespace websocket { @@ -810,6 +812,27 @@ public: } } +#if BOOST_ASIO_HAS_CO_AWAIT + void testAwaitableCompiles( + stream& s, + http::request& req, + net::mutable_buffer buf + ) + { + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_accept(net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_accept(req, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_accept(buf, net::use_awaitable))>); + } +#endif + void run() override { @@ -820,6 +843,9 @@ public: testInvalidInputs(); testEndOfStream(); testAsync(); +#if BOOST_ASIO_HAS_CO_AWAIT + boost::ignore_unused(&accept_test::testAwaitableCompiles); +#endif } }; diff --git a/test/beast/websocket/close.cpp b/test/beast/websocket/close.cpp index 1b891b33..f5db13f7 100644 --- a/test/beast/websocket/close.cpp +++ b/test/beast/websocket/close.cpp @@ -16,6 +16,9 @@ #include #include +#if BOOST_ASIO_HAS_CO_AWAIT +#include +#endif namespace boost { namespace beast { @@ -735,6 +738,15 @@ public: } }; +#if BOOST_ASIO_HAS_CO_AWAIT + void testAwaitableCompiles(stream& s, close_reason cr ) + { + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_close(cr, net::use_awaitable))>); + } +#endif + void run() override { @@ -742,6 +754,9 @@ public: testTimeout(); testSuspend(); testMoveOnly(); +#if BOOST_ASIO_HAS_CO_AWAIT + boost::ignore_unused(&close_test::testAwaitableCompiles); +#endif } }; diff --git a/test/beast/websocket/handshake.cpp b/test/beast/websocket/handshake.cpp index e5ea4004..5723415e 100644 --- a/test/beast/websocket/handshake.cpp +++ b/test/beast/websocket/handshake.cpp @@ -18,6 +18,9 @@ #include #include #include +#if BOOST_ASIO_HAS_CO_AWAIT +#include +#endif namespace boost { namespace beast { @@ -704,6 +707,23 @@ public: } } +#if BOOST_ASIO_HAS_CO_AWAIT + void testAwaitableCompiles( + stream& s, + std::string host, + std::string port, + response_type& resp) + { + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_handshake(host, port, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_handshake(resp, host, port, net::use_awaitable))>); + } +#endif + void run() override { @@ -714,6 +734,9 @@ public: testMoveOnly(); testAsync(); testIssue1460(); +#if BOOST_ASIO_HAS_CO_AWAIT + boost::ignore_unused(&handshake_test::testAwaitableCompiles); +#endif } }; diff --git a/test/beast/websocket/ping.cpp b/test/beast/websocket/ping.cpp index 1810927b..2647ae39 100644 --- a/test/beast/websocket/ping.cpp +++ b/test/beast/websocket/ping.cpp @@ -18,6 +18,10 @@ #include #include +#if BOOST_ASIO_HAS_CO_AWAIT +#include +#endif + namespace boost { namespace beast { namespace websocket { @@ -483,12 +487,30 @@ public: } }; +#if BOOST_ASIO_HAS_CO_AWAIT + void testAwaitableCompiles( + stream& s, + ping_data& pdat) + { + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_ping(pdat, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_pong(pdat, net::use_awaitable))>); + } +#endif + void run() override { testPing(); testSuspend(); testMoveOnly(); +#if BOOST_ASIO_HAS_CO_AWAIT + boost::ignore_unused(&ping_test::testAwaitableCompiles); +#endif } }; diff --git a/test/beast/websocket/read2.cpp b/test/beast/websocket/read2.cpp index 0f211fcf..90a79149 100644 --- a/test/beast/websocket/read2.cpp +++ b/test/beast/websocket/read2.cpp @@ -14,6 +14,10 @@ #include +#if BOOST_ASIO_HAS_CO_AWAIT +#include +#endif + #include #if BOOST_WORKAROUND(BOOST_GCC, < 80200) #define BOOST_BEAST_SYMBOL_HIDDEN __attribute__ ((visibility("hidden"))) @@ -673,10 +677,34 @@ public: } } +#if BOOST_ASIO_HAS_CO_AWAIT + void testAwaitableCompiles( + stream& s, + flat_buffer& dynbuf, + net::mutable_buffer buf, + std::size_t limit) + { + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_read(dynbuf, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_read_some(buf, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_read_some(dynbuf, limit, net::use_awaitable))>); + } +#endif + void run() override { testRead(); +#if BOOST_ASIO_HAS_CO_AWAIT + boost::ignore_unused(&read2_test::testAwaitableCompiles); +#endif } }; diff --git a/test/beast/websocket/write.cpp b/test/beast/websocket/write.cpp index c9b0b7ff..5b7618f0 100644 --- a/test/beast/websocket/write.cpp +++ b/test/beast/websocket/write.cpp @@ -13,6 +13,10 @@ #include #include +#if BOOST_ASIO_HAS_CO_AWAIT +#include +#endif + #include "test.hpp" namespace boost { @@ -716,6 +720,22 @@ public: BEAST_EXPECT(n1 < n0 + s.size()); } +#if BOOST_ASIO_HAS_CO_AWAIT + void testAwaitableCompiles( + stream& s, + net::mutable_buffer buf, + bool fin) + { + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_write(buf, net::use_awaitable))>); + + static_assert(std::is_same_v< + net::awaitable, decltype( + s.async_write_some(fin, buf, net::use_awaitable))>); + } +#endif + void run() override { @@ -726,6 +746,9 @@ public: testMoveOnly(); testIssue300(); testIssue1666(); +#if BOOST_ASIO_HAS_CO_AWAIT + boost::ignore_unused(&write_test::testAwaitableCompiles); +#endif } };