alsk/tests/skeleton.cpp

265 lines
6.7 KiB
C++

#include <catch.hpp>
#include <alsk/skeleton/skeleton.h>
using namespace alsk;
using tmp::Pack;
struct Int {
int v;
Int(int v): v{v} {}
operator int() const { return v; }
};
struct A: Int {};
struct B: Int {};
struct C: Int {};
struct D: Int {};
struct E: Int {};
struct F: Int {};
struct G: Int {};
struct H: Int {};
struct I: Int {};
template<typename R>
struct Unary {
template<typename T>
R operator()(T a) { return{a+1}; }
};
template<typename R>
struct Binary {
template<typename T, typename U>
R operator()(T a, U b) { return{a+b}; }
};
template<>
struct Binary<void> {
template<typename T, typename U>
void operator()(T, U) {}
};
using S_ =
S<Serial,
S<Serial, Unary<D>, Binary<E>>,
Unary<F>,
S<Serial,
Unary<G>,
S<Serial, Unary<H>, Binary<void>>,
Unary<I>
>
>;
using L1 =
L<Serial, arg::R<1>(arg::P<1>, arg::P<2>),
D(arg::P<1>),
E(arg::R<0>, arg::P<0>)
>;
using L2 = F(arg::P<2>);
using L31 = G(arg::P<0>, arg::P<2>);
using L32 =
L<Serial, arg::R<0>(arg::R<0>, arg::P<1>),
H(arg::P<0>),
void(arg::P<0>, arg::P<1>)
>;
using L33 = I(arg::R<0>);
using L3 =
L<Serial, arg::R<2>(arg::R<1>, arg::P<0>, arg::R<0>),
L31, L32, L33
>;
using L_ =
L<Serial, arg::R<2>(A, B, C),
L1, L2, L3
>;
TEST_CASE("LinksToReturnTypes") {
REQUIRE(std::is_same<Pack<E>, impl::LinksToReturnTypes<L1>::type>{});
REQUIRE(std::is_same<Pack<F>, impl::LinksToReturnTypes<L2>::type>{});
REQUIRE(std::is_same<Pack<G>, impl::LinksToReturnTypes<L31>::type>{});
REQUIRE(std::is_same<Pack<H>, impl::LinksToReturnTypes<L32>::type>{});
REQUIRE(std::is_same<Pack<I>, impl::LinksToReturnTypes<L33>::type>{});
REQUIRE(std::is_same<Pack<I>, impl::LinksToReturnTypes<L3>::type>{});
REQUIRE(std::is_same<Pack<I>, impl::LinksToReturnTypes<L_>::type>{});
REQUIRE(std::is_same<Pack<E, F, I>, impl::LinksToReturnTypes<L1, L2, L3>::type>{});
}
using T_ =
Serial<arg::R<2>(A, B, C),
// 1
Fun<Serial<arg::R<1>(B, C),
Fun<Unary<D>, D(arg::P<1>)>,
Fun<Binary<E>, E(arg::R<0>, arg::P<0>)>
>, E(arg::P<1>, arg::P<2>)>,
// 2
Fun<Unary<F>, F(arg::P<2>)>,
// 3
Fun<Serial<arg::R<2>(F, A, E),
Fun<Unary<G>, G(arg::P<0>, arg::P<2>)>,
Fun<Serial<arg::R<0>(G, A),
Fun<Unary<H>, H(arg::P<0>)>,
Fun<Binary<void>, void(arg::P<0>, arg::P<1>)>
>, H(arg::R<0>, arg::P<1>)>,
Fun<Unary<I>, I(arg::R<0>)>
>, I(arg::R<1>, arg::P<0>, arg::R<0>)>
>;
template<typename...>
using TS_ = S_;
template<typename...>
using TL_ = L_;
TEST_CASE("BuildSkeleton") {
using T1 = BuildSkeleton<TS_, TL_>::skeleton<Pack<>, Pack<>>;
using T2 = BuildSkeletonT<S_, L_>;
REQUIRE(std::is_same<T_, T1>{});
REQUIRE(std::is_same<T_, T2>{});
}
TEST_CASE("TreeFromSkeleton") {
SECTION("simple") {
struct F {};
using Struct = S<Serial, F>;
using Links = L<Serial, void(), void()>;
using Skel = BuildSkeletonT<Struct, Links>;
using Expected =
tmp::Tree<
Branch<Serial, void ()>,
tmp::Tree<Leaf<F, void ()>>
>;
using Result = TreeFromSkeleton<Skel>;
REQUIRE(std::is_same<Expected, Result>{});
}
SECTION("with links") {
struct F {}; struct G {};
using Struct = S<Serial, S<Serial, F, G>>;
using Links = L<Serial, arg::R<0>(int&, int), L<Serial, arg::R<1>(arg::P<1>, arg::P<0>), long(arg::P<1>, arg::P<0>), int(arg::R<0>)>>;
using Skel = BuildSkeletonT<Struct, Links>;
using Expected =
tmp::Tree<
Branch<Serial, arg::R<0>(int&, int)>,
tmp::Tree<
Branch<Serial, arg::R<1>(int, int&), int(arg::P<1>, arg::P<0>)>,
tmp::Tree<Leaf<F, long(arg::P<1>, arg::P<0>)>>,
tmp::Tree<Leaf<G, int(arg::R<0>)>>
>
>;
using Result = TreeFromSkeleton<Skel>;
REQUIRE(std::is_same<Expected, Result>{});
}
SECTION("complex") {
struct A0 {}; struct A1 {}; struct A2 {}; struct A3 {}; struct R {};
using Struct = S<Serial, A0, S<Farm, S<Serial, A1, A2>>, A0, S<Serial, A3, A3>>;
using Links = L<Serial, void(), R(), L<Farm, bool(), L<Serial, char(), short(), int()>>, R(), L<Serial, long(), float(), double()>>;
using Skel = BuildSkeletonT<Struct, Links>;
using Expected =
tmp::Tree<
Branch<Serial, void()>,
tmp::Tree<Leaf<A0, R()>>,
tmp::Tree<
Branch<Farm, bool()>,
tmp::Tree<
Branch<Serial, char()>,
tmp::Tree<Leaf<A1, short()>>,
tmp::Tree<Leaf<A2, int()>>
>
>,
tmp::Tree<Leaf<A0, R()>>,
tmp::Tree<
Branch<Serial, long()>,
tmp::Tree<Leaf<A3, float()>>,
tmp::Tree<Leaf<A3, double()>>
>
>;
using Result = TreeFromSkeleton<Skel>;
REQUIRE(std::is_same<Expected, Result>{});
}
}
TEST_CASE("ToSkeleton") {
struct A0 {}; struct A1 {}; struct A2 {}; struct A3 {}; struct R {};
using Struct = S<Serial, A0, S<Farm, S<Serial, A1, A2>>, A0, S<Serial, A3, A3>>;
using Links = L<Serial, void(), R(), L<Farm, bool(), L<Serial, char(), short(), int()>>, R(), L<Serial, long(), float(), double()>>;
using Expected = BuildSkeletonT<Struct, Links>;
using Input =
tmp::Tree<
Branch<Serial, void()>,
tmp::Tree<Leaf<A0, R()>>,
tmp::Tree<
Branch<Farm, bool()>,
tmp::Tree<
Branch<Serial, char()>,
tmp::Tree<Leaf<A1, short()>>,
tmp::Tree<Leaf<A2, int()>>
>
>,
tmp::Tree<Leaf<A0, R()>>,
tmp::Tree<
Branch<Serial, long()>,
tmp::Tree<Leaf<A3, float()>>,
tmp::Tree<Leaf<A3, double()>>
>
>;
using Result = SkeletonFromTree<Input>;
REQUIRE(std::is_same<Expected, Result>{});
REQUIRE(std::is_same<Expected, SkeletonFromTree<TreeFromSkeleton<Expected>>>{});
}
TEST_CASE("SkeletonParallelHeight") {
SECTION("serial") {
struct F {}; struct G {};
using Struct = S<Serial, S<Serial, F, G>>;
using Links = L<Serial, arg::R<0>(int&, int), L<Serial, arg::R<1>(arg::P<1>, arg::P<0>), long(arg::P<1>, arg::P<0>), int(arg::R<0>)>>;
using Skel = BuildSkeletonT<Struct, Links>;
REQUIRE(skeletonParallelHeight<Skel> == 0);
}
SECTION("par2") {
struct A0 {}; struct A1 {}; struct A2 {};
using Struct = S<Serial, A0, S<Farm, S<Farm, A1>>, S<Farm, A2>>;
using Links = L<Serial, int(), int(), L<Farm, int(), L<Farm, int(), int()>>, L<Farm, int(), int()>>;
using Skel = BuildSkeletonT<Struct, Links>;
REQUIRE(skeletonParallelHeight<Skel> == 2);
}
SECTION("par4") {
struct A0 {};
using Struct = S<Farm, S<Farm, S<Farm, S<Farm, A0>>>>;
using Links = L<Farm, int(), L<Farm, int(), L<Farm, int(), L<Farm, int(), int()>>>>;
using Skel = BuildSkeletonT<Struct, Links>;
REQUIRE(skeletonParallelHeight<Skel> == 4);
}
SECTION("complex") {
struct A0 {};
using Struct = S<Farm, S<Serial, S<Farm, S<Farm, A0>>, S<Farm, S<Serial, S<Farm, A0>>>>>;
using Links = L<Farm, int(), L<Serial, int(), L<Farm, int(), L<Farm, int(), int()>>, L<Farm, int(), L<Serial, int(), L<Farm, int(), int()>>>>>;
using Skel = BuildSkeletonT<Struct, Links>;
REQUIRE(skeletonParallelHeight<Skel> == 3);
}
}