Files
boost_beast/test/beast/core/test_handler.hpp
2021-12-09 14:27:18 +01:00

247 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_XXX_HPP
#define BOOST_BEAST_TEST_HANDLER_XXX_HPP
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/_experimental/unit_test/suite.hpp>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/handler_alloc_hook.hpp>
#include <boost/asio/handler_continuation_hook.hpp>
#include <boost/asio/handler_invoke_hook.hpp>
namespace boost {
namespace beast {
class simple_allocator
{
std::size_t id_;
public:
simple_allocator()
: id_([]
{
static std::size_t n = 0;
return ++n;
}())
{
}
friend
bool operator==(
simple_allocator const& lhs,
simple_allocator const& rhs) noexcept
{
return lhs.id_ == rhs.id_;
}
friend
bool operator!=(
simple_allocator const& lhs,
simple_allocator const& rhs) noexcept
{
return lhs.id_ != rhs.id_;
}
};
class simple_executor
{
std::size_t id_;
public:
simple_executor() noexcept
: id_([]
{
static std::size_t n = 0;
return ++n;
}())
{
}
#if defined(BOOST_ASIO_NO_TS_EXECUTORS)
void* query(net::execution::context_t) const { return nullptr; }
template<class F>
void execute(F&&) const {}
simple_executor prefer(net::execution::outstanding_work_t::tracked_t) const { return *this; }
#else
void* context() { return nullptr; }
void on_work_started() {}
void on_work_finished() {}
template<class F> void dispatch(F&&) {}
template<class F> void post(F&&) {}
template<class F> void defer(F&&) {}
#endif
friend
bool operator==(
simple_executor const& lhs,
simple_executor const& rhs) noexcept
{
return lhs.id_ == rhs.id_;
}
friend
bool operator!=(
simple_executor const& lhs,
simple_executor const& rhs) noexcept
{
return lhs.id_ != rhs.id_;
}
};
#if defined(BOOST_ASIO_NO_TS_EXECUTORS)
BOOST_STATIC_ASSERT(net::execution::is_executor<simple_executor>::value);
#endif
// A move-only handler
struct move_only_handler
{
move_only_handler() = default;
move_only_handler(move_only_handler&&) = default;
move_only_handler(move_only_handler const&) = delete;
void operator()() const{};
};
// Used to test the legacy handler hooks
struct legacy_handler
{
bool& hook_invoked;
simple_executor
get_executor() const noexcept
{
return {};
};
// Signature of `f` is H<legacy_handler> where H is the wrapper to test
template<class F>
static
void
test(F const& f)
{
#if !defined(BOOST_ASIO_NO_DEPRECATED)
{
bool hook_invoked = false;
bool lambda_invoked = false;
auto h = f(legacy_handler{hook_invoked});
using net::asio_handler_invoke;
asio_handler_invoke(
[&lambda_invoked]
{
lambda_invoked =true;
}, &h);
BEAST_EXPECT(hook_invoked);
BEAST_EXPECT(lambda_invoked);
}
{
bool hook_invoked = false;
auto h = f(legacy_handler{hook_invoked});
using net::asio_handler_allocate;
asio_handler_allocate(0, &h);
BEAST_EXPECT(hook_invoked);
}
{
bool hook_invoked = false;
auto h = f(legacy_handler{hook_invoked});
using net::asio_handler_deallocate;
asio_handler_deallocate(nullptr, 0, &h);
BEAST_EXPECT(hook_invoked);
}
{
bool hook_invoked = false;
auto h = f(legacy_handler{hook_invoked});
using net::asio_handler_is_continuation;
asio_handler_is_continuation(&h);
BEAST_EXPECT(hook_invoked);
}
#else // !defined(BOOST_ASIO_NO_DEPRECATED)
boost::ignore_unused(f);
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
}
};
template<class Function>
void
asio_handler_invoke(
Function&& f,
legacy_handler* p)
{
p->hook_invoked = true;
f();
}
inline
void*
asio_handler_allocate(
std::size_t,
legacy_handler* p)
{
p->hook_invoked = true;
return nullptr;
}
inline
void
asio_handler_deallocate(
void*, std::size_t,
legacy_handler* p)
{
p->hook_invoked = true;
}
inline
bool
asio_handler_is_continuation(
legacy_handler* p)
{
p->hook_invoked = true;
return false;
}
} // beast
} // boost
namespace boost {
namespace asio {
template<class Allocator>
struct associated_allocator<
boost::beast::legacy_handler, Allocator>
{
using type = std::allocator<int>;
static type get(
boost::beast::legacy_handler const&,
Allocator const& = Allocator()) noexcept
{
return type{};
}
};
template<class Executor>
struct associated_executor<
boost::beast::legacy_handler, Executor>
{
using type = boost::beast::simple_executor;
static type get(
boost::beast::legacy_handler const&,
Executor const& = Executor()) noexcept
{
return type{};
}
};
} // asio
} // boost
#endif