handler.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_TEST_HANDLER_HPP
  10. #define BOOST_BEAST_TEST_HANDLER_HPP
  11. #include <boost/beast/_experimental/unit_test/suite.hpp>
  12. #include <boost/beast/core/error.hpp>
  13. #include <boost/asio/io_context.hpp>
  14. #include <boost/core/exchange.hpp>
  15. #include <boost/optional.hpp>
  16. namespace boost {
  17. namespace beast {
  18. namespace test {
  19. /** A CompletionHandler used for testing.
  20. This completion handler is used by tests to ensure correctness
  21. of behavior. It is designed as a single type to reduce template
  22. instantiations, with configurable settings through constructor
  23. arguments. Typically this type will be used in type lists and
  24. not instantiated directly; instances of this class are returned
  25. by the helper functions listed below.
  26. @see success_handler, @ref fail_handler, @ref any_handler
  27. */
  28. class handler
  29. {
  30. boost::optional<error_code> ec_;
  31. bool pass_ = false;
  32. boost::source_location loc_{BOOST_CURRENT_LOCATION};
  33. public:
  34. handler(boost::source_location loc = BOOST_CURRENT_LOCATION) : loc_(loc) {}
  35. explicit
  36. handler(error_code ec, boost::source_location loc = BOOST_CURRENT_LOCATION)
  37. : ec_(ec), loc_(loc)
  38. {
  39. }
  40. explicit
  41. handler(boost::none_t, boost::source_location loc = BOOST_CURRENT_LOCATION) : loc_(loc)
  42. {
  43. }
  44. handler(handler&& other)
  45. : ec_(other.ec_)
  46. , pass_(boost::exchange(other.pass_, true))
  47. , loc_(other.loc_)
  48. {
  49. }
  50. ~handler()
  51. {
  52. ::boost::beast::unit_test::suite::this_suite()->expect(pass_, loc_.file_name(), loc_.line());
  53. }
  54. template<class... Args>
  55. void
  56. operator()(error_code ec, Args&&...)
  57. {
  58. ::boost::beast::unit_test::suite::this_suite()->expect(!pass_, loc_.file_name(), loc_.line());
  59. if (ec_ && ec != *ec_)
  60. ::boost::beast::unit_test::suite::this_suite()->fail(ec.message(), loc_.file_name(), loc_.line());
  61. else
  62. ::boost::beast::unit_test::suite::this_suite()->pass();
  63. pass_ = true;
  64. }
  65. void
  66. operator()()
  67. {
  68. ::boost::beast::unit_test::suite::this_suite()->expect(!pass_, loc_.file_name(), loc_.line());
  69. if (ec_ && ec_->failed())
  70. ::boost::beast::unit_test::suite::this_suite()->fail(ec_->message(), loc_.file_name(), loc_.line());
  71. else
  72. ::boost::beast::unit_test::suite::this_suite()->pass();
  73. pass_ = true;
  74. }
  75. template<class Arg0, class... Args,
  76. class = typename std::enable_if<
  77. ! std::is_convertible<Arg0, error_code>::value>::type>
  78. void
  79. operator()(Arg0&&, Args&&...)
  80. {
  81. ::boost::beast::unit_test::suite::this_suite()->expect(!pass_, loc_.file_name(), loc_.line());
  82. if (ec_ && ec_->failed())
  83. ::boost::beast::unit_test::suite::this_suite()->fail(ec_->message(), loc_.file_name(), loc_.line());
  84. else
  85. ::boost::beast::unit_test::suite::this_suite()->pass();
  86. pass_ = true;
  87. }
  88. };
  89. /** Return a test CompletionHandler which requires success.
  90. The returned handler can be invoked with any signature whose
  91. first parameter is an `error_code`. The handler fails the test
  92. if:
  93. @li The handler is destroyed without being invoked, or
  94. @li The handler is invoked with a non-successful error code.
  95. */
  96. inline
  97. handler
  98. success_handler(boost::source_location loc = BOOST_CURRENT_LOCATION) noexcept
  99. {
  100. return handler(error_code{}, loc);
  101. }
  102. /** Return a test CompletionHandler which requires invocation.
  103. The returned handler can be invoked with any signature.
  104. The handler fails the test if:
  105. @li The handler is destroyed without being invoked.
  106. */
  107. inline
  108. handler
  109. any_handler(boost::source_location loc = BOOST_CURRENT_LOCATION) noexcept
  110. {
  111. return handler(boost::none, loc);
  112. }
  113. /** Return a test CompletionHandler which requires a specific error code.
  114. This handler can be invoked with any signature whose first
  115. parameter is an `error_code`. The handler fails the test if:
  116. @li The handler is destroyed without being invoked.
  117. @li The handler is invoked with an error code different from
  118. what is specified.
  119. @param ec The error code to specify.
  120. */
  121. inline
  122. handler
  123. fail_handler(error_code ec,boost::source_location loc = BOOST_CURRENT_LOCATION) noexcept
  124. {
  125. return handler(ec, loc);
  126. }
  127. /** Run an I/O context.
  128. This function runs and dispatches handlers on the specified
  129. I/O context, until one of the following conditions is true:
  130. @li The I/O context runs out of work.
  131. @param ioc The I/O context to run
  132. */
  133. inline
  134. void
  135. run(net::io_context& ioc)
  136. {
  137. ioc.run();
  138. ioc.restart();
  139. }
  140. /** Run an I/O context for a certain amount of time.
  141. This function runs and dispatches handlers on the specified
  142. I/O context, until one of the following conditions is true:
  143. @li The I/O context runs out of work.
  144. @li No completions occur and the specified amount of time has elapsed.
  145. @param ioc The I/O context to run
  146. @param elapsed The maximum amount of time to run for.
  147. */
  148. template<class Rep, class Period>
  149. void
  150. run_for(
  151. net::io_context& ioc,
  152. std::chrono::duration<Rep, Period> elapsed)
  153. {
  154. ioc.run_for(elapsed);
  155. ioc.restart();
  156. }
  157. } // test
  158. } // beast
  159. } // boost
  160. #endif