4
0
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:
Mikhail Svetkin 2019-08-30 23:14:31 +02:00
parent 52bce52413
commit 3eebefcd27
4 changed files with 605 additions and 169 deletions

@ -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)