200 lines
5.4 KiB
C++
200 lines
5.4 KiB
C++
//
|
|
// 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 BOOST_BEAST_TEST_HANDLER_HPP
|
|
#define BOOST_BEAST_TEST_HANDLER_HPP
|
|
|
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
|
#include <boost/beast/core/error.hpp>
|
|
#include <boost/asio/io_context.hpp>
|
|
#include <boost/core/exchange.hpp>
|
|
#include <boost/optional.hpp>
|
|
|
|
namespace boost {
|
|
namespace beast {
|
|
namespace test {
|
|
|
|
/** A CompletionHandler used for testing.
|
|
|
|
This completion handler is used by tests to ensure correctness
|
|
of behavior. It is designed as a single type to reduce template
|
|
instantiations, with configurable settings through constructor
|
|
arguments. Typically this type will be used in type lists and
|
|
not instantiated directly; instances of this class are returned
|
|
by the helper functions listed below.
|
|
|
|
@see success_handler, @ref fail_handler, @ref any_handler
|
|
*/
|
|
class handler
|
|
{
|
|
boost::optional<error_code> ec_;
|
|
bool pass_ = false;
|
|
boost::source_location loc_{BOOST_CURRENT_LOCATION};
|
|
public:
|
|
handler(boost::source_location loc = BOOST_CURRENT_LOCATION) : loc_(loc) {}
|
|
|
|
explicit
|
|
handler(error_code ec, boost::source_location loc = BOOST_CURRENT_LOCATION)
|
|
: ec_(ec), loc_(loc)
|
|
{
|
|
}
|
|
|
|
explicit
|
|
handler(boost::none_t, boost::source_location loc = BOOST_CURRENT_LOCATION) : loc_(loc)
|
|
{
|
|
}
|
|
|
|
handler(handler&& other)
|
|
: ec_(other.ec_)
|
|
, pass_(boost::exchange(other.pass_, true))
|
|
, loc_(other.loc_)
|
|
|
|
{
|
|
}
|
|
|
|
~handler()
|
|
{
|
|
::boost::beast::unit_test::suite::this_suite()->expect(pass_, loc_.file_name(), loc_.line());
|
|
}
|
|
|
|
template<class... Args>
|
|
void
|
|
operator()(error_code ec, Args&&...)
|
|
{
|
|
::boost::beast::unit_test::suite::this_suite()->expect(!pass_, loc_.file_name(), loc_.line());
|
|
if (ec_ && ec != *ec_)
|
|
::boost::beast::unit_test::suite::this_suite()->fail(ec.message(), loc_.file_name(), loc_.line());
|
|
else
|
|
::boost::beast::unit_test::suite::this_suite()->pass();
|
|
pass_ = true;
|
|
}
|
|
|
|
void
|
|
operator()()
|
|
{
|
|
::boost::beast::unit_test::suite::this_suite()->expect(!pass_, loc_.file_name(), loc_.line());
|
|
if (ec_ && ec_->failed())
|
|
::boost::beast::unit_test::suite::this_suite()->fail(ec_->message(), loc_.file_name(), loc_.line());
|
|
else
|
|
::boost::beast::unit_test::suite::this_suite()->pass();
|
|
|
|
pass_ = true;
|
|
}
|
|
|
|
template<class Arg0, class... Args,
|
|
class = typename std::enable_if<
|
|
! std::is_convertible<Arg0, error_code>::value>::type>
|
|
void
|
|
operator()(Arg0&&, Args&&...)
|
|
{
|
|
::boost::beast::unit_test::suite::this_suite()->expect(!pass_, loc_.file_name(), loc_.line());
|
|
if (ec_ && ec_->failed())
|
|
::boost::beast::unit_test::suite::this_suite()->fail(ec_->message(), loc_.file_name(), loc_.line());
|
|
else
|
|
::boost::beast::unit_test::suite::this_suite()->pass();
|
|
pass_ = true;
|
|
}
|
|
};
|
|
|
|
/** Return a test CompletionHandler which requires success.
|
|
|
|
The returned handler can be invoked with any signature whose
|
|
first parameter is an `error_code`. The handler fails the test
|
|
if:
|
|
|
|
@li The handler is destroyed without being invoked, or
|
|
|
|
@li The handler is invoked with a non-successful error code.
|
|
*/
|
|
inline
|
|
handler
|
|
success_handler(boost::source_location loc = BOOST_CURRENT_LOCATION) noexcept
|
|
{
|
|
return handler(error_code{}, loc);
|
|
}
|
|
|
|
/** Return a test CompletionHandler which requires invocation.
|
|
|
|
The returned handler can be invoked with any signature.
|
|
The handler fails the test if:
|
|
|
|
@li The handler is destroyed without being invoked.
|
|
*/
|
|
inline
|
|
handler
|
|
any_handler(boost::source_location loc = BOOST_CURRENT_LOCATION) noexcept
|
|
{
|
|
return handler(boost::none, loc);
|
|
}
|
|
|
|
/** Return a test CompletionHandler which requires a specific error code.
|
|
|
|
This handler can be invoked with any signature whose first
|
|
parameter is an `error_code`. The handler fails the test if:
|
|
|
|
@li The handler is destroyed without being invoked.
|
|
|
|
@li The handler is invoked with an error code different from
|
|
what is specified.
|
|
|
|
@param ec The error code to specify.
|
|
*/
|
|
inline
|
|
handler
|
|
fail_handler(error_code ec,boost::source_location loc = BOOST_CURRENT_LOCATION) noexcept
|
|
{
|
|
return handler(ec, loc);
|
|
}
|
|
|
|
/** Run an I/O context.
|
|
|
|
This function runs and dispatches handlers on the specified
|
|
I/O context, until one of the following conditions is true:
|
|
|
|
@li The I/O context runs out of work.
|
|
|
|
@param ioc The I/O context to run
|
|
*/
|
|
inline
|
|
void
|
|
run(net::io_context& ioc)
|
|
{
|
|
ioc.run();
|
|
ioc.restart();
|
|
}
|
|
|
|
/** Run an I/O context for a certain amount of time.
|
|
|
|
This function runs and dispatches handlers on the specified
|
|
I/O context, until one of the following conditions is true:
|
|
|
|
@li The I/O context runs out of work.
|
|
|
|
@li No completions occur and the specified amount of time has elapsed.
|
|
|
|
@param ioc The I/O context to run
|
|
|
|
@param elapsed The maximum amount of time to run for.
|
|
*/
|
|
template<class Rep, class Period>
|
|
void
|
|
run_for(
|
|
net::io_context& ioc,
|
|
std::chrono::duration<Rep, Period> elapsed)
|
|
{
|
|
ioc.run_for(elapsed);
|
|
ioc.restart();
|
|
}
|
|
|
|
} // test
|
|
} // beast
|
|
} // boost
|
|
|
|
#endif
|