mirror of
https://github.com/QuasarApp/qthttpserver.git
synced 2025-05-12 17:39:43 +00:00
QHttpServerRouterViewTraits: Make it simpler and testable
Currently QHttpServerRouterViewTraits contains all helpers and tools inside itself. It is hard to read and extend. This patch: - Moves all helper and tools to QtPrivate namespace - Tries to "simplify" template magic - Adds support for unit test Change-Id: I6aa443b286c4c896b8dbfee85fffb638328868ad Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
52bce52413
commit
3eebefcd27
src/httpserver
tests/auto/qhttpserverrouter
@ -68,7 +68,7 @@ public:
|
||||
{
|
||||
using ViewHandler = typename VariadicTypeLast<Args...>::Type;
|
||||
using ViewTraits = QHttpServerRouterViewTraits<ViewHandler>;
|
||||
static_assert(ViewTraits::Arguments::compileCheck(),
|
||||
static_assert(ViewTraits::Arguments::StaticAssert,
|
||||
"ViewHandler arguments are in the wrong order or not supported");
|
||||
return routeHelper<Rule, ViewHandler, ViewTraits>(
|
||||
QtPrivate::makeIndexSequence<sizeof ... (Args) - 1>{},
|
||||
@ -102,7 +102,7 @@ private:
|
||||
}
|
||||
|
||||
template<typename ViewTraits, typename T>
|
||||
typename std::enable_if<ViewTraits::IsLastArgNonSpecial, void>::type
|
||||
typename std::enable_if<!ViewTraits::Arguments::Last::IsSpecial::Value, void>::type
|
||||
responseImpl(T &boundViewHandler,
|
||||
const QHttpServerRequest &request,
|
||||
QTcpSocket *socket)
|
||||
@ -112,7 +112,7 @@ private:
|
||||
}
|
||||
|
||||
template<typename ViewTraits, typename T>
|
||||
typename std::enable_if<ViewTraits::IsLastArgRequest, void>::type
|
||||
typename std::enable_if<ViewTraits::Arguments::Last::IsRequest::Value, void>::type
|
||||
responseImpl(T &boundViewHandler, const QHttpServerRequest &request, QTcpSocket *socket)
|
||||
{
|
||||
const QHttpServerResponse response(boundViewHandler(request));
|
||||
@ -120,7 +120,7 @@ private:
|
||||
}
|
||||
|
||||
template<typename ViewTraits, typename T>
|
||||
typename std::enable_if<ViewTraits::IsLastArgResponder, void>::type
|
||||
typename std::enable_if<ViewTraits::Arguments::Last::IsResponder::Value, void>::type
|
||||
responseImpl(T &boundViewHandler,
|
||||
const QHttpServerRequest &request,
|
||||
QTcpSocket *socket)
|
||||
|
@ -97,7 +97,7 @@ public:
|
||||
{
|
||||
return addRuleHelper<ViewTraits>(
|
||||
rule,
|
||||
typename QtPrivate::Indexes<ViewTraits::ArgumentCount>::Value{});
|
||||
typename ViewTraits::Arguments::Indexes{});
|
||||
}
|
||||
|
||||
template<typename ViewHandler, typename ViewTraits = QHttpServerRouterViewTraits<ViewHandler>>
|
||||
@ -107,8 +107,8 @@ public:
|
||||
return bindCapturedImpl<ViewHandler, ViewTraits>(
|
||||
std::forward<ViewHandler>(handler),
|
||||
match,
|
||||
typename QtPrivate::Indexes<ViewTraits::ArgumentCapturableCount>::Value{},
|
||||
typename QtPrivate::Indexes<ViewTraits::ArgumentPlaceholdersCount>::Value{});
|
||||
typename ViewTraits::Arguments::CapturableIndexes{},
|
||||
typename ViewTraits::Arguments::PlaceholdersIndexes{});
|
||||
}
|
||||
|
||||
bool handleRequest(const QHttpServerRequest &request,
|
||||
@ -119,7 +119,8 @@ private:
|
||||
bool addRuleHelper(QHttpServerRouterRule *rule,
|
||||
QtPrivate::IndexesList<Idx...>)
|
||||
{
|
||||
const std::initializer_list<int> types = {ViewTraits::template Arg<Idx>::metaTypeId()...};
|
||||
const std::initializer_list<int> types = {
|
||||
ViewTraits::Arguments::template metaTypeId<Idx>()...};
|
||||
return addRuleImpl(rule, types);
|
||||
}
|
||||
|
||||
@ -135,7 +136,8 @@ private:
|
||||
|
||||
return std::bind(
|
||||
std::forward<ViewHandler>(handler),
|
||||
QVariant(match.captured(Cx + 1)).value<typename ViewTraits::template Arg<Cx>::Type>()...,
|
||||
QVariant(match.captured(Cx + 1))
|
||||
.value<typename ViewTraits::Arguments::template Arg<Cx>::CleanType>()...,
|
||||
QtPrivate::QHttpServerRouterPlaceholder<Px>{}...);
|
||||
}
|
||||
|
||||
|
@ -44,181 +44,289 @@ QT_BEGIN_NAMESPACE
|
||||
class QHttpServerRequest;
|
||||
class QHttpServerResponder;
|
||||
|
||||
template <typename ViewHandler>
|
||||
struct QHttpServerRouterViewTraits : QHttpServerRouterViewTraits<decltype(&ViewHandler::operator())> {};
|
||||
namespace QtPrivate {
|
||||
|
||||
template <typename ClassType, typename Ret, typename ... Args>
|
||||
struct QHttpServerRouterViewTraits<Ret(ClassType::*)(Args...) const>
|
||||
template<typename T>
|
||||
struct RemoveCVRef
|
||||
{
|
||||
static constexpr const int ArgumentCount = sizeof ... (Args);
|
||||
|
||||
template <int I>
|
||||
struct Arg {
|
||||
using OriginalType = typename std::tuple_element<I, std::tuple<Args...>>::type;
|
||||
using Type = typename QtPrivate::RemoveConstRef<OriginalType>::Type;
|
||||
|
||||
static constexpr int metaTypeId() noexcept {
|
||||
return qMetaTypeId<
|
||||
typename std::conditional<
|
||||
!QMetaTypeId2<Type>::Defined,
|
||||
void,
|
||||
Type>::type>();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
// Tools used to check position of special arguments (QHttpServerResponder, QHttpServerRequest)
|
||||
// and unsupported types
|
||||
template<bool Last, typename Arg>
|
||||
static constexpr bool checkArgument() noexcept
|
||||
{
|
||||
static_assert(Last || !std::is_same<Arg, const QHttpServerRequest &>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be the last argument");
|
||||
static_assert(Last || !std::is_same<Arg, QHttpServerResponder &&>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be the last argument");
|
||||
|
||||
static_assert(!std::is_same<Arg, QHttpServerRequest &&>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be passed as a const reference");
|
||||
static_assert(!std::is_same<Arg, QHttpServerRequest &>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be passed as a const reference");
|
||||
static_assert(!std::is_same<Arg, const QHttpServerRequest *>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be passed as a const reference");
|
||||
static_assert(!std::is_same<Arg, QHttpServerRequest const*>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be passed as a const reference");
|
||||
static_assert(!std::is_same<Arg, QHttpServerRequest *>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be passed as a const reference");
|
||||
|
||||
static_assert(!std::is_same<Arg, QHttpServerResponder &>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be passed as a universal reference");
|
||||
static_assert(!std::is_same<Arg, const QHttpServerResponder *const>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be passed as a universal reference");
|
||||
static_assert(!std::is_same<Arg, const QHttpServerResponder *>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be passed as a universal reference");
|
||||
static_assert(!std::is_same<Arg, QHttpServerResponder const*>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be passed as a universal reference");
|
||||
static_assert(!std::is_same<Arg, QHttpServerResponder *>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be passed as a universal reference");
|
||||
|
||||
using Type = typename std::remove_cv<typename std::remove_reference<Arg>::type>::type;
|
||||
|
||||
static_assert(QMetaTypeId2<Type>::Defined
|
||||
|| std::is_same<Type, QHttpServerResponder>::value
|
||||
|| std::is_same<Type, QHttpServerRequest>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"Type is not registered, please use the Q_DECLARE_METATYPE macro "
|
||||
"to make it known to Qt's meta-object system");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename Arg, typename ... ArgX>
|
||||
struct ArgumentsCheck {
|
||||
static constexpr bool compileCheck()
|
||||
{
|
||||
return checkArgument<false, Arg>() && ArgumentsCheck<ArgX...>::compileCheck();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Arg>
|
||||
struct ArgumentsCheck<Arg> {
|
||||
static constexpr bool compileCheck()
|
||||
{
|
||||
return checkArgument<true, Arg>();
|
||||
}
|
||||
};
|
||||
|
||||
using Arguments = ArgumentsCheck<Args...>;
|
||||
|
||||
private:
|
||||
// Tools used to compute ArgumentCapturableCount
|
||||
template<typename T>
|
||||
static constexpr typename std::enable_if<QMetaTypeId2<T>::Defined, int>::type
|
||||
capturable()
|
||||
{ return 1; }
|
||||
|
||||
template<typename T>
|
||||
static constexpr typename std::enable_if<!QMetaTypeId2<T>::Defined, int>::type
|
||||
capturable()
|
||||
{ return 0; }
|
||||
|
||||
static constexpr std::size_t sum() noexcept { return 0; }
|
||||
|
||||
template<typename ... N>
|
||||
static constexpr std::size_t sum(const std::size_t it, N ... n) noexcept
|
||||
{ return it + sum(n...); }
|
||||
|
||||
public:
|
||||
static constexpr const std::size_t ArgumentCapturableCount =
|
||||
sum(capturable<typename QtPrivate::RemoveConstRef<Args>::Type>()...);
|
||||
static constexpr const std::size_t ArgumentPlaceholdersCount = ArgumentCount
|
||||
- ArgumentCapturableCount;
|
||||
|
||||
private:
|
||||
// Tools used to get BindableType
|
||||
template<typename Return, typename ... ArgsX>
|
||||
struct BindTypeHelper {
|
||||
using Type = std::function<Return(ArgsX...)>;
|
||||
};
|
||||
|
||||
template<int ... Idx>
|
||||
static constexpr typename BindTypeHelper<
|
||||
Ret, typename Arg<ArgumentCapturableCount + Idx>::OriginalType...>::Type
|
||||
bindTypeHelper(QtPrivate::IndexesList<Idx...>)
|
||||
{
|
||||
return BindTypeHelper<Ret,
|
||||
typename Arg<ArgumentCapturableCount + Idx>::OriginalType...>::Type();
|
||||
}
|
||||
|
||||
public:
|
||||
using BindableType = decltype(bindTypeHelper(typename QtPrivate::Indexes<
|
||||
ArgumentPlaceholdersCount>::Value{}));
|
||||
|
||||
static constexpr bool IsLastArgRequest = std::is_same<
|
||||
typename Arg<ArgumentCount - 1>::Type, QHttpServerRequest>::value;
|
||||
|
||||
static constexpr bool IsLastArgResponder = std::is_same<
|
||||
typename Arg<ArgumentCount - 1>::Type, QHttpServerResponder&&>::value;
|
||||
|
||||
static constexpr bool IsLastArgNonSpecial = !(IsLastArgRequest || IsLastArgResponder);
|
||||
using Type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
|
||||
};
|
||||
|
||||
template <typename ClassType, typename Ret>
|
||||
struct QHttpServerRouterViewTraits<Ret(ClassType::*)() const>
|
||||
|
||||
template<bool classMember, typename ReturnT, typename ... Args>
|
||||
struct FunctionTraitsHelper
|
||||
{
|
||||
static constexpr const int ArgumentCount = 0;
|
||||
static constexpr const int ArgumentCount = sizeof ... (Args);
|
||||
static constexpr const int ArgumentIndexMax = ArgumentCount - 1;
|
||||
static constexpr const bool IsClassMember = classMember;
|
||||
using ReturnType = ReturnT;
|
||||
|
||||
template <int I>
|
||||
struct Arg {
|
||||
using Type = void;
|
||||
using Type = typename std::tuple_element<I, std::tuple<Args...>>::type;
|
||||
|
||||
using CleanType = typename QtPrivate::RemoveCVRef<Type>::Type;
|
||||
|
||||
static constexpr bool Defined = QMetaTypeId2<CleanType>::Defined;
|
||||
};
|
||||
};
|
||||
|
||||
template<bool classMember, typename ReturnT>
|
||||
struct FunctionTraitsHelper<classMember, ReturnT>
|
||||
{
|
||||
static constexpr const int ArgumentCount = 0;
|
||||
static constexpr const int ArgumentIndexMax = -1;
|
||||
static constexpr const bool IsClassMember = classMember;
|
||||
using ReturnType = ReturnT;
|
||||
|
||||
template <int I>
|
||||
struct Arg {
|
||||
using Type = std::false_type;
|
||||
using CleanType = Type;
|
||||
static constexpr bool Defined = QMetaTypeId2<CleanType>::Defined;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct FunctionTraits;
|
||||
|
||||
template<typename T>
|
||||
struct FunctionTraits : public FunctionTraits<decltype(&T::operator())>{};
|
||||
|
||||
template<typename ReturnT, typename ... Args>
|
||||
struct FunctionTraits<ReturnT (*)(Args...)>
|
||||
: public FunctionTraitsHelper<false, ReturnT, Args...>
|
||||
{
|
||||
};
|
||||
|
||||
template<class ReturnT, class ClassT, class ...Args>
|
||||
struct FunctionTraits<ReturnT (ClassT::*)(Args...) const>
|
||||
: public FunctionTraitsHelper<true, ReturnT, Args...>
|
||||
{
|
||||
using classType = ClassT;
|
||||
};
|
||||
|
||||
template<typename ViewHandler, bool DisableStaticAssert>
|
||||
struct ViewTraitsHelper {
|
||||
using FunctionTraits = typename QtPrivate::FunctionTraits<ViewHandler>;
|
||||
using ArgumentIndexes = typename QtPrivate::Indexes<FunctionTraits::ArgumentCount>::Value;
|
||||
|
||||
struct StaticMath {
|
||||
template <template<typename> class Predicate, bool defaultValue>
|
||||
struct Loop {
|
||||
static constexpr bool eval() noexcept {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
template<typename T, typename ... N>
|
||||
static constexpr T eval(const T it, N ...n) noexcept {
|
||||
return Predicate<T>::eval(it, eval(n...));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct SumPredicate {
|
||||
static constexpr T eval(const T rs, const T ls) noexcept
|
||||
{
|
||||
return rs + ls;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct AndPredicate {
|
||||
static constexpr T eval(const T rs, const T ls) noexcept
|
||||
{
|
||||
return rs && ls;
|
||||
}
|
||||
};
|
||||
|
||||
using Sum = Loop<SumPredicate, false>;
|
||||
using And = Loop<AndPredicate, true>;
|
||||
using Or = Sum;
|
||||
};
|
||||
|
||||
static constexpr const std::size_t ArgumentCapturableCount = 0u;
|
||||
static constexpr const std::size_t ArgumentPlaceholdersCount = 0u;
|
||||
struct Arguments {
|
||||
template<int I>
|
||||
struct StaticCheck {
|
||||
using Arg = typename FunctionTraits::template Arg<I>;
|
||||
using CleanType = typename Arg::CleanType;
|
||||
|
||||
using BindableType = decltype(std::function<Ret()>{});
|
||||
template<typename T, bool Clean = false>
|
||||
static constexpr bool isType() noexcept
|
||||
{
|
||||
using SelectedType =
|
||||
typename std::conditional<
|
||||
Clean,
|
||||
CleanType,
|
||||
typename Arg::Type
|
||||
>::type;
|
||||
return std::is_same<SelectedType, T>::value;
|
||||
}
|
||||
|
||||
static constexpr bool IsLastArgRequest = false;
|
||||
static constexpr bool IsLastArgResponder = false;
|
||||
static constexpr bool IsLastArgNonSpecial = true;
|
||||
template<typename T>
|
||||
struct SpecialHelper {
|
||||
using CleanTypeT = typename QtPrivate::RemoveCVRef<T>::Type;
|
||||
|
||||
struct ArgumentsCheck {
|
||||
static constexpr bool compileCheck() { return true; }
|
||||
static constexpr bool TypeMatched = isType<CleanTypeT, true>();
|
||||
static constexpr bool TypeCVRefMatched = isType<T>();
|
||||
static constexpr bool ValidPosition =
|
||||
(I == FunctionTraits::ArgumentIndexMax);
|
||||
static constexpr bool ValidAll = TypeCVRefMatched && ValidPosition;
|
||||
|
||||
static constexpr bool assertCondition =
|
||||
DisableStaticAssert || !TypeMatched || TypeCVRefMatched;
|
||||
|
||||
static constexpr bool assertConditionOrder =
|
||||
DisableStaticAssert || !TypeMatched || ValidPosition;
|
||||
|
||||
static constexpr bool staticAssert() noexcept
|
||||
{
|
||||
static_assert(assertConditionOrder,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest or QHttpServerResponder"
|
||||
" can only be the last argument");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ... T>
|
||||
struct CheckAny {
|
||||
static constexpr bool Value = StaticMath::Or::eval(T::Value...);
|
||||
static constexpr bool Valid = StaticMath::Or::eval(T::Valid...);
|
||||
static constexpr bool staticAssert() noexcept
|
||||
{
|
||||
return StaticMath::Or::eval(T::staticAssert()...);
|
||||
}
|
||||
};
|
||||
|
||||
struct IsRequest {
|
||||
using Helper = SpecialHelper<const QHttpServerRequest &>;
|
||||
static constexpr bool Value = Helper::TypeMatched;
|
||||
static constexpr bool Valid = Helper::ValidAll;
|
||||
|
||||
static constexpr bool staticAssert() noexcept
|
||||
{
|
||||
static_assert(Helper::assertCondition,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be passed as a const reference");
|
||||
return Helper::staticAssert();
|
||||
}
|
||||
};
|
||||
|
||||
struct IsResponder {
|
||||
using Helper = SpecialHelper<QHttpServerResponder &&>;
|
||||
static constexpr bool Value = Helper::TypeMatched;
|
||||
static constexpr bool Valid = Helper::ValidAll;
|
||||
|
||||
static constexpr bool staticAssert() noexcept
|
||||
{
|
||||
static_assert(Helper::assertCondition,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be passed as a universal reference");
|
||||
return Helper::staticAssert();
|
||||
}
|
||||
};
|
||||
|
||||
using IsSpecial = CheckAny<IsRequest, IsResponder>;
|
||||
|
||||
struct IsSimple {
|
||||
static constexpr bool Value = !IsSpecial::Value &&
|
||||
I < FunctionTraits::ArgumentCount &&
|
||||
FunctionTraits::ArgumentIndexMax != -1;
|
||||
static constexpr bool Valid = Arg::Defined;
|
||||
|
||||
static constexpr bool assertCondition =
|
||||
DisableStaticAssert || !Value || Valid;
|
||||
|
||||
static constexpr bool staticAssert() noexcept
|
||||
{
|
||||
static_assert(assertCondition,
|
||||
"ViewHandler arguments error: "
|
||||
"Type is not registered, please use the Q_DECLARE_METATYPE macro "
|
||||
"to make it known to Qt's meta-object system");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
using CheckOk = CheckAny<IsSimple, IsSpecial>;
|
||||
|
||||
static constexpr bool Valid = CheckOk::Valid;
|
||||
static constexpr bool StaticAssert = CheckOk::staticAssert();
|
||||
};
|
||||
|
||||
template<int ... I>
|
||||
struct ArgumentsReturn {
|
||||
template<int Idx>
|
||||
using Arg = StaticCheck<Idx>;
|
||||
|
||||
template<int Idx>
|
||||
static constexpr int metaTypeId() noexcept
|
||||
{
|
||||
using Type = typename FunctionTraits::template Arg<Idx>::CleanType;
|
||||
|
||||
return qMetaTypeId<
|
||||
typename std::conditional<
|
||||
QMetaTypeId2<Type>::Defined,
|
||||
Type,
|
||||
void>::type>();
|
||||
}
|
||||
|
||||
static constexpr std::size_t Count = FunctionTraits::ArgumentCount;
|
||||
static constexpr std::size_t CapturableCount =
|
||||
StaticMath::Sum::eval(
|
||||
static_cast<std::size_t>(FunctionTraits::template Arg<I>::Defined)...);
|
||||
static constexpr std::size_t PlaceholdersCount = Count - CapturableCount;
|
||||
|
||||
static constexpr bool Valid = StaticMath::And::eval(StaticCheck<I>::Valid...);
|
||||
static constexpr bool StaticAssert =
|
||||
StaticMath::And::eval(StaticCheck<I>::StaticAssert...);
|
||||
|
||||
using Indexes = typename QtPrivate::IndexesList<I...>;
|
||||
|
||||
using CapturableIndexes =
|
||||
typename QtPrivate::Indexes<CapturableCount>::Value;
|
||||
|
||||
using PlaceholdersIndexes =
|
||||
typename QtPrivate::Indexes<PlaceholdersCount>::Value;
|
||||
|
||||
using Last = Arg<FunctionTraits::ArgumentIndexMax>;
|
||||
};
|
||||
|
||||
template<int ... I>
|
||||
static constexpr ArgumentsReturn<I...> eval(QtPrivate::IndexesList<I...>) noexcept
|
||||
{
|
||||
return ArgumentsReturn<I...>{};
|
||||
}
|
||||
};
|
||||
|
||||
using Arguments = ArgumentsCheck;
|
||||
template<int CaptureOffset>
|
||||
struct BindType {
|
||||
template<typename ... Args>
|
||||
struct FunctionWrapper {
|
||||
using Type = std::function<typename FunctionTraits::ReturnType (Args...)>;
|
||||
};
|
||||
|
||||
template<int ... Idx>
|
||||
static constexpr typename FunctionWrapper<
|
||||
typename FunctionTraits::template Arg<CaptureOffset + Idx>::Type...>::Type
|
||||
eval(QtPrivate::IndexesList<Idx...>) noexcept
|
||||
{
|
||||
return FunctionWrapper<
|
||||
typename FunctionTraits::template Arg<CaptureOffset + Idx>::Type...>::Type();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace QtPrivate
|
||||
|
||||
template <typename ViewHandler, bool DisableStaticAssert = false>
|
||||
struct QHttpServerRouterViewTraits
|
||||
{
|
||||
using Helpers = typename QtPrivate::ViewTraitsHelper<ViewHandler, DisableStaticAssert>;
|
||||
using Arguments = decltype(Helpers::Arguments::eval(typename Helpers::ArgumentIndexes{}));
|
||||
using BindableType = decltype(
|
||||
Helpers::template BindType<Arguments::CapturableCount>::eval(
|
||||
typename Arguments::PlaceholdersIndexes{}));
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -87,6 +87,12 @@ private slots:
|
||||
void initTestCase();
|
||||
void routerRule_data();
|
||||
void routerRule();
|
||||
void viewHandlerNoArg();
|
||||
void viewHandlerOneArg();
|
||||
void viewHandlerTwoArgs();
|
||||
void viewHandlerResponder();
|
||||
void viewHandlerRequest();
|
||||
void viewHandlerLastTwoSpecials();
|
||||
|
||||
private:
|
||||
HttpServer httpserver;
|
||||
@ -211,6 +217,326 @@ void tst_QHttpServerRouter::routerRule()
|
||||
QCOMPARE(reply->readAll(), body);
|
||||
}
|
||||
|
||||
void tst_QHttpServerRouter::viewHandlerNoArg()
|
||||
{
|
||||
auto viewNonArg = [] () {
|
||||
};
|
||||
|
||||
using ViewTraits = QHttpServerRouterViewTraits<decltype(viewNonArg), true>;
|
||||
using Args = typename ViewTraits::Arguments;
|
||||
|
||||
static_assert(Args::Count == 0,
|
||||
"viewNonArg: Args::Count == 0");
|
||||
static_assert(Args::CapturableCount == 0,
|
||||
"viewNonArg: Args::CapturableCount == 0");
|
||||
static_assert(Args::PlaceholdersCount == 0,
|
||||
"viewNonArg: Args::PlaceholdersCount == 0");
|
||||
|
||||
static_assert(Args::Last::IsRequest::Value == 0,
|
||||
"viewNonArg: Args::Last::IsRequest::Value == 0");
|
||||
static_assert(Args::Last::IsRequest::Valid == 0,
|
||||
"viewNonArg: Args::Last::IsRequest::Valid == 0");
|
||||
static_assert(Args::Last::IsResponder::Value == 0,
|
||||
"viewNonArg: Args::Last::IsResponder::Value == 0");
|
||||
static_assert(Args::Last::IsResponder::Valid == 0,
|
||||
"viewNonArg: Args::Last::IsResponder::Valid == 0");
|
||||
static_assert(Args::Last::IsSpecial::Value == 0,
|
||||
"viewNonArg: Args::Last::IsSpecial::Value == 0");
|
||||
static_assert(Args::Last::IsSpecial::Valid == 0,
|
||||
"viewNonArg: Args::Last::IsSpecial::Valid == 0");
|
||||
static_assert(Args::Last::IsSimple::Value == 0,
|
||||
"viewNonArg: Args::Last::IsSimple::Value == 0");
|
||||
static_assert(Args::Last::IsSimple::Valid == 0,
|
||||
"viewNonArg: Args::Last::IsSimple::Valid == 0");
|
||||
static_assert(Args::Last::Valid == 0,
|
||||
"viewOneArg: Args::Last::Valid");
|
||||
static_assert(Args::Last::StaticAssert,
|
||||
"viewOneArg: Args::Last::StaticAssert");
|
||||
static_assert(Args::Last::isType<std::false_type>(),
|
||||
"viewNonArg: Args::Last::isType<std::false_type>()");
|
||||
|
||||
using Arg1 = typename Args::template Arg<1>;
|
||||
static_assert(Arg1::IsRequest::Value == 0,
|
||||
"viewNonArg: Args::Arg<1>::isRequest::Value == 0");
|
||||
static_assert(Arg1::IsRequest::Valid == 0,
|
||||
"viewNonArg: Args::Arg<1>::IsRequest::Valid == 0");
|
||||
static_assert(Arg1::IsResponder::Value == 0,
|
||||
"viewNonArg: Args::Arg<1>::IsResponder::Value == 0");
|
||||
static_assert(Arg1::IsResponder::Valid == 0,
|
||||
"viewNonArg: Args::Arg<1>::IsResponder::Valid == 0");
|
||||
static_assert(Arg1::IsSpecial::Value == 0,
|
||||
"viewNonArg: Args::Arg<1>::IsSpecial::Value == 0");
|
||||
static_assert(Arg1::IsSpecial::Valid == 0,
|
||||
"viewNonArg: Args::Arg<1>::IsSpecial::Valid == 0");
|
||||
static_assert(Arg1::Valid == 0,
|
||||
"viewOneArg: Args::Arg<1>::Valid");
|
||||
static_assert(Arg1::StaticAssert,
|
||||
"viewOneArg: Args::Arg<1>::Valid::StaticAssert");
|
||||
static_assert(Arg1::isType<std::false_type>(),
|
||||
"viewNonArg: Args::Arg<1>::isType<std::false_type>()");
|
||||
|
||||
static_assert(Args::Valid, "viewNonArg: Args::Valid");
|
||||
static_assert(Args::StaticAssert, "viewNonArg: Args::StaticAssert");
|
||||
}
|
||||
|
||||
void tst_QHttpServerRouter::viewHandlerOneArg()
|
||||
{
|
||||
auto view = [] (const quint64 &) {
|
||||
};
|
||||
|
||||
using ViewTraits = QHttpServerRouterViewTraits<decltype(view), true>;
|
||||
using Args = typename ViewTraits::Arguments;
|
||||
|
||||
static_assert(Args::Count == 1,
|
||||
"viewOneArg: Args::Count == 1");
|
||||
static_assert(Args::CapturableCount == 1,
|
||||
"viewOneArg: Args::CapturableCount == 1");
|
||||
static_assert(Args::PlaceholdersCount == 0,
|
||||
"viewOneArg: Args::PlaceholdersCount == 0");
|
||||
static_assert(Args::Last::IsRequest::Value == 0,
|
||||
"viewOneArg: Args::Last::IsRequest::Value == 0");
|
||||
static_assert(Args::Last::IsRequest::Valid == 0,
|
||||
"viewOneArg: Args::Last::IsRequest::Valid == 0");
|
||||
static_assert(Args::Last::IsResponder::Value == 0,
|
||||
"viewOneArg: Args::Last::IsResponder::Value == 0");
|
||||
static_assert(Args::Last::IsResponder::Valid == 0,
|
||||
"viewOneArg: Args::Last::IsResponder::Valid == 0");
|
||||
static_assert(Args::Last::IsSpecial::Value == 0,
|
||||
"viewOneArg: Args::Last::IsSpecial::Value == 0");
|
||||
static_assert(Args::Last::IsSpecial::Valid == 0,
|
||||
"viewOneArg: Args::Last::IsSpecial::Valid == 0");
|
||||
static_assert(Args::Last::IsSimple::Value,
|
||||
"viewOneArg: Args::Last::IsSimple::Value");
|
||||
static_assert(Args::Last::IsSimple::Valid,
|
||||
"viewOneArg: Args::Last::IsSimple::Valid");
|
||||
static_assert(Args::Last::Valid,
|
||||
"viewOneArg: Args::Last::Valid");
|
||||
static_assert(Args::Last::StaticAssert,
|
||||
"viewOneArg: Args::Last::StaticAssert");
|
||||
static_assert(Args::Last::isType<const quint64 &>(),
|
||||
"viewNonArg: Args::Last::isType<const quint64 &>()");
|
||||
static_assert(Args::Valid, "viewOneArg: Args::Valid");
|
||||
static_assert(Args::StaticAssert, "viewOneArg: Args::StaticAssert");
|
||||
}
|
||||
|
||||
void tst_QHttpServerRouter::viewHandlerTwoArgs()
|
||||
{
|
||||
auto view = [] (const quint64 &, const QHttpServerResponder &) {
|
||||
};
|
||||
|
||||
using ViewTraits = QHttpServerRouterViewTraits<decltype(view), true>;
|
||||
using Args = typename ViewTraits::Arguments;
|
||||
|
||||
static_assert(Args::Count == 2,
|
||||
"viewTwoArgs: Args::Count == 2");
|
||||
static_assert(Args::CapturableCount == 1,
|
||||
"viewTwoArgs: Args::CapturableCount == 1");
|
||||
static_assert(Args::PlaceholdersCount == 1,
|
||||
"viewTwoArgs: Args::PlaceholdersCount == 0");
|
||||
|
||||
using Arg0 = typename Args::template Arg<0>;
|
||||
static_assert(Arg0::IsRequest::Value == 0,
|
||||
"viewTwoArgs: Args::Arg0::IsRequest::Value == 0");
|
||||
static_assert(Arg0::IsRequest::Valid == 0,
|
||||
"viewTwoArgs: Args::Arg0::IsRequest::Valid == 0");
|
||||
static_assert(Arg0::IsResponder::Value == 0,
|
||||
"viewTwoArgs: Args::Arg0::IsResponder::Value == 0");
|
||||
static_assert(Arg0::IsResponder::Valid == 0,
|
||||
"viewTwoArgs: Args::Arg0::IsResponder::Valid == 0");
|
||||
static_assert(Arg0::IsSpecial::Value == 0,
|
||||
"viewTwoArgs: Args::Arg0::IsSpecial::Value == 0");
|
||||
static_assert(Arg0::IsSpecial::Valid == 0,
|
||||
"viewTwoArgs: Args::Arg0::IsSpecial::Valid == 0");
|
||||
static_assert(Arg0::IsSimple::Value,
|
||||
"viewTwoArgs: Args::Arg0::IsSimple::Value");
|
||||
static_assert(Arg0::IsSimple::Valid,
|
||||
"viewTwoArgs: Args::Arg0::IsSimple::Valid");
|
||||
static_assert(Arg0::Valid,
|
||||
"viewTwoArgs: Args::Arg0::Valid");
|
||||
static_assert(Arg0::StaticAssert,
|
||||
"viewTwoArgs: Args::Arg0::StaticAssert");
|
||||
static_assert(Arg0::isType<const quint64 &>(),
|
||||
"viewNonArg: Args::Arg0::isType<const quint64>()");
|
||||
|
||||
using Arg1 = typename Args::template Arg<1>;
|
||||
static_assert(Arg1::IsRequest::Value == 0,
|
||||
"viewTwoArgs: Args::Arg1::IsRequest::Value == 0");
|
||||
static_assert(Arg1::IsRequest::Valid == 0,
|
||||
"viewTwoArgs: Args::Arg1::IsRequest::Valid == 0");
|
||||
static_assert(Arg1::IsResponder::Value,
|
||||
"viewTwoArgs: Args::Arg1::IsResponder::Value");
|
||||
static_assert(Arg1::IsResponder::Valid == 0,
|
||||
"viewTwoArgs: Args::Arg1::IsResponder::Valid == 0");
|
||||
static_assert(Arg1::IsSpecial::Value == 1,
|
||||
"viewTwoArgs: Args::Arg1::IsSpecial::Value");
|
||||
static_assert(Arg1::IsSpecial::Valid == 0,
|
||||
"viewTwoArgs: Args::Arg1::IsSpecial::Valid == 0");
|
||||
static_assert(Arg1::IsSimple::Value == 0,
|
||||
"viewTwoArgs: Args::Arg1::IsSimple::Value == 0");
|
||||
static_assert(Arg1::IsSimple::Valid == 0,
|
||||
"viewTwoArgs: Args::Arg1::IsSimple::Valid == 0");
|
||||
static_assert(Arg1::Valid == 0,
|
||||
"viewTwoArgs: Args::Arg1::Valid");
|
||||
// StaticAssert is disabled in tests
|
||||
static_assert(Arg1::StaticAssert,
|
||||
"viewOneArg: Args::Arg1::StaticAssert");
|
||||
static_assert(Arg1::isType<const QHttpServerResponder &>(),
|
||||
"viewTwoArgs: Args::Arg1::isType<const QHttpServerResponder &>>()");
|
||||
|
||||
static_assert(Args::Valid == 0, "viewTwoArgs: Args::Valid == 0");
|
||||
// StaticAssert is disabled in tests
|
||||
static_assert(Args::StaticAssert, "viewTwoArgs: Args::StaticAssert");
|
||||
}
|
||||
|
||||
void tst_QHttpServerRouter::viewHandlerResponder()
|
||||
{
|
||||
auto view = [] (QHttpServerResponder &&) {
|
||||
};
|
||||
|
||||
using ViewTraits = QHttpServerRouterViewTraits<decltype(view), true>;
|
||||
using Args = typename ViewTraits::Arguments;
|
||||
|
||||
static_assert(Args::Count == 1,
|
||||
"viewResponder: Args::Count == 1");
|
||||
static_assert(Args::CapturableCount == 0,
|
||||
"viewResponder: Args::CapturableCount == 0");
|
||||
static_assert(Args::PlaceholdersCount == 1,
|
||||
"viewResponder: Args::PlaceholdersCount == 1");
|
||||
static_assert(Args::Last::IsRequest::Value == 0,
|
||||
"viewResponder: Args::Last::IsRequest::Value == 0");
|
||||
static_assert(Args::Last::IsRequest::Valid == 0,
|
||||
"viewResponder: Args::Last::IsRequest::Valid == 0");
|
||||
static_assert(Args::Last::IsResponder::Value,
|
||||
"viewResponder: Args::Last::IsResponder::Value");
|
||||
static_assert(Args::Last::IsResponder::Valid,
|
||||
"viewResponder: Args::Last::IsResponder::Valid");
|
||||
static_assert(Args::Last::IsSpecial::Value,
|
||||
"viewResponder: Args::Last::IsSpecial::Value");
|
||||
static_assert(Args::Last::IsSpecial::Valid,
|
||||
"viewResponder: Args::Last::IsSpecial::Valid");
|
||||
static_assert(Args::Last::IsSimple::Value == 0,
|
||||
"viewResponder: Args::Last::IsSimple::Value == 0");
|
||||
static_assert(Args::Last::IsSimple::Valid == 0,
|
||||
"viewResponder: Args::Last::IsSimple::Valid == 0");
|
||||
static_assert(Args::Last::Valid,
|
||||
"viewResponder: Args::Last::Valid");
|
||||
static_assert(Args::Last::StaticAssert,
|
||||
"viewResponder: Args::Last::StaticAssert");
|
||||
static_assert(Args::Last::isType<QHttpServerResponder &&>(),
|
||||
"viewNonArg: Args::Last::isType<QHttpServerResponder &&>()");
|
||||
static_assert(Args::Valid, "viewResponder: Args::Valid");
|
||||
static_assert(Args::StaticAssert, "viewResponder: Args::StaticAssert");
|
||||
}
|
||||
|
||||
void tst_QHttpServerRouter::viewHandlerRequest()
|
||||
{
|
||||
auto view = [] (const QHttpServerRequest &) {
|
||||
};
|
||||
|
||||
using ViewTraits = QHttpServerRouterViewTraits<decltype(view), true>;
|
||||
using Args = typename ViewTraits::Arguments;
|
||||
|
||||
static_assert(Args::Count == 1,
|
||||
"viewResponder: Args::Count == 1");
|
||||
static_assert(Args::CapturableCount == 0,
|
||||
"viewResponder: Args::CapturableCount == 0");
|
||||
static_assert(Args::PlaceholdersCount == 1,
|
||||
"viewResponder: Args::PlaceholdersCount == 1");
|
||||
static_assert(Args::Last::IsRequest::Value,
|
||||
"viewResponder: Args::Last::IsRequest::Value");
|
||||
static_assert(Args::Last::IsRequest::Valid,
|
||||
"viewResponder: Args::Last::IsRequest::Valid");
|
||||
static_assert(Args::Last::IsResponder::Value == 0,
|
||||
"viewResponder: Args::Last::IsResponder::Value == 0");
|
||||
static_assert(Args::Last::IsResponder::Valid == 0,
|
||||
"viewResponder: Args::Last::IsResponder::Valid == 0");
|
||||
static_assert(Args::Last::IsSpecial::Value,
|
||||
"viewResponder: Args::Last::IsSpecial::Value");
|
||||
static_assert(Args::Last::IsSpecial::Valid,
|
||||
"viewResponder: Args::Last::IsSpecial::Valid");
|
||||
static_assert(Args::Last::IsSimple::Value == 0,
|
||||
"viewResponder: Args::Last::IsSimple::Value == 0");
|
||||
static_assert(Args::Last::IsSimple::Valid == 0,
|
||||
"viewResponder: Args::Last::IsSimple::Valid == 0");
|
||||
static_assert(Args::Last::Valid,
|
||||
"viewResponder: Args::Last::Valid");
|
||||
static_assert(Args::Last::StaticAssert,
|
||||
"viewResponder: Args::Last::StaticAssert");
|
||||
static_assert(Args::Last::isType<const QHttpServerRequest &>(),
|
||||
"viewNonArg: Args::Last::isType<const QHttpServerRequest &>()");
|
||||
static_assert(Args::Valid, "viewResponder: Args::Valid");
|
||||
static_assert(Args::StaticAssert, "viewResponder: Args::StaticAssert");
|
||||
}
|
||||
|
||||
void tst_QHttpServerRouter::viewHandlerLastTwoSpecials()
|
||||
{
|
||||
auto view = [] (const QHttpServerRequest &, QHttpServerResponder &&) {
|
||||
};
|
||||
|
||||
using ViewTraits = QHttpServerRouterViewTraits<decltype(view), true>;
|
||||
using Args = typename ViewTraits::Arguments;
|
||||
|
||||
static_assert(Args::Count == 2,
|
||||
"viewTwoSpecialArgs: Args::Count == 2");
|
||||
static_assert(Args::CapturableCount == 0,
|
||||
"viewTwoSpecialArgs: Args::CapturableCount == 1");
|
||||
static_assert(Args::PlaceholdersCount == 2,
|
||||
"viewTwoSpecialArgs: Args::PlaceholdersCount == 0");
|
||||
|
||||
using Arg0 = typename Args::template Arg<0>;
|
||||
static_assert(Arg0::IsRequest::Value,
|
||||
"viewTwoSpecialArgs: Args::Arg0::IsRequest::Value");
|
||||
static_assert(Arg0::IsRequest::Valid == 0,
|
||||
"viewTwoSpecialArgs: Args::Arg0::IsRequest::Valid == 0");
|
||||
static_assert(Arg0::IsResponder::Value == 0,
|
||||
"viewTwoSpecialArgs: Args::Arg0::IsResponder::Value == 0");
|
||||
static_assert(Arg0::IsResponder::Valid == 0,
|
||||
"viewTwoSpecialArgs: Args::Arg0::IsResponder::Valid == 0");
|
||||
static_assert(Arg0::IsSpecial::Value,
|
||||
"viewTwoSpecialArgs: Args::Arg0::IsSpecial::Value");
|
||||
static_assert(Arg0::IsSpecial::Valid == 0,
|
||||
"viewTwoSpecialArgs: Args::Arg0::IsSpecial::Valid == 0");
|
||||
static_assert(Arg0::IsSimple::Value == 0,
|
||||
"viewTwoSpecialArgs: Args::Arg0::IsSimple::Value == 0");
|
||||
static_assert(Arg0::IsSimple::Valid == 0,
|
||||
"viewTwoSpecialArgs: Args::Arg0::IsSimple::Valid == 0");
|
||||
static_assert(Arg0::Valid == 0,
|
||||
"viewTwoSpecialArgs: Args::Arg0::Valid");
|
||||
// StaticAssert is disabled in tests
|
||||
static_assert(Arg0::StaticAssert,
|
||||
"viewTwoSpecialArgs: Args::Arg0::StaticAssert");
|
||||
static_assert(Arg0::isType<const QHttpServerRequest &>(),
|
||||
"viewNonArg: Args::Arg0::isType<const QHttpServerRequest &>()");
|
||||
|
||||
using Arg1 = typename Args::template Arg<1>;
|
||||
static_assert(Arg1::IsRequest::Value == 0,
|
||||
"viewTwoSpecialArgs: Args::Arg1::IsRequest::Value == 0");
|
||||
static_assert(Arg1::IsRequest::Valid == 0,
|
||||
"viewTwoSpecialArgs: Args::Arg1::IsRequest::Valid == 0");
|
||||
static_assert(Arg1::IsResponder::Value,
|
||||
"viewTwoSpecialArgs: Args::Arg1::IsResponder::Value");
|
||||
static_assert(Arg1::IsResponder::Valid,
|
||||
"viewTwoSpecialArgs: Args::Arg1::IsResponder::Valid");
|
||||
static_assert(Arg1::IsSpecial::Value,
|
||||
"viewTwoSpecialArgs: Args::Arg1::IsSpecial::Value");
|
||||
static_assert(Arg1::IsSpecial::Valid,
|
||||
"viewTwoSpecialArgs: Args::Arg1::IsSpecial::Valid");
|
||||
static_assert(Arg1::IsSimple::Value == 0,
|
||||
"viewTwoSpecialArgs: Args::Arg1::IsSimple::Value == 0");
|
||||
static_assert(Arg1::IsSimple::Valid == 0,
|
||||
"viewTwoSpecialArgs: Args::Arg1::IsSimple::Valid == 0");
|
||||
static_assert(Arg1::Valid,
|
||||
"viewTwoSpecialArgs: Args::Arg1::Valid");
|
||||
static_assert(Arg1::StaticAssert,
|
||||
"viewTwoSpecialArgs: Args::Arg1::StaticAssert");
|
||||
static_assert(Arg1::isType<QHttpServerResponder &&>(),
|
||||
"viewTwoSpecialArgs: Args::Arg1::isType<QHttpServerResponder &&>()");
|
||||
|
||||
static_assert(Args::Valid == 0, "viewTwoSpecialArgs: Args::Valid");
|
||||
// StaticAssert is disabled in tests
|
||||
static_assert(Args::StaticAssert, "viewTwoSpecialArgs: Args::StaticAssert");
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
QTEST_MAIN(tst_QHttpServerRouter)
|
||||
|
Loading…
x
Reference in New Issue
Block a user