// // 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 #include #include #include #include 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 ec_; bool pass_ = false; public: handler() = default; explicit handler(error_code ec) : ec_(ec) { } explicit handler(boost::none_t) { } handler(handler&& other) : ec_(other.ec_) , pass_(boost::exchange(other.pass_, true)) { } ~handler() { BEAST_EXPECT(pass_); } template void operator()(error_code ec, Args&&...) { BEAST_EXPECT(! pass_); // can't call twice BEAST_EXPECTS(! ec_ || ec == *ec_, ec.message()); pass_ = true; } void operator()() { BEAST_EXPECT(! pass_); // can't call twice BEAST_EXPECT(! ec_); pass_ = true; } template::value>::type> void operator()(Arg0&&, Args&&...) { BEAST_EXPECT(! pass_); // can't call twice BEAST_EXPECT(! ec_); 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() noexcept { return handler(error_code{}); } /** 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() noexcept { return handler(boost::none); } /** 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) noexcept { return handler(ec); } /** 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 void run_for( net::io_context& ioc, std::chrono::duration elapsed) { ioc.run_for(elapsed); ioc.restart(); } } // test } // beast } // boost #endif