summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/beast/test/beast/websocket/test.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/beast/test/beast/websocket/test.hpp')
-rw-r--r--src/boost/libs/beast/test/beast/websocket/test.hpp1590
1 files changed, 1590 insertions, 0 deletions
diff --git a/src/boost/libs/beast/test/beast/websocket/test.hpp b/src/boost/libs/beast/test/beast/websocket/test.hpp
new file mode 100644
index 00000000..b4c90d2b
--- /dev/null
+++ b/src/boost/libs/beast/test/beast/websocket/test.hpp
@@ -0,0 +1,1590 @@
+//
+// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BEAST_TEST_WEBSOCKET_TEST_HPP
+#define BEAST_TEST_WEBSOCKET_TEST_HPP
+
+#include <boost/beast/core/bind_handler.hpp>
+#include <boost/beast/core/buffer_traits.hpp>
+#include <boost/beast/core/buffers_to_string.hpp>
+#include <boost/beast/core/ostream.hpp>
+#include <boost/beast/core/multi_buffer.hpp>
+#include <boost/beast/websocket/stream.hpp>
+#include <boost/beast/_experimental/test/stream.hpp>
+#include <boost/beast/test/yield_to.hpp>
+#include <boost/beast/_experimental/unit_test/suite.hpp>
+#include <boost/asio/executor_work_guard.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/optional.hpp>
+#include <cstdlib>
+#include <memory>
+#include <random>
+#include <string>
+
+namespace boost {
+namespace beast {
+namespace websocket {
+
+class websocket_test_suite
+ : public beast::unit_test::suite
+ , public test::enable_yield_to
+{
+public:
+ template<bool deflateSupported>
+ using ws_type_t =
+ websocket::stream<test::stream&, deflateSupported>;
+
+ using ws_type =
+ websocket::stream<test::stream&>;
+
+ struct move_only_handler
+ {
+ move_only_handler() = default;
+ move_only_handler(move_only_handler&&) = default;
+ move_only_handler(move_only_handler const&) = delete;
+
+ template<class... Args>
+ void
+ operator()(Args&&...) const
+ {
+ }
+ };
+
+ enum class kind
+ {
+ sync,
+ async,
+ async_client
+ };
+
+ class echo_server
+ {
+ enum
+ {
+ buf_size = 20000
+ };
+
+ std::ostream& log_;
+ net::io_context ioc_;
+ net::executor_work_guard<
+ net::io_context::executor_type> work_;
+ static_buffer<buf_size> buffer_;
+ test::stream ts_;
+ std::thread t_;
+ websocket::stream<test::stream&> ws_;
+ bool close_ = false;
+
+ public:
+ explicit
+ echo_server(
+ std::ostream& log,
+ kind k = kind::sync)
+ : log_(log)
+ , work_(ioc_.get_executor())
+ , ts_(ioc_)
+ , ws_(ts_)
+ {
+ permessage_deflate pmd;
+ pmd.server_enable = true;
+ pmd.server_max_window_bits = 9;
+ pmd.compLevel = 1;
+ ws_.set_option(pmd);
+
+ switch(k)
+ {
+ case kind::sync:
+ t_ = std::thread{[&]{ do_sync(); }};
+ break;
+
+ case kind::async:
+ t_ = std::thread{[&]{ ioc_.run(); }};
+ do_accept();
+ break;
+
+ case kind::async_client:
+ t_ = std::thread{[&]{ ioc_.run(); }};
+ break;
+ }
+ }
+
+ ~echo_server()
+ {
+ work_.reset();
+ t_.join();
+ }
+
+ test::stream&
+ stream()
+ {
+ return ts_;
+ }
+
+ void
+ async_handshake()
+ {
+ ws_.async_handshake("localhost", "/",
+ bind_front_handler(
+ &echo_server::on_handshake,
+ this));
+ }
+
+ void
+ async_close()
+ {
+ net::post(ioc_,
+ [&]
+ {
+ if(ws_.is_open())
+ {
+ ws_.async_close({},
+ bind_front_handler(
+ &echo_server::on_close,
+ this));
+ }
+ else
+ {
+ close_ = true;
+ }
+ });
+ }
+
+ private:
+ void
+ do_sync()
+ {
+ try
+ {
+ ws_.accept();
+ for(;;)
+ {
+ ws_.read(buffer_);
+ ws_.text(ws_.got_text());
+ ws_.write(buffer_.data());
+ buffer_.consume(buffer_.size());
+ }
+ }
+ catch(system_error const& se)
+ {
+ boost::ignore_unused(se);
+ #if 0
+ if( se.code() != error::closed &&
+ se.code() != error::failed &&
+ se.code() != net::error::eof)
+ log_ << "echo_server: " << se.code().message() << std::endl;
+ #endif
+ }
+ catch(std::exception const& e)
+ {
+ log_ << "echo_server: " << e.what() << std::endl;
+ }
+ }
+
+ void
+ do_accept()
+ {
+ ws_.async_accept(
+ bind_front_handler(
+ &echo_server::on_accept,
+ this));
+ }
+
+ void
+ on_handshake(error_code ec)
+ {
+ if(ec)
+ return fail(ec);
+
+ do_read();
+ }
+
+ void
+ on_accept(error_code ec)
+ {
+ if(ec)
+ return fail(ec);
+
+ if(close_)
+ {
+ return ws_.async_close({},
+ bind_front_handler(
+ &echo_server::on_close,
+ this));
+ }
+
+ do_read();
+ }
+
+ void
+ do_read()
+ {
+ ws_.async_read(buffer_,
+ beast::bind_front_handler(
+ &echo_server::on_read,
+ this));
+ }
+
+ void
+ on_read(error_code ec, std::size_t)
+ {
+ if(ec)
+ return fail(ec);
+ ws_.text(ws_.got_text());
+ ws_.async_write(buffer_.data(),
+ beast::bind_front_handler(
+ &echo_server::on_write,
+ this));
+ }
+
+ void
+ on_write(error_code ec, std::size_t)
+ {
+ if(ec)
+ return fail(ec);
+ buffer_.consume(buffer_.size());
+ do_read();
+ }
+
+ void
+ on_close(error_code ec)
+ {
+ if(ec)
+ return fail(ec);
+ }
+
+ void
+ fail(error_code ec)
+ {
+ boost::ignore_unused(ec);
+ #if 0
+ if( ec != error::closed &&
+ ec != error::failed &&
+ ec != net::error::eof)
+ log_ <<
+ "echo_server_async: " <<
+ ec.message() <<
+ std::endl;
+ #endif
+ }
+ };
+
+ template<class Test>
+ void
+ doFailLoop(
+ Test const& f, std::size_t limit = 200)
+ {
+ std::size_t n;
+ for(n = 0; n < limit; ++n)
+ {
+ test::fail_count fc{n};
+ try
+ {
+ f(fc);
+ break;
+ }
+ catch(system_error const& se)
+ {
+ BEAST_EXPECTS(
+ se.code() == test::error::test_failure,
+ se.code().message());
+ }
+ }
+ BEAST_EXPECT(n < limit);
+ }
+
+ template<class Test>
+ void
+ doStreamLoop(Test const& f)
+ {
+ // This number has to be high for the
+ // test that writes the large buffer.
+ static std::size_t constexpr limit = 200;
+
+ doFailLoop(
+ [&](test::fail_count& fc)
+ {
+ test::stream ts{ioc_, fc};
+ f(ts);
+ ts.close();
+ }
+ , limit);
+ }
+
+ template<bool deflateSupported = true, class Test>
+ void
+ doTest(
+ permessage_deflate const& pmd,
+ Test const& f)
+ {
+ // This number has to be high for the
+ // test that writes the large buffer.
+ static std::size_t constexpr limit = 200;
+
+ for(int i = 0; i < 2; ++i)
+ {
+ std::size_t n;
+ for(n = 0; n < limit; ++n)
+ {
+ test::fail_count fc{n};
+ test::stream ts{ioc_, fc};
+ ws_type_t<deflateSupported> ws{ts};
+ ws.set_option(pmd);
+
+ echo_server es{log, i==1 ?
+ kind::async : kind::sync};
+ error_code ec;
+ ws.next_layer().connect(es.stream());
+ ws.handshake("localhost", "/", ec);
+ if(ec)
+ {
+ ts.close();
+ if( ! BEAST_EXPECTS(
+ ec == test::error::test_failure,
+ ec.message()))
+ BOOST_THROW_EXCEPTION(system_error{ec});
+ continue;
+ }
+ try
+ {
+ f(ws);
+ ts.close();
+ break;
+ }
+ catch(system_error const& se)
+ {
+ BEAST_EXPECTS(
+ se.code() == test::error::test_failure,
+ se.code().message());
+ }
+ catch(std::exception const& e)
+ {
+ fail(e.what(), __FILE__, __LINE__);
+ }
+ ts.close();
+ continue;
+ }
+ BEAST_EXPECT(n < limit);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
+ net::const_buffer cbuf(std::initializer_list<std::uint8_t> bytes)
+ {
+ return {bytes.begin(), bytes.size()};
+ }
+
+ template<std::size_t N>
+ static
+ net::const_buffer
+ sbuf(const char (&s)[N])
+ {
+ return net::const_buffer(&s[0], N-1);
+ }
+
+ template<
+ class DynamicBuffer,
+ class ConstBufferSequence>
+ void
+ put(
+ DynamicBuffer& buffer,
+ ConstBufferSequence const& buffers)
+ {
+ buffer.commit(net::buffer_copy(
+ buffer.prepare(buffer_bytes(buffers)),
+ buffers));
+ }
+
+ template<class Pred>
+ bool
+ run_until(net::io_context& ioc,
+ std::size_t limit, Pred&& pred)
+ {
+ for(std::size_t i = 0; i < limit; ++i)
+ {
+ if(pred())
+ return true;
+ ioc.run_one();
+ }
+ return false;
+ }
+
+ template<class Pred>
+ bool
+ run_until(
+ net::io_context& ioc, Pred&& pred)
+ {
+ return run_until(ioc, 100, pred);
+ }
+
+ inline
+ std::string const&
+ random_string()
+ {
+ static std::string const s = []
+ {
+ std::size_t constexpr N = 16384;
+ std::mt19937 mt{1};
+ std::string tmp;
+ tmp.reserve(N);
+ for(std::size_t i = 0; i < N; ++ i)
+ tmp.push_back(static_cast<char>(
+ std::uniform_int_distribution<
+ unsigned>{0, 255}(mt)));
+ return tmp;
+ }();
+ return s;
+ }
+
+ //--------------------------------------------------------------------------
+
+ struct SyncClient
+ {
+ template<class NextLayer, bool deflateSupported>
+ void
+ accept(
+ stream<NextLayer, deflateSupported>& ws) const
+ {
+ ws.accept();
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers>
+ typename std::enable_if<
+ ! http::detail::is_header<Buffers>::value>::type
+ accept(stream<NextLayer, deflateSupported>& ws,
+ Buffers const& buffers) const
+ {
+ ws.accept(buffers);
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ accept(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req) const
+ {
+ ws.accept(req);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ Decorator const& d) const
+ {
+ ws.accept_ex(d);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers, class Decorator>
+ typename std::enable_if<
+ ! http::detail::is_header<Buffers>::value>::type
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ Buffers const& buffers,
+ Decorator const& d) const
+ {
+ ws.accept_ex(buffers, d);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req,
+ Decorator const& d) const
+ {
+ ws.accept_ex(req, d);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers, class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req,
+ Buffers const& buffers,
+ Decorator const& d) const
+ {
+ ws.accept_ex(req, buffers, d);
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ handshake(
+ stream<NextLayer, deflateSupported>& ws,
+ string_view uri,
+ string_view path) const
+ {
+ ws.handshake(uri, path);
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ handshake(
+ stream<NextLayer, deflateSupported>& ws,
+ response_type& res,
+ string_view uri,
+ string_view path) const
+ {
+ ws.handshake(res, uri, path);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ handshake_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ string_view uri,
+ string_view path,
+ Decorator const& d) const
+ {
+ ws.handshake_ex(uri, path, d);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ handshake_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ response_type& res,
+ string_view uri,
+ string_view path,
+ Decorator const& d) const
+ {
+ ws.handshake_ex(res, uri, path, d);
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ ping(stream<NextLayer, deflateSupported>& ws,
+ ping_data const& payload) const
+ {
+ ws.ping(payload);
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ pong(stream<NextLayer, deflateSupported>& ws,
+ ping_data const& payload) const
+ {
+ ws.pong(payload);
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ close(stream<NextLayer, deflateSupported>& ws,
+ close_reason const& cr) const
+ {
+ ws.close(cr);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class DynamicBuffer>
+ std::size_t
+ read(stream<NextLayer, deflateSupported>& ws,
+ DynamicBuffer& buffer) const
+ {
+ return ws.read(buffer);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class DynamicBuffer>
+ std::size_t
+ read_some(
+ stream<NextLayer, deflateSupported>& ws,
+ std::size_t limit,
+ DynamicBuffer& buffer) const
+ {
+ return ws.read_some(buffer, limit);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class MutableBufferSequence>
+ std::size_t
+ read_some(
+ stream<NextLayer, deflateSupported>& ws,
+ MutableBufferSequence const& buffers) const
+ {
+ return ws.read_some(buffers);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write(
+ stream<NextLayer, deflateSupported>& ws,
+ ConstBufferSequence const& buffers) const
+ {
+ return ws.write(buffers);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write_some(
+ stream<NextLayer, deflateSupported>& ws,
+ bool fin,
+ ConstBufferSequence const& buffers) const
+ {
+ return ws.write_some(fin, buffers);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write_raw(
+ stream<NextLayer, deflateSupported>& ws,
+ ConstBufferSequence const& buffers) const
+ {
+ return net::write(
+ ws.next_layer(), buffers);
+ }
+ };
+
+ //--------------------------------------------------------------------------
+
+ class AsyncClient
+ {
+ net::yield_context& yield_;
+
+ public:
+ explicit
+ AsyncClient(net::yield_context& yield)
+ : yield_(yield)
+ {
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ accept(stream<NextLayer, deflateSupported>& ws) const
+ {
+ error_code ec;
+ ws.async_accept(yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers>
+ typename std::enable_if<
+ ! http::detail::is_header<Buffers>::value>::type
+ accept(
+ stream<NextLayer, deflateSupported>& ws,
+ Buffers const& buffers) const
+ {
+ error_code ec;
+ ws.async_accept(buffers, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ accept(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req) const
+ {
+ error_code ec;
+ ws.async_accept(req, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ Decorator const& d) const
+ {
+ error_code ec;
+ ws.async_accept_ex(d, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers, class Decorator>
+ typename std::enable_if<
+ ! http::detail::is_header<Buffers>::value>::type
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ Buffers const& buffers,
+ Decorator const& d) const
+ {
+ error_code ec;
+ ws.async_accept_ex(buffers, d, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req,
+ Decorator const& d) const
+ {
+ error_code ec;
+ ws.async_accept_ex(req, d, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers, class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req,
+ Buffers const& buffers,
+ Decorator const& d) const
+ {
+ error_code ec;
+ ws.async_accept_ex(
+ req, buffers, d, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported>
+ void
+ handshake(
+ stream<NextLayer, deflateSupported>& ws,
+ string_view uri,
+ string_view path) const
+ {
+ error_code ec;
+ ws.async_handshake(
+ uri, path, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ handshake(
+ stream<NextLayer, deflateSupported>& ws,
+ response_type& res,
+ string_view uri,
+ string_view path) const
+ {
+ error_code ec;
+ ws.async_handshake(
+ res, uri, path, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ handshake_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ string_view uri,
+ string_view path,
+ Decorator const &d) const
+ {
+ error_code ec;
+ ws.async_handshake_ex(
+ uri, path, d, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ handshake_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ response_type& res,
+ string_view uri,
+ string_view path,
+ Decorator const &d) const
+ {
+ error_code ec;
+ ws.async_handshake_ex(
+ res, uri, path, d, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ ping(
+ stream<NextLayer, deflateSupported>& ws,
+ ping_data const& payload) const
+ {
+ error_code ec;
+ ws.async_ping(payload, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ pong(
+ stream<NextLayer, deflateSupported>& ws,
+ ping_data const& payload) const
+ {
+ error_code ec;
+ ws.async_pong(payload, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ close(
+ stream<NextLayer, deflateSupported>& ws,
+ close_reason const& cr) const
+ {
+ error_code ec;
+ ws.async_close(cr, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class DynamicBuffer>
+ std::size_t
+ read(
+ stream<NextLayer, deflateSupported>& ws,
+ DynamicBuffer& buffer) const
+ {
+ error_code ec;
+ auto const bytes_written =
+ ws.async_read(buffer, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ return bytes_written;
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class DynamicBuffer>
+ std::size_t
+ read_some(
+ stream<NextLayer, deflateSupported>& ws,
+ std::size_t limit,
+ DynamicBuffer& buffer) const
+ {
+ error_code ec;
+ auto const bytes_written =
+ ws.async_read_some(buffer, limit, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ return bytes_written;
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class MutableBufferSequence>
+ std::size_t
+ read_some(
+ stream<NextLayer, deflateSupported>& ws,
+ MutableBufferSequence const& buffers) const
+ {
+ error_code ec;
+ auto const bytes_written =
+ ws.async_read_some(buffers, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ return bytes_written;
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write(
+ stream<NextLayer, deflateSupported>& ws,
+ ConstBufferSequence const& buffers) const
+ {
+ error_code ec;
+ auto const bytes_transferred =
+ ws.async_write(buffers, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ return bytes_transferred;
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write_some(
+ stream<NextLayer, deflateSupported>& ws,
+ bool fin,
+ ConstBufferSequence const& buffers) const
+ {
+ error_code ec;
+ auto const bytes_transferred =
+ ws.async_write_some(fin, buffers, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ return bytes_transferred;
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write_raw(
+ stream<NextLayer, deflateSupported>& ws,
+ ConstBufferSequence const& buffers) const
+ {
+ error_code ec;
+ auto const bytes_transferred =
+ net::async_write(
+ ws.next_layer(), buffers, yield_[ec]);
+ if(ec)
+ throw system_error{ec};
+ return bytes_transferred;
+ }
+ };
+};
+
+struct test_sync_api
+{
+ template<class NextLayer, bool deflateSupported>
+ void
+ accept(
+ stream<NextLayer, deflateSupported>& ws) const
+ {
+ ws.accept();
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers>
+ typename std::enable_if<
+ ! http::detail::is_header<Buffers>::value>::type
+ accept(stream<NextLayer, deflateSupported>& ws,
+ Buffers const& buffers) const
+ {
+ ws.accept(buffers);
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ accept(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req) const
+ {
+ ws.accept(req);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ Decorator const& d) const
+ {
+ ws.accept_ex(d);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers, class Decorator>
+ typename std::enable_if<
+ ! http::detail::is_header<Buffers>::value>::type
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ Buffers const& buffers,
+ Decorator const& d) const
+ {
+ ws.accept_ex(buffers, d);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req,
+ Decorator const& d) const
+ {
+ ws.accept_ex(req, d);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers, class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req,
+ Buffers const& buffers,
+ Decorator const& d) const
+ {
+ ws.accept_ex(req, buffers, d);
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ handshake(
+ stream<NextLayer, deflateSupported>& ws,
+ response_type& res,
+ string_view uri,
+ string_view path) const
+ {
+ ws.handshake(res, uri, path);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ handshake_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ string_view uri,
+ string_view path,
+ Decorator const& d) const
+ {
+ ws.handshake_ex(uri, path, d);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ handshake_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ response_type& res,
+ string_view uri,
+ string_view path,
+ Decorator const& d) const
+ {
+ ws.handshake_ex(res, uri, path, d);
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ ping(stream<NextLayer, deflateSupported>& ws,
+ ping_data const& payload) const
+ {
+ ws.ping(payload);
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ pong(stream<NextLayer, deflateSupported>& ws,
+ ping_data const& payload) const
+ {
+ ws.pong(payload);
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ close(stream<NextLayer, deflateSupported>& ws,
+ close_reason const& cr) const
+ {
+ ws.close(cr);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class DynamicBuffer>
+ std::size_t
+ read(stream<NextLayer, deflateSupported>& ws,
+ DynamicBuffer& buffer) const
+ {
+ return ws.read(buffer);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class DynamicBuffer>
+ std::size_t
+ read_some(
+ stream<NextLayer, deflateSupported>& ws,
+ std::size_t limit,
+ DynamicBuffer& buffer) const
+ {
+ return ws.read_some(buffer, limit);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class MutableBufferSequence>
+ std::size_t
+ read_some(
+ stream<NextLayer, deflateSupported>& ws,
+ MutableBufferSequence const& buffers) const
+ {
+ return ws.read_some(buffers);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write(
+ stream<NextLayer, deflateSupported>& ws,
+ ConstBufferSequence const& buffers) const
+ {
+ return ws.write(buffers);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write_some(
+ stream<NextLayer, deflateSupported>& ws,
+ bool fin,
+ ConstBufferSequence const& buffers) const
+ {
+ return ws.write_some(fin, buffers);
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write_raw(
+ stream<NextLayer, deflateSupported>& ws,
+ ConstBufferSequence const& buffers) const
+ {
+ return net::write(
+ ws.next_layer(), buffers);
+ }
+};
+
+//--------------------------------------------------------------------------
+
+class test_async_api
+{
+ struct handler
+ {
+ error_code& ec_;
+ std::size_t* n_ = 0;
+ bool pass_ = false;
+
+ explicit
+ handler(error_code& ec)
+ : ec_(ec)
+ {
+ }
+
+ explicit
+ handler(error_code& ec, std::size_t& n)
+ : ec_(ec)
+ , n_(&n)
+ {
+ *n_ = 0;
+ }
+
+ handler(handler&& other)
+ : ec_(other.ec_)
+ , pass_(boost::exchange(other.pass_, true))
+ {
+ }
+
+ ~handler()
+ {
+ BEAST_EXPECT(pass_);
+ }
+
+ void
+ operator()(error_code ec)
+ {
+ BEAST_EXPECT(! pass_);
+ pass_ = true;
+ ec_ = ec;
+ }
+
+ void
+ operator()(error_code ec, std::size_t n)
+ {
+ BEAST_EXPECT(! pass_);
+ pass_ = true;
+ ec_ = ec;
+ if(n_)
+ *n_ = n;
+ }
+ };
+
+public:
+ template<class NextLayer, bool deflateSupported>
+ void
+ accept(
+ stream<NextLayer, deflateSupported>& ws) const
+ {
+ error_code ec;
+ ws.async_accept(handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers>
+ typename std::enable_if<
+ ! http::detail::is_header<Buffers>::value>::type
+ accept(
+ stream<NextLayer, deflateSupported>& ws,
+ Buffers const& buffers) const
+ {
+ error_code ec;
+ ws.async_accept(buffers, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ accept(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req) const
+ {
+ error_code ec;
+ ws.async_accept(req, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ Decorator const& d) const
+ {
+ error_code ec;
+ ws.async_accept_ex(d, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers, class Decorator>
+ typename std::enable_if<
+ ! http::detail::is_header<Buffers>::value>::type
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ Buffers const& buffers,
+ Decorator const& d) const
+ {
+ error_code ec;
+ ws.async_accept_ex(buffers, d, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req,
+ Decorator const& d) const
+ {
+ error_code ec;
+ ws.async_accept_ex(req, d, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Buffers, class Decorator>
+ void
+ accept_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ http::request<http::empty_body> const& req,
+ Buffers const& buffers,
+ Decorator const& d) const
+ {
+ error_code ec;
+ ws.async_accept_ex(
+ req, buffers, d, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported>
+ void
+ handshake(
+ stream<NextLayer, deflateSupported>& ws,
+ string_view uri,
+ string_view path) const
+ {
+ error_code ec;
+ ws.async_handshake(
+ uri, path, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ handshake(
+ stream<NextLayer, deflateSupported>& ws,
+ response_type& res,
+ string_view uri,
+ string_view path) const
+ {
+ error_code ec;
+ ws.async_handshake(
+ res, uri, path, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ handshake_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ string_view uri,
+ string_view path,
+ Decorator const &d) const
+ {
+ error_code ec;
+ ws.async_handshake_ex(
+ uri, path, d, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class Decorator>
+ void
+ handshake_ex(
+ stream<NextLayer, deflateSupported>& ws,
+ response_type& res,
+ string_view uri,
+ string_view path,
+ Decorator const &d) const
+ {
+ error_code ec;
+ ws.async_handshake_ex(
+ res, uri, path, d, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ ping(
+ stream<NextLayer, deflateSupported>& ws,
+ ping_data const& payload) const
+ {
+ error_code ec;
+ ws.async_ping(payload, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ pong(
+ stream<NextLayer, deflateSupported>& ws,
+ ping_data const& payload) const
+ {
+ error_code ec;
+ ws.async_pong(payload, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<class NextLayer, bool deflateSupported>
+ void
+ close(
+ stream<NextLayer, deflateSupported>& ws,
+ close_reason const& cr) const
+ {
+ error_code ec;
+ ws.async_close(cr, handler(ec));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class DynamicBuffer>
+ std::size_t
+ read(
+ stream<NextLayer, deflateSupported>& ws,
+ DynamicBuffer& buffer) const
+ {
+ error_code ec;
+ std::size_t n;
+ ws.async_read(buffer, handler(ec, n));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ return n;
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class DynamicBuffer>
+ std::size_t
+ read_some(
+ stream<NextLayer, deflateSupported>& ws,
+ std::size_t limit,
+ DynamicBuffer& buffer) const
+ {
+ error_code ec;
+ std::size_t n;
+ ws.async_read_some(buffer, limit, handler(ec, n));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ return n;
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class MutableBufferSequence>
+ std::size_t
+ read_some(
+ stream<NextLayer, deflateSupported>& ws,
+ MutableBufferSequence const& buffers) const
+ {
+ error_code ec;
+ std::size_t n;
+ ws.async_read_some(buffers, handler(ec, n));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ return n;
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write(
+ stream<NextLayer, deflateSupported>& ws,
+ ConstBufferSequence const& buffers) const
+ {
+ error_code ec;
+ std::size_t n;
+ ws.async_write(buffers, handler(ec, n));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ return n;
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write_some(
+ stream<NextLayer, deflateSupported>& ws,
+ bool fin,
+ ConstBufferSequence const& buffers) const
+ {
+ error_code ec;
+ std::size_t n;
+ ws.async_write_some(fin, buffers, handler(ec, n));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ return n;
+ }
+
+ template<
+ class NextLayer, bool deflateSupported,
+ class ConstBufferSequence>
+ std::size_t
+ write_raw(
+ stream<NextLayer, deflateSupported>& ws,
+ ConstBufferSequence const& buffers) const
+ {
+ error_code ec;
+ std::size_t n;
+ net::async_write(ws.next_layer(),
+ buffers, handler(ec, n));
+ ws.get_executor().context().run();
+ ws.get_executor().context().restart();
+ if(ec)
+ throw system_error{ec};
+ return n;
+ }
+};
+
+} // websocket
+} // beast
+} // boost
+
+#endif