alsk/tests/edsl/edsl.cpp
2021-05-10 18:14:13 +02:00

128 lines
3.5 KiB
C++

#include <catch.hpp>
#include <alsk/alsk.h>
using namespace alsk::arg;
using namespace alsk::edsl;
static int counterDo, counterThen, counterDone;
struct Do { void operator()() { ++counterDo; } };
struct Then { void operator()() { ++counterThen; } };
struct Done { void operator()() { ++counterDone; } };
struct Produce0 { int operator()(int x) { return x+1; } };
struct Produce1 { int operator()(int x) { return x-2; } };
struct Consume { int operator()(int x, int y) { return x*y; } };
// TODO? avoid copies so it is truly stateful
struct Generate { int value; int operator()(int b) { return ++value+b; } };
struct Transform0 { int operator()(int x) { return x+1; } };
struct Transform1 { int operator()(int x) { return x-2; } };
struct Produce { int operator()(int x, int y) { return x*y; } };
struct Select {
int mod;
int operator()(int a, int b) { if(a%mod == b%mod) return std::min(a, b); return (a%mod > b%mod)? a : b; }
};
TEST_CASE("edsl") {
auto aDo = makeOperand<Do>();
auto aThen = makeOperand<Then>();
auto aDone = makeOperand<Done>();
auto aProduce0 = makeOperand<Produce0>();
auto aProduce1 = makeOperand<Produce1>();
auto aConsume = makeOperand<Consume>();
auto e0 = aDo & (5*aThen) & aDone;
using E0 = decltype(e0);
using S0 = alsk::S<alsk::Serial, Do, alsk::S<alsk::Farm, Then>, Done>;
using L0 = alsk::L<alsk::Serial, void(), void(), alsk::L<alsk::Farm, void(), void()>, void()>;
auto e1 = 5*(aDo, 2*aThen, aDone);
using E1 = decltype(e1);
using S1 = alsk::S<alsk::Farm, alsk::S<alsk::Serial, Do, alsk::S<alsk::Farm, Then>, Done>>;
using L1 = alsk::L<alsk::Farm, void(), alsk::L<alsk::Serial, void(), void(), alsk::L<alsk::Farm, void(), void()>, void()>>;
auto e2 = link<R<2>(int)>(
link<int(P<0>)>(aProduce0),
link<int(P<0>)>(aProduce1),
link<int(R<1>, R<0>)>(aConsume)
);
SECTION("Construction") {
REQUIRE(std::is_same<E0::Signature, void()>{});
REQUIRE(std::is_same<E0::Struct, S0>{});
REQUIRE(std::is_same<E0::Links, L0>{});
REQUIRE(std::is_same<E1::Signature, void()>{});
REQUIRE(std::is_same<E1::Struct, S1>{});
REQUIRE(std::is_same<E1::Links, L1>{});
}
SECTION("Linking") {
{
auto f2 = implement<alsk::exec::Sequential>(e2);
REQUIRE(f2(0) == -2);
REQUIRE(f2(2) == 0);
REQUIRE(f2(5) == 18);
}
}
SECTION("Setup") {
auto f0 = implement<alsk::exec::Sequential>(e0);
REQUIRE(f0.skeleton.task<1>().n == 5);
}
SECTION("Check run") {
{
auto f0 = implement<alsk::exec::Sequential>(e0);
counterDo = counterThen = counterDone = 0;
f0();
REQUIRE(counterDo == 1);
REQUIRE(counterThen == 5);
REQUIRE(counterDone == 1);
}
{
auto f1 = implement<alsk::exec::Sequential>(e1);
counterDo = counterThen = counterDone = 0;
f1();
REQUIRE(counterDo == 5);
REQUIRE(counterThen == 10);
REQUIRE(counterDone == 5);
}
}
SECTION("Complex case") {
auto generate = makeOperand<Generate>();
auto transform0 = makeOperand<Transform0>();
auto transform1 = makeOperand<Transform1>();
auto produce = makeOperand<Produce>();
auto select = makeOperand<int(int, int), Select>();
auto innerTask = link<R<3>(int)>(
link<int(P<0>)>(generate),
link<int(R<0>)>(transform0),
link<int(R<0>)>(transform1),
link<int(R<2>, R<1>)>(produce)
);
auto task = link<int(int)>(10 * link<R<3>(P<0>)>(innerTask)) ->* select;
auto f = implement<alsk::exec::Sequential>(task);
f.skeleton.select.mod = 5;
REQUIRE(f(4) == 18);
REQUIRE(f(5) == 28);
REQUIRE(f(6) == 40);
REQUIRE(f(7) == 54);
REQUIRE(f(8) == 70);
}
}