mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 04:47:29 +02:00
Add test::stream to experimental
This commit is contained in:
@ -4,6 +4,7 @@ Version 170:
|
|||||||
* Add ssl_stream to experimental
|
* Add ssl_stream to experimental
|
||||||
* Add test::error to experimental
|
* Add test::error to experimental
|
||||||
* Add test::fail_count to experimental
|
* Add test::fail_count to experimental
|
||||||
|
* Add test::stream to experimental
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -303,6 +303,7 @@
|
|||||||
<member><link linkend="beast.ref.boost__beast__flat_stream">flat_stream</link></member>
|
<member><link linkend="beast.ref.boost__beast__flat_stream">flat_stream</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__ssl_stream">ssl_stream</link></member>
|
<member><link linkend="beast.ref.boost__beast__ssl_stream">ssl_stream</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__test__fail_count">test::fail_count</link></member>
|
<member><link linkend="beast.ref.boost__beast__test__fail_count">test::fail_count</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__test__stream">test::stream</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
|
@ -7,375 +7,147 @@
|
|||||||
// Official repository: https://github.com/boostorg/beast
|
// Official repository: https://github.com/boostorg/beast
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BOOST_BEAST_TEST_STREAM_HPP
|
#ifndef BOOST_BEAST_TEST_IMPL_STREAM_IPP
|
||||||
#define BOOST_BEAST_TEST_STREAM_HPP
|
#define BOOST_BEAST_TEST_IMPL_STREAM_IPP
|
||||||
|
|
||||||
#include <boost/beast/core/bind_handler.hpp>
|
|
||||||
#include <boost/beast/core/buffers_prefix.hpp>
|
#include <boost/beast/core/buffers_prefix.hpp>
|
||||||
#include <boost/beast/core/flat_buffer.hpp>
|
|
||||||
#include <boost/beast/core/string.hpp>
|
|
||||||
#include <boost/beast/core/type_traits.hpp>
|
|
||||||
#include <boost/beast/websocket/teardown.hpp>
|
|
||||||
#include <boost/beast/experimental/test/fail_count.hpp>
|
|
||||||
#include <boost/asio/async_result.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
#include <boost/asio/executor_work_guard.hpp>
|
|
||||||
#include <boost/asio/io_context.hpp>
|
|
||||||
#include <boost/asio/post.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <boost/throw_exception.hpp>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <limits>
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
/** A bidirectional in-memory communication channel
|
inline
|
||||||
|
stream::
|
||||||
An instance of this class provides a client and server
|
~stream()
|
||||||
endpoint that are automatically connected to each other
|
|
||||||
similarly to a connected socket.
|
|
||||||
|
|
||||||
Test pipes are used to facilitate writing unit tests
|
|
||||||
where the behavior of the transport is tightly controlled
|
|
||||||
to help illuminate all code paths (for code coverage)
|
|
||||||
*/
|
|
||||||
class stream
|
|
||||||
{
|
{
|
||||||
struct read_op
|
|
||||||
{
|
{
|
||||||
virtual ~read_op() = default;
|
std::unique_lock<std::mutex> lock{in_->m};
|
||||||
virtual void operator()() = 0;
|
in_->op.reset();
|
||||||
};
|
}
|
||||||
|
auto out = out_.lock();
|
||||||
template<class Handler, class Buffers>
|
if(out)
|
||||||
class read_op_impl;
|
|
||||||
|
|
||||||
enum class status
|
|
||||||
{
|
{
|
||||||
ok,
|
std::unique_lock<std::mutex> lock{out->m};
|
||||||
eof,
|
if(out->code == status::ok)
|
||||||
reset
|
|
||||||
};
|
|
||||||
|
|
||||||
struct state
|
|
||||||
{
|
|
||||||
friend class stream;
|
|
||||||
|
|
||||||
std::mutex m;
|
|
||||||
flat_buffer b;
|
|
||||||
std::condition_variable cv;
|
|
||||||
std::unique_ptr<read_op> op;
|
|
||||||
boost::asio::io_context& ioc;
|
|
||||||
status code = status::ok;
|
|
||||||
fail_count* fc = nullptr;
|
|
||||||
std::size_t nread = 0;
|
|
||||||
std::size_t nwrite = 0;
|
|
||||||
std::size_t read_max =
|
|
||||||
(std::numeric_limits<std::size_t>::max)();
|
|
||||||
std::size_t write_max =
|
|
||||||
(std::numeric_limits<std::size_t>::max)();
|
|
||||||
|
|
||||||
~state()
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(! op);
|
out->code = status::reset;
|
||||||
}
|
out->on_write();
|
||||||
|
|
||||||
explicit
|
|
||||||
state(
|
|
||||||
boost::asio::io_context& ioc_,
|
|
||||||
fail_count* fc_)
|
|
||||||
: ioc(ioc_)
|
|
||||||
, fc(fc_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
on_write()
|
|
||||||
{
|
|
||||||
if(op)
|
|
||||||
{
|
|
||||||
std::unique_ptr<read_op> op_ = std::move(op);
|
|
||||||
op_->operator()();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cv.notify_all();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<state> in_;
|
|
||||||
std::weak_ptr<state> out_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using buffer_type = flat_buffer;
|
|
||||||
|
|
||||||
/// The type of the lowest layer.
|
|
||||||
using lowest_layer_type = stream;
|
|
||||||
|
|
||||||
/// Destructor
|
|
||||||
~stream()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock{in_->m};
|
|
||||||
in_->op.reset();
|
|
||||||
}
|
|
||||||
auto out = out_.lock();
|
|
||||||
if(out)
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock{out->m};
|
|
||||||
if(out->code == status::ok)
|
|
||||||
{
|
|
||||||
out->code = status::reset;
|
|
||||||
out->on_write();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructor
|
inline
|
||||||
stream(stream&& other)
|
stream::
|
||||||
{
|
stream(stream&& other)
|
||||||
auto in = std::make_shared<state>(
|
{
|
||||||
other.in_->ioc, other.in_->fc);
|
auto in = std::make_shared<state>(
|
||||||
in_ = std::move(other.in_);
|
other.in_->ioc, other.in_->fc);
|
||||||
out_ = std::move(other.out_);
|
in_ = std::move(other.in_);
|
||||||
other.in_ = in;
|
out_ = std::move(other.out_);
|
||||||
}
|
other.in_ = in;
|
||||||
|
}
|
||||||
|
|
||||||
/// Assignment
|
inline
|
||||||
stream&
|
stream&
|
||||||
operator=(stream&& other)
|
stream::
|
||||||
{
|
operator=(stream&& other)
|
||||||
auto in = std::make_shared<state>(
|
{
|
||||||
other.in_->ioc, other.in_->fc);
|
auto in = std::make_shared<state>(
|
||||||
in_ = std::move(other.in_);
|
other.in_->ioc, other.in_->fc);
|
||||||
out_ = std::move(other.out_);
|
in_ = std::move(other.in_);
|
||||||
other.in_ = in;
|
out_ = std::move(other.out_);
|
||||||
return *this;
|
other.in_ = in;
|
||||||
}
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructor
|
inline
|
||||||
explicit
|
stream::
|
||||||
stream(boost::asio::io_context& ioc)
|
stream(boost::asio::io_context& ioc)
|
||||||
: in_(std::make_shared<state>(ioc, nullptr))
|
: in_(std::make_shared<state>(ioc, nullptr))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructor
|
inline
|
||||||
stream(
|
stream::
|
||||||
boost::asio::io_context& ioc,
|
stream(
|
||||||
fail_count& fc)
|
boost::asio::io_context& ioc,
|
||||||
: in_(std::make_shared<state>(ioc, &fc))
|
fail_count& fc)
|
||||||
{
|
: in_(std::make_shared<state>(ioc, &fc))
|
||||||
}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructor
|
inline
|
||||||
stream(
|
stream::
|
||||||
boost::asio::io_context& ioc,
|
stream(
|
||||||
string_view s)
|
boost::asio::io_context& ioc,
|
||||||
: in_(std::make_shared<state>(ioc, nullptr))
|
string_view s)
|
||||||
{
|
: in_(std::make_shared<state>(ioc, nullptr))
|
||||||
using boost::asio::buffer;
|
{
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer;
|
||||||
in_->b.commit(buffer_copy(
|
using boost::asio::buffer_copy;
|
||||||
in_->b.prepare(s.size()),
|
in_->b.commit(buffer_copy(
|
||||||
buffer(s.data(), s.size())));
|
in_->b.prepare(s.size()),
|
||||||
}
|
buffer(s.data(), s.size())));
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructor
|
inline
|
||||||
stream(
|
stream::
|
||||||
boost::asio::io_context& ioc,
|
stream(
|
||||||
fail_count& fc,
|
boost::asio::io_context& ioc,
|
||||||
string_view s)
|
fail_count& fc,
|
||||||
: in_(std::make_shared<state>(ioc, &fc))
|
string_view s)
|
||||||
{
|
: in_(std::make_shared<state>(ioc, &fc))
|
||||||
using boost::asio::buffer;
|
{
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer;
|
||||||
in_->b.commit(buffer_copy(
|
using boost::asio::buffer_copy;
|
||||||
in_->b.prepare(s.size()),
|
in_->b.commit(buffer_copy(
|
||||||
buffer(s.data(), s.size())));
|
in_->b.prepare(s.size()),
|
||||||
}
|
buffer(s.data(), s.size())));
|
||||||
|
}
|
||||||
|
|
||||||
/// Establish a connection
|
inline
|
||||||
void
|
void
|
||||||
connect(stream& remote)
|
stream::
|
||||||
{
|
connect(stream& remote)
|
||||||
BOOST_ASSERT(! out_.lock());
|
{
|
||||||
BOOST_ASSERT(! remote.out_.lock());
|
BOOST_ASSERT(! out_.lock());
|
||||||
out_ = remote.in_;
|
BOOST_ASSERT(! remote.out_.lock());
|
||||||
remote.out_ = in_;
|
out_ = remote.in_;
|
||||||
}
|
remote.out_ = in_;
|
||||||
|
}
|
||||||
|
inline
|
||||||
|
string_view
|
||||||
|
stream::
|
||||||
|
str() const
|
||||||
|
{
|
||||||
|
auto const bs = in_->b.data();
|
||||||
|
if(boost::asio::buffer_size(bs) == 0)
|
||||||
|
return {};
|
||||||
|
auto const b = buffers_front(bs);
|
||||||
|
return {reinterpret_cast<char const*>(b.data()), b.size()};
|
||||||
|
}
|
||||||
|
|
||||||
/// The type of the executor associated with the object.
|
inline
|
||||||
using executor_type =
|
void
|
||||||
boost::asio::io_context::executor_type;
|
stream::
|
||||||
|
append(string_view s)
|
||||||
|
{
|
||||||
|
using boost::asio::buffer;
|
||||||
|
using boost::asio::buffer_copy;
|
||||||
|
std::lock_guard<std::mutex> lock{in_->m};
|
||||||
|
in_->b.commit(buffer_copy(
|
||||||
|
in_->b.prepare(s.size()),
|
||||||
|
buffer(s.data(), s.size())));
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the executor associated with the object.
|
inline
|
||||||
boost::asio::io_context::executor_type
|
void
|
||||||
get_executor() noexcept
|
stream::
|
||||||
{
|
clear()
|
||||||
return in_->ioc.get_executor();
|
{
|
||||||
};
|
std::lock_guard<std::mutex> lock{in_->m};
|
||||||
|
in_->b.consume(in_->b.size());
|
||||||
/** Get a reference to the lowest layer
|
}
|
||||||
|
|
||||||
This function returns a reference to the lowest layer
|
|
||||||
in a stack of stream layers.
|
|
||||||
|
|
||||||
@return A reference to the lowest layer in the stack of
|
|
||||||
stream layers.
|
|
||||||
*/
|
|
||||||
lowest_layer_type&
|
|
||||||
lowest_layer()
|
|
||||||
{
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a reference to the lowest layer
|
|
||||||
|
|
||||||
This function returns a reference to the lowest layer
|
|
||||||
in a stack of stream layers.
|
|
||||||
|
|
||||||
@return A reference to the lowest layer in the stack of
|
|
||||||
stream layers. Ownership is not transferred to the caller.
|
|
||||||
*/
|
|
||||||
lowest_layer_type const&
|
|
||||||
lowest_layer() const
|
|
||||||
{
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the maximum number of bytes returned by read_some
|
|
||||||
void
|
|
||||||
read_size(std::size_t n)
|
|
||||||
{
|
|
||||||
in_->read_max = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the maximum number of bytes returned by write_some
|
|
||||||
void
|
|
||||||
write_size(std::size_t n)
|
|
||||||
{
|
|
||||||
in_->write_max = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Direct input buffer access
|
|
||||||
buffer_type&
|
|
||||||
buffer()
|
|
||||||
{
|
|
||||||
return in_->b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a string view representing the pending input data
|
|
||||||
string_view
|
|
||||||
str() const
|
|
||||||
{
|
|
||||||
auto const bs = in_->b.data();
|
|
||||||
if(boost::asio::buffer_size(bs) == 0)
|
|
||||||
return {};
|
|
||||||
auto const b = buffers_front(bs);
|
|
||||||
return {reinterpret_cast<char const*>(b.data()), b.size()};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Appends a string to the pending input data
|
|
||||||
void
|
|
||||||
append(string_view s)
|
|
||||||
{
|
|
||||||
using boost::asio::buffer;
|
|
||||||
using boost::asio::buffer_copy;
|
|
||||||
std::lock_guard<std::mutex> lock{in_->m};
|
|
||||||
in_->b.commit(buffer_copy(
|
|
||||||
in_->b.prepare(s.size()),
|
|
||||||
buffer(s.data(), s.size())));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clear the pending input area
|
|
||||||
void
|
|
||||||
clear()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock{in_->m};
|
|
||||||
in_->b.consume(in_->b.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the number of reads
|
|
||||||
std::size_t
|
|
||||||
nread() const
|
|
||||||
{
|
|
||||||
return in_->nread;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the number of writes
|
|
||||||
std::size_t
|
|
||||||
nwrite() const
|
|
||||||
{
|
|
||||||
return in_->nwrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Close the stream.
|
|
||||||
|
|
||||||
The other end of the connection will see
|
|
||||||
`error::eof` after reading all the remaining data.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
close();
|
|
||||||
|
|
||||||
/** Close the other end of the stream.
|
|
||||||
|
|
||||||
This end of the connection will see
|
|
||||||
`error::eof` after reading all the remaining data.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
close_remote();
|
|
||||||
|
|
||||||
template<class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const& buffers);
|
|
||||||
|
|
||||||
template<class MutableBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
read_some(MutableBufferSequence const& buffers,
|
|
||||||
error_code& ec);
|
|
||||||
|
|
||||||
template<class MutableBufferSequence, class ReadHandler>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
|
||||||
ReadHandler, void(error_code, std::size_t))
|
|
||||||
async_read_some(MutableBufferSequence const& buffers,
|
|
||||||
ReadHandler&& handler);
|
|
||||||
|
|
||||||
template<class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(ConstBufferSequence const& buffers);
|
|
||||||
|
|
||||||
template<class ConstBufferSequence>
|
|
||||||
std::size_t
|
|
||||||
write_some(
|
|
||||||
ConstBufferSequence const& buffers, error_code&);
|
|
||||||
|
|
||||||
template<class ConstBufferSequence, class WriteHandler>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
|
||||||
WriteHandler, void(error_code, std::size_t))
|
|
||||||
async_write_some(ConstBufferSequence const& buffers,
|
|
||||||
WriteHandler&& handler);
|
|
||||||
|
|
||||||
friend
|
|
||||||
void
|
|
||||||
teardown(websocket::role_type,
|
|
||||||
stream& s, boost::system::error_code& ec);
|
|
||||||
|
|
||||||
template<class TeardownHandler>
|
|
||||||
friend
|
|
||||||
void
|
|
||||||
async_teardown(websocket::role_type role,
|
|
||||||
stream& s, TeardownHandler&& handler);
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
@ -532,7 +304,7 @@ async_read_some(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
in_->op.reset(new read_op_impl<BOOST_ASIO_HANDLER_TYPE(
|
in_->op.reset(new read_op<BOOST_ASIO_HANDLER_TYPE(
|
||||||
ReadHandler, void(error_code, std::size_t)),
|
ReadHandler, void(error_code, std::size_t)),
|
||||||
MutableBufferSequence>{*in_, buffers,
|
MutableBufferSequence>{*in_, buffers,
|
||||||
std::move(init.completion_handler)});
|
std::move(init.completion_handler)});
|
||||||
@ -645,9 +417,9 @@ async_write_some(ConstBufferSequence const& buffers,
|
|||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
teardown(
|
teardown(
|
||||||
websocket::role_type,
|
websocket::role_type,
|
||||||
stream& s,
|
stream& s,
|
||||||
boost::system::error_code& ec)
|
boost::system::error_code& ec)
|
||||||
{
|
{
|
||||||
if( s.in_->fc &&
|
if( s.in_->fc &&
|
||||||
s.in_->fc->fail(ec))
|
s.in_->fc->fail(ec))
|
||||||
@ -666,9 +438,9 @@ template<class TeardownHandler>
|
|||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
async_teardown(
|
async_teardown(
|
||||||
websocket::role_type,
|
websocket::role_type,
|
||||||
stream& s,
|
stream& s,
|
||||||
TeardownHandler&& handler)
|
TeardownHandler&& handler)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
if( s.in_->fc &&
|
if( s.in_->fc &&
|
||||||
@ -691,7 +463,7 @@ async_teardown(
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Handler, class Buffers>
|
template<class Handler, class Buffers>
|
||||||
class stream::read_op_impl : public stream::read_op
|
class stream::read_op : public stream::read_op_base
|
||||||
{
|
{
|
||||||
class lambda
|
class lambda
|
||||||
{
|
{
|
||||||
@ -769,7 +541,7 @@ class stream::read_op_impl : public stream::read_op
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
read_op_impl(state& s, Buffers const& b, DeducedHandler&& h)
|
read_op(state& s, Buffers const& b, DeducedHandler&& h)
|
||||||
: fn_(s, b, std::forward<DeducedHandler>(h))
|
: fn_(s, b, std::forward<DeducedHandler>(h))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -781,7 +553,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Create and return a connected stream
|
|
||||||
inline
|
inline
|
||||||
stream
|
stream
|
||||||
connect(stream& to)
|
connect(stream& to)
|
||||||
@ -791,7 +562,6 @@ connect(stream& to)
|
|||||||
return from;
|
return from;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create and return a connected stream
|
|
||||||
template<class Arg1, class... ArgN>
|
template<class Arg1, class... ArgN>
|
||||||
stream
|
stream
|
||||||
connect(stream& to, Arg1&& arg1, ArgN&&... argn)
|
connect(stream& to, Arg1&& arg1, ArgN&&... argn)
|
538
include/boost/beast/experimental/test/stream.hpp
Normal file
538
include/boost/beast/experimental/test/stream.hpp
Normal file
@ -0,0 +1,538 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2016-2017 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 BOOST_BEAST_TEST_STREAM_HPP
|
||||||
|
#define BOOST_BEAST_TEST_STREAM_HPP
|
||||||
|
|
||||||
|
#include <boost/beast/core/bind_handler.hpp>
|
||||||
|
#include <boost/beast/core/flat_buffer.hpp>
|
||||||
|
#include <boost/beast/core/string.hpp>
|
||||||
|
#include <boost/beast/core/type_traits.hpp>
|
||||||
|
#include <boost/beast/websocket/teardown.hpp>
|
||||||
|
#include <boost/beast/experimental/test/fail_count.hpp>
|
||||||
|
#include <boost/asio/async_result.hpp>
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/asio/post.hpp>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <boost/throw_exception.hpp>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace test {
|
||||||
|
|
||||||
|
/** A two-way socket useful for unit testing
|
||||||
|
|
||||||
|
An instance of this class simulates a traditional socket,
|
||||||
|
while also providing features useful for unit testing.
|
||||||
|
Each endpoint maintains an independent buffer called
|
||||||
|
the input area. Writes from one endpoint append data
|
||||||
|
to the peer's pending input area. When an endpoint performs
|
||||||
|
a read and data is present in the input area, the data is
|
||||||
|
delivered to the blocking or asynchronous operation. Otherwise
|
||||||
|
the operation is blocked or deferred until data is made
|
||||||
|
available, or until the endpoints become disconnected.
|
||||||
|
|
||||||
|
These streams may be used anywhere an algorithm accepts a
|
||||||
|
reference to a synchronous or asynchronous read or write
|
||||||
|
stream. It is possible to use a test stream in a call to
|
||||||
|
`boost::asio::read_until`, or in a call to
|
||||||
|
@ref boost::beast::http::async_write for example.
|
||||||
|
|
||||||
|
As with Boost.Asio I/O objects, a @ref stream constructs
|
||||||
|
with a reference to the `boost::asio::io_context` to use for
|
||||||
|
handling asynchronous I/O. For asynchronous operations, the
|
||||||
|
stream follows the same rules as a traditional asio socket
|
||||||
|
with respect to how completion handlers for asynchronous
|
||||||
|
operations are performed.
|
||||||
|
|
||||||
|
To facilitate testing, these streams support some additional
|
||||||
|
features:
|
||||||
|
|
||||||
|
@li The input area, represented by a @ref flat_buffer, may
|
||||||
|
be directly accessed by the caller to inspect the contents
|
||||||
|
before or after the remote endpoint writes data. This allows
|
||||||
|
a unit test to verify that the received data matches.
|
||||||
|
|
||||||
|
@li Data may be manually appended to the input area. This data
|
||||||
|
will delivered in the next call to
|
||||||
|
@ref stream::read_some or @ref stream::async_read_some.
|
||||||
|
This allows predefined test vectors to be set up for testing
|
||||||
|
read algorithms.
|
||||||
|
|
||||||
|
@li The stream may be constructed with a @ref fail count. The
|
||||||
|
stream will eventually fail with a predefined error after a
|
||||||
|
certain number of operations, where the number of operations
|
||||||
|
is controlled by the test. When a test loops over a range of
|
||||||
|
operation counts, it is possible to exercise every possible
|
||||||
|
point of failure in the algorithm being tested. When used
|
||||||
|
correctly the technique allows the tests to reach a high
|
||||||
|
percentage of code coverage.
|
||||||
|
|
||||||
|
@par Thread Safety
|
||||||
|
@e Distinct @e objects: Safe.@n
|
||||||
|
@e Shared @e objects: Unsafe.
|
||||||
|
The application must also ensure that all asynchronous
|
||||||
|
operations are performed within the same implicit or explicit strand.
|
||||||
|
|
||||||
|
@par Concepts
|
||||||
|
@li @b SyncReadStream
|
||||||
|
@li @b SyncWriteStream
|
||||||
|
@li @b AsyncReadStream
|
||||||
|
@li @b AsyncWriteStream
|
||||||
|
*/
|
||||||
|
class stream
|
||||||
|
{
|
||||||
|
struct read_op_base
|
||||||
|
{
|
||||||
|
virtual ~read_op_base() = default;
|
||||||
|
virtual void operator()() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Handler, class Buffers>
|
||||||
|
class read_op;
|
||||||
|
|
||||||
|
enum class status
|
||||||
|
{
|
||||||
|
ok,
|
||||||
|
eof,
|
||||||
|
reset
|
||||||
|
};
|
||||||
|
|
||||||
|
struct state
|
||||||
|
{
|
||||||
|
friend class stream;
|
||||||
|
|
||||||
|
std::mutex m;
|
||||||
|
flat_buffer b;
|
||||||
|
std::condition_variable cv;
|
||||||
|
std::unique_ptr<read_op_base> op;
|
||||||
|
boost::asio::io_context& ioc;
|
||||||
|
status code = status::ok;
|
||||||
|
fail_count* fc = nullptr;
|
||||||
|
std::size_t nread = 0;
|
||||||
|
std::size_t nwrite = 0;
|
||||||
|
std::size_t read_max =
|
||||||
|
(std::numeric_limits<std::size_t>::max)();
|
||||||
|
std::size_t write_max =
|
||||||
|
(std::numeric_limits<std::size_t>::max)();
|
||||||
|
|
||||||
|
~state()
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(! op);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit
|
||||||
|
state(
|
||||||
|
boost::asio::io_context& ioc_,
|
||||||
|
fail_count* fc_)
|
||||||
|
: ioc(ioc_)
|
||||||
|
, fc(fc_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
on_write()
|
||||||
|
{
|
||||||
|
if(op)
|
||||||
|
{
|
||||||
|
std::unique_ptr<read_op_base> op_ = std::move(op);
|
||||||
|
op_->operator()();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cv.notify_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<state> in_;
|
||||||
|
std::weak_ptr<state> out_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using buffer_type = flat_buffer;
|
||||||
|
|
||||||
|
/// The type of the lowest layer.
|
||||||
|
using lowest_layer_type = stream;
|
||||||
|
|
||||||
|
/** Destructor
|
||||||
|
|
||||||
|
If an asynchronous read operation is pending, it will
|
||||||
|
simply be discarded with no notification to the completion
|
||||||
|
handler.
|
||||||
|
|
||||||
|
If a connection is established while the stream is destroyed,
|
||||||
|
the peer will see the error `boost::asio::error::connection_reset`
|
||||||
|
when performing any reads or writes.
|
||||||
|
*/
|
||||||
|
~stream();
|
||||||
|
|
||||||
|
/** Move Constructor
|
||||||
|
|
||||||
|
Moving the stream while asynchronous operations are pending
|
||||||
|
results in undefined behavior.
|
||||||
|
*/
|
||||||
|
stream(stream&& other);
|
||||||
|
|
||||||
|
/** Move Assignment
|
||||||
|
|
||||||
|
Moving the stream while asynchronous operations are pending
|
||||||
|
results in undefined behavior.
|
||||||
|
*/
|
||||||
|
stream&
|
||||||
|
operator=(stream&& other);
|
||||||
|
|
||||||
|
/** Construct a stream
|
||||||
|
|
||||||
|
The stream will be created in a disconnected state.
|
||||||
|
|
||||||
|
@param ioc The `io_context` object that the stream will use to
|
||||||
|
dispatch handlers for any asynchronous operations.
|
||||||
|
*/
|
||||||
|
explicit
|
||||||
|
stream(boost::asio::io_context& ioc);
|
||||||
|
|
||||||
|
/** Construct a stream
|
||||||
|
|
||||||
|
The stream will be created in a disconnected state.
|
||||||
|
|
||||||
|
@param ioc The `io_context` object that the stream will use to
|
||||||
|
dispatch handlers for any asynchronous operations.
|
||||||
|
|
||||||
|
@param fc The @ref fail_count to associate with the stream.
|
||||||
|
Each I/O operation performed on the stream will increment the
|
||||||
|
fail count. When the fail count reaches its internal limit,
|
||||||
|
a simulated failure error will be raised.
|
||||||
|
*/
|
||||||
|
stream(
|
||||||
|
boost::asio::io_context& ioc,
|
||||||
|
fail_count& fc);
|
||||||
|
|
||||||
|
/** Construct a stream
|
||||||
|
|
||||||
|
The stream will be created in a disconnected state.
|
||||||
|
|
||||||
|
@param ioc The `io_context` object that the stream will use to
|
||||||
|
dispatch handlers for any asynchronous operations.
|
||||||
|
|
||||||
|
@param s A string which will be appended to the input area, not
|
||||||
|
including the null terminator.
|
||||||
|
*/
|
||||||
|
stream(
|
||||||
|
boost::asio::io_context& ioc,
|
||||||
|
string_view s);
|
||||||
|
|
||||||
|
/** Construct a stream
|
||||||
|
|
||||||
|
The stream will be created in a disconnected state.
|
||||||
|
|
||||||
|
@param ioc The `io_context` object that the stream will use to
|
||||||
|
dispatch handlers for any asynchronous operations.
|
||||||
|
|
||||||
|
@param fc The @ref fail_count to associate with the stream.
|
||||||
|
Each I/O operation performed on the stream will increment the
|
||||||
|
fail count. When the fail count reaches its internal limit,
|
||||||
|
a simulated failure error will be raised.
|
||||||
|
|
||||||
|
@param s A string which will be appended to the input area, not
|
||||||
|
including the null terminator.
|
||||||
|
*/
|
||||||
|
stream(
|
||||||
|
boost::asio::io_context& ioc,
|
||||||
|
fail_count& fc,
|
||||||
|
string_view s);
|
||||||
|
|
||||||
|
/// Establish a connection
|
||||||
|
void
|
||||||
|
connect(stream& remote);
|
||||||
|
|
||||||
|
/// The type of the executor associated with the object.
|
||||||
|
using executor_type =
|
||||||
|
boost::asio::io_context::executor_type;
|
||||||
|
|
||||||
|
/// Return the executor associated with the object.
|
||||||
|
boost::asio::io_context::executor_type
|
||||||
|
get_executor() noexcept
|
||||||
|
{
|
||||||
|
return in_->ioc.get_executor();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Get a reference to the lowest layer
|
||||||
|
|
||||||
|
This function returns a reference to the lowest layer
|
||||||
|
in a stack of stream layers.
|
||||||
|
|
||||||
|
@return A reference to the lowest layer in the stack of
|
||||||
|
stream layers.
|
||||||
|
*/
|
||||||
|
lowest_layer_type&
|
||||||
|
lowest_layer()
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a reference to the lowest layer
|
||||||
|
|
||||||
|
This function returns a reference to the lowest layer
|
||||||
|
in a stack of stream layers.
|
||||||
|
|
||||||
|
@return A reference to the lowest layer in the stack of
|
||||||
|
stream layers. Ownership is not transferred to the caller.
|
||||||
|
*/
|
||||||
|
lowest_layer_type const&
|
||||||
|
lowest_layer() const
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the maximum number of bytes returned by read_some
|
||||||
|
void
|
||||||
|
read_size(std::size_t n)
|
||||||
|
{
|
||||||
|
in_->read_max = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the maximum number of bytes returned by write_some
|
||||||
|
void
|
||||||
|
write_size(std::size_t n)
|
||||||
|
{
|
||||||
|
in_->write_max = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Direct input buffer access
|
||||||
|
buffer_type&
|
||||||
|
buffer()
|
||||||
|
{
|
||||||
|
return in_->b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a string view representing the pending input data
|
||||||
|
string_view
|
||||||
|
str() const;
|
||||||
|
|
||||||
|
/// Appends a string to the pending input data
|
||||||
|
void
|
||||||
|
append(string_view s);
|
||||||
|
|
||||||
|
/// Clear the pending input area
|
||||||
|
void
|
||||||
|
clear();
|
||||||
|
|
||||||
|
/// Return the number of reads
|
||||||
|
std::size_t
|
||||||
|
nread() const
|
||||||
|
{
|
||||||
|
return in_->nread;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the number of writes
|
||||||
|
std::size_t
|
||||||
|
nwrite() const
|
||||||
|
{
|
||||||
|
return in_->nwrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Close the stream.
|
||||||
|
|
||||||
|
The other end of the connection will see
|
||||||
|
`error::eof` after reading all the remaining data.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
close();
|
||||||
|
|
||||||
|
/** Close the other end of the stream.
|
||||||
|
|
||||||
|
This end of the connection will see
|
||||||
|
`error::eof` after reading all the remaining data.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
close_remote();
|
||||||
|
|
||||||
|
/** Read some data from the stream.
|
||||||
|
|
||||||
|
This function is used to read data from the stream. The function call will
|
||||||
|
block until one or more bytes of data has been read successfully, or until
|
||||||
|
an error occurs.
|
||||||
|
|
||||||
|
@param buffers The buffers into which the data will be read.
|
||||||
|
|
||||||
|
@returns The number of bytes read.
|
||||||
|
|
||||||
|
@throws boost::system::system_error Thrown on failure.
|
||||||
|
|
||||||
|
@note The `read_some` operation may not read all of the requested number of
|
||||||
|
bytes. Consider using the function `boost::asio::read` if you need to ensure
|
||||||
|
that the requested amount of data is read before the blocking operation
|
||||||
|
completes.
|
||||||
|
*/
|
||||||
|
template<class MutableBufferSequence>
|
||||||
|
std::size_t
|
||||||
|
read_some(MutableBufferSequence const& buffers);
|
||||||
|
|
||||||
|
/** Read some data from the stream.
|
||||||
|
|
||||||
|
This function is used to read data from the stream. The function call will
|
||||||
|
block until one or more bytes of data has been read successfully, or until
|
||||||
|
an error occurs.
|
||||||
|
|
||||||
|
@param buffers The buffers into which the data will be read.
|
||||||
|
|
||||||
|
@param ec Set to indicate what error occurred, if any.
|
||||||
|
|
||||||
|
@returns The number of bytes read.
|
||||||
|
|
||||||
|
@note The `read_some` operation may not read all of the requested number of
|
||||||
|
bytes. Consider using the function `boost::asio::read` if you need to ensure
|
||||||
|
that the requested amount of data is read before the blocking operation
|
||||||
|
completes.
|
||||||
|
*/
|
||||||
|
template<class MutableBufferSequence>
|
||||||
|
std::size_t
|
||||||
|
read_some(MutableBufferSequence const& buffers,
|
||||||
|
error_code& ec);
|
||||||
|
|
||||||
|
/** Start an asynchronous read.
|
||||||
|
|
||||||
|
This function is used to asynchronously read one or more bytes of data from
|
||||||
|
the stream. The function call always returns immediately.
|
||||||
|
|
||||||
|
@param buffers The buffers into which the data will be read. Although the
|
||||||
|
buffers object may be copied as necessary, ownership of the underlying
|
||||||
|
buffers is retained by the caller, which must guarantee that they remain
|
||||||
|
valid until the handler is called.
|
||||||
|
|
||||||
|
@param handler The handler to be called when the read operation completes.
|
||||||
|
Copies will be made of the handler as required. The equivalent function
|
||||||
|
signature of the handler must be:
|
||||||
|
@code void handler(
|
||||||
|
const boost::system::error_code& error, // Result of operation.
|
||||||
|
std::size_t bytes_transferred // Number of bytes read.
|
||||||
|
); @endcode
|
||||||
|
|
||||||
|
@note The `read_some` operation may not read all of the requested number of
|
||||||
|
bytes. Consider using the function `boost::asio::async_read` if you need
|
||||||
|
to ensure that the requested amount of data is read before the asynchronous
|
||||||
|
operation completes.
|
||||||
|
*/
|
||||||
|
template<class MutableBufferSequence, class ReadHandler>
|
||||||
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
|
ReadHandler, void(error_code, std::size_t))
|
||||||
|
async_read_some(MutableBufferSequence const& buffers,
|
||||||
|
ReadHandler&& handler);
|
||||||
|
|
||||||
|
/** Write some data to the stream.
|
||||||
|
|
||||||
|
This function is used to write data on the stream. The function call will
|
||||||
|
block until one or more bytes of data has been written successfully, or
|
||||||
|
until an error occurs.
|
||||||
|
|
||||||
|
@param buffers The data to be written.
|
||||||
|
|
||||||
|
@returns The number of bytes written.
|
||||||
|
|
||||||
|
@throws boost::system::system_error Thrown on failure.
|
||||||
|
|
||||||
|
@note The `write_some` operation may not transmit all of the data to the
|
||||||
|
peer. Consider using the function `boost::asio::write` if you need to
|
||||||
|
ensure that all data is written before the blocking operation completes.
|
||||||
|
*/
|
||||||
|
template<class ConstBufferSequence>
|
||||||
|
std::size_t
|
||||||
|
write_some(ConstBufferSequence const& buffers);
|
||||||
|
|
||||||
|
/** Write some data to the stream.
|
||||||
|
|
||||||
|
This function is used to write data on the stream. The function call will
|
||||||
|
block until one or more bytes of data has been written successfully, or
|
||||||
|
until an error occurs.
|
||||||
|
|
||||||
|
@param buffers The data to be written.
|
||||||
|
|
||||||
|
@param ec Set to indicate what error occurred, if any.
|
||||||
|
|
||||||
|
@returns The number of bytes written.
|
||||||
|
|
||||||
|
@note The `write_some` operation may not transmit all of the data to the
|
||||||
|
peer. Consider using the function `boost::asio::write` if you need to
|
||||||
|
ensure that all data is written before the blocking operation completes.
|
||||||
|
*/
|
||||||
|
template<class ConstBufferSequence>
|
||||||
|
std::size_t
|
||||||
|
write_some(
|
||||||
|
ConstBufferSequence const& buffers, error_code&);
|
||||||
|
|
||||||
|
/** Start an asynchronous write.
|
||||||
|
|
||||||
|
This function is used to asynchronously write one or more bytes of data to
|
||||||
|
the stream. The function call always returns immediately.
|
||||||
|
|
||||||
|
@param buffers The data to be written to the stream. Although the buffers
|
||||||
|
object may be copied as necessary, ownership of the underlying buffers is
|
||||||
|
retained by the caller, which must guarantee that they remain valid until
|
||||||
|
the handler is called.
|
||||||
|
|
||||||
|
@param handler The handler to be called when the write operation completes.
|
||||||
|
Copies will be made of the handler as required. The equivalent function
|
||||||
|
signature of the handler must be:
|
||||||
|
@code void handler(
|
||||||
|
const boost::system::error_code& error, // Result of operation.
|
||||||
|
std::size_t bytes_transferred // Number of bytes written.
|
||||||
|
); @endcode
|
||||||
|
|
||||||
|
@note The `async_write_some` operation may not transmit all of the data to
|
||||||
|
the peer. Consider using the function `boost::asio::async_write` if you need
|
||||||
|
to ensure that all data is written before the asynchronous operation completes.
|
||||||
|
*/
|
||||||
|
template<class ConstBufferSequence, class WriteHandler>
|
||||||
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
|
WriteHandler, void(error_code, std::size_t))
|
||||||
|
async_write_some(ConstBufferSequence const& buffers,
|
||||||
|
WriteHandler&& handler);
|
||||||
|
|
||||||
|
#ifndef BOOST_BEAST_DOXYGEN
|
||||||
|
friend
|
||||||
|
void
|
||||||
|
teardown(
|
||||||
|
websocket::role_type,
|
||||||
|
stream& s,
|
||||||
|
boost::system::error_code& ec);
|
||||||
|
|
||||||
|
template<class TeardownHandler>
|
||||||
|
friend
|
||||||
|
void
|
||||||
|
async_teardown(
|
||||||
|
websocket::role_type role,
|
||||||
|
stream& s,
|
||||||
|
TeardownHandler&& handler);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Create and return a connected stream
|
||||||
|
stream
|
||||||
|
connect(stream& to);
|
||||||
|
|
||||||
|
/// Create and return a connected stream
|
||||||
|
template<class Arg1, class... ArgN>
|
||||||
|
stream
|
||||||
|
connect(stream& to, Arg1&& arg1, ArgN&&... argn);
|
||||||
|
|
||||||
|
} // test
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
#include <boost/beast/experimental/test/impl/stream.ipp>
|
||||||
|
|
||||||
|
#endif
|
@ -11,7 +11,7 @@
|
|||||||
#include <boost/beast/core/bind_handler.hpp>
|
#include <boost/beast/core/bind_handler.hpp>
|
||||||
|
|
||||||
#include <boost/beast/core/detail/type_traits.hpp>
|
#include <boost/beast/core/detail/type_traits.hpp>
|
||||||
#include <boost/beast/test/stream.hpp>
|
#include <boost/beast/experimental/test/stream.hpp>
|
||||||
#include <boost/beast/unit_test/suite.hpp>
|
#include <boost/beast/unit_test/suite.hpp>
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_service.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include <boost/beast/core/buffered_read_stream.hpp>
|
#include <boost/beast/core/buffered_read_stream.hpp>
|
||||||
|
|
||||||
#include <boost/beast/core/multi_buffer.hpp>
|
#include <boost/beast/core/multi_buffer.hpp>
|
||||||
#include <boost/beast/test/stream.hpp>
|
#include <boost/beast/experimental/test/stream.hpp>
|
||||||
#include <boost/beast/test/yield_to.hpp>
|
#include <boost/beast/test/yield_to.hpp>
|
||||||
#include <boost/beast/unit_test/suite.hpp>
|
#include <boost/beast/unit_test/suite.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
|
@ -20,6 +20,7 @@ add_executable (tests-beast-experimental
|
|||||||
error.cpp
|
error.cpp
|
||||||
flat_stream.cpp
|
flat_stream.cpp
|
||||||
ssl_stream.cpp
|
ssl_stream.cpp
|
||||||
|
stream.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set_property(TARGET tests-beast-experimental PROPERTY FOLDER "tests")
|
set_property(TARGET tests-beast-experimental PROPERTY FOLDER "tests")
|
||||||
|
@ -11,6 +11,7 @@ local SOURCES =
|
|||||||
error.cpp
|
error.cpp
|
||||||
flat_stream.cpp
|
flat_stream.cpp
|
||||||
ssl_stream.cpp
|
ssl_stream.cpp
|
||||||
|
stream.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
local RUN_TESTS ;
|
local RUN_TESTS ;
|
||||||
|
11
test/beast/experimental/stream.cpp
Normal file
11
test/beast/experimental/stream.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2016-2017 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
|
||||||
|
//
|
||||||
|
|
||||||
|
// Test that header file is self-contained.
|
||||||
|
#include <boost/beast/experimental/test/stream.hpp>
|
@ -16,7 +16,7 @@
|
|||||||
#include <boost/beast/http/parser.hpp>
|
#include <boost/beast/http/parser.hpp>
|
||||||
#include <boost/beast/http/read.hpp>
|
#include <boost/beast/http/read.hpp>
|
||||||
#include <boost/beast/http/write.hpp>
|
#include <boost/beast/http/write.hpp>
|
||||||
#include <boost/beast/test/stream.hpp>
|
#include <boost/beast/experimental/test/stream.hpp>
|
||||||
#include <boost/beast/unit_test/suite.hpp>
|
#include <boost/beast/unit_test/suite.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include <boost/beast/http/dynamic_body.hpp>
|
#include <boost/beast/http/dynamic_body.hpp>
|
||||||
#include <boost/beast/http/parser.hpp>
|
#include <boost/beast/http/parser.hpp>
|
||||||
#include <boost/beast/http/string_body.hpp>
|
#include <boost/beast/http/string_body.hpp>
|
||||||
#include <boost/beast/test/stream.hpp>
|
#include <boost/beast/experimental/test/stream.hpp>
|
||||||
#include <boost/beast/test/yield_to.hpp>
|
#include <boost/beast/test/yield_to.hpp>
|
||||||
#include <boost/beast/unit_test/suite.hpp>
|
#include <boost/beast/unit_test/suite.hpp>
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_service.hpp>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <boost/beast/core/buffers_to_string.hpp>
|
#include <boost/beast/core/buffers_to_string.hpp>
|
||||||
#include <boost/beast/core/error.hpp>
|
#include <boost/beast/core/error.hpp>
|
||||||
#include <boost/beast/core/multi_buffer.hpp>
|
#include <boost/beast/core/multi_buffer.hpp>
|
||||||
#include <boost/beast/test/stream.hpp>
|
#include <boost/beast/experimental/test/stream.hpp>
|
||||||
#include <boost/beast/test/yield_to.hpp>
|
#include <boost/beast/test/yield_to.hpp>
|
||||||
#include <boost/beast/unit_test/suite.hpp>
|
#include <boost/beast/unit_test/suite.hpp>
|
||||||
#include <boost/asio/error.hpp>
|
#include <boost/asio/error.hpp>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include <boost/beast/core/ostream.hpp>
|
#include <boost/beast/core/ostream.hpp>
|
||||||
#include <boost/beast/core/multi_buffer.hpp>
|
#include <boost/beast/core/multi_buffer.hpp>
|
||||||
#include <boost/beast/websocket/stream.hpp>
|
#include <boost/beast/websocket/stream.hpp>
|
||||||
#include <boost/beast/test/stream.hpp>
|
#include <boost/beast/experimental/test/stream.hpp>
|
||||||
#include <boost/beast/test/yield_to.hpp>
|
#include <boost/beast/test/yield_to.hpp>
|
||||||
#include <boost/beast/unit_test/suite.hpp>
|
#include <boost/beast/unit_test/suite.hpp>
|
||||||
#include <boost/asio/executor_work_guard.hpp>
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include <boost/beast/core/flat_buffer.hpp>
|
#include <boost/beast/core/flat_buffer.hpp>
|
||||||
#include <boost/beast/core/ostream.hpp>
|
#include <boost/beast/core/ostream.hpp>
|
||||||
#include <boost/beast/test/stream.hpp>
|
#include <boost/beast/experimental/test/stream.hpp>
|
||||||
#include <boost/beast/test/yield_to.hpp>
|
#include <boost/beast/test/yield_to.hpp>
|
||||||
#include <boost/beast/unit_test/suite.hpp>
|
#include <boost/beast/unit_test/suite.hpp>
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include <boost/beast/http/parser.hpp>
|
#include <boost/beast/http/parser.hpp>
|
||||||
#include <boost/beast/http/read.hpp>
|
#include <boost/beast/http/read.hpp>
|
||||||
#include <boost/beast/http/write.hpp>
|
#include <boost/beast/http/write.hpp>
|
||||||
#include <boost/beast/test/stream.hpp>
|
#include <boost/beast/experimental/test/stream.hpp>
|
||||||
#include <boost/beast/test/yield_to.hpp>
|
#include <boost/beast/test/yield_to.hpp>
|
||||||
#include <boost/beast/unit_test/suite.hpp>
|
#include <boost/beast/unit_test/suite.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#include <boost/beast/core/multi_buffer.hpp>
|
#include <boost/beast/core/multi_buffer.hpp>
|
||||||
#include <boost/beast/websocket/stream.hpp>
|
#include <boost/beast/websocket/stream.hpp>
|
||||||
#include <boost/beast/test/stream.hpp>
|
#include <boost/beast/experimental/test/stream.hpp>
|
||||||
#include <boost/asio/executor_work_guard.hpp>
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/spawn.hpp>
|
#include <boost/asio/spawn.hpp>
|
||||||
|
Reference in New Issue
Block a user