Commit d58fe683 authored by Kirk Shoop's avatar Kirk Shoop Committed by Facebook Github Bot

migrate to gtest

Summary:
migrated tests
fixed some bugs introduced while tests were disabled

Reviewed By: yfeldblum

Differential Revision: D10515231

fbshipit-source-id: 34cddb6588c4da9cd05256111bf9626b013dd4fa
parent 20d6c1df
...@@ -84,8 +84,8 @@ class any_constrained_single_sender { ...@@ -84,8 +84,8 @@ class any_constrained_single_sender {
return ::folly::pushmi::top(*static_cast<Wrapped*>((void*)src.buffer_)); return ::folly::pushmi::top(*static_cast<Wrapped*>((void*)src.buffer_));
} }
static any_constrained_executor<E, CV> executor(data& src) { static any_constrained_executor<E, CV> executor(data& src) {
return any_constrained_executor<E, CV>{ return any_constrained_executor<E, CV>{::folly::pushmi::executor(
executor(*static_cast<Wrapped*>((void*)src.buffer_))}; *static_cast<Wrapped*>((void*)src.buffer_))};
} }
static void submit(data& src, CV cv, any_receiver<E, VN...> out) { static void submit(data& src, CV cv, any_receiver<E, VN...> out) {
::folly::pushmi::submit( ::folly::pushmi::submit(
......
...@@ -166,7 +166,7 @@ struct entangled { ...@@ -166,7 +166,7 @@ struct entangled {
entangled& operator=(entangled&&) = delete; entangled& operator=(entangled&&) = delete;
explicit entangled(T t) explicit entangled(T t)
: t(std::move(t)), dual(nullptr), stateMachine(kUnlocked) {} : stateMachine(kUnlocked), t(std::move(t)), dual(nullptr) {}
entangled(entangled&& other) entangled(entangled&& other)
: stateMachine((other.lockBoth(), kLocked)), : stateMachine((other.lockBoth(), kLocked)),
t(std::move(other.t)), t(std::move(other.t)),
......
...@@ -34,16 +34,27 @@ struct for_each_fn { ...@@ -34,16 +34,27 @@ struct for_each_fn {
using properties = using properties =
property_set_insert_t<properties_t<Out>, property_set<is_flow<>>>; property_set_insert_t<properties_t<Out>, property_set<is_flow<>>>;
std::function<void(std::ptrdiff_t)> pull; std::function<void(std::ptrdiff_t)> pull;
template <class V> template <class... VN>
void value(V&& v) { void value(VN&&... vn) {
set_value(static_cast<Out&>(*this), (V &&) v); ::folly::pushmi::set_value(static_cast<Out&>(*this), (VN &&) vn...);
pull(1); pull(1);
} }
template <class E>
void error(E&& e) {
// break circular reference
pull = nullptr;
::folly::pushmi::set_error(static_cast<Out&>(*this), (E &&) e);
}
void done() {
// break circular reference
pull = nullptr;
::folly::pushmi::set_done(static_cast<Out&>(*this));
}
PUSHMI_TEMPLATE(class Up) PUSHMI_TEMPLATE(class Up)
(requires Receiver<Up>) (requires Receiver<Up> && ReceiveValue<Up, std::ptrdiff_t>)
void starting(Up up) { void starting(Up up) {
pull = [up = std::move(up)](std::ptrdiff_t requested) mutable { pull = [up = std::move(up)](std::ptrdiff_t requested) mutable {
set_value(up, requested); ::folly::pushmi::set_value(up, requested);
}; };
pull(1); pull(1);
} }
...@@ -62,23 +73,8 @@ struct for_each_fn { ...@@ -62,23 +73,8 @@ struct for_each_fn {
property_set_index_t<properties_t<In>, is_single<>>>>()( property_set_index_t<properties_t<In>, is_single<>>>>()(
std::move(args_))}; std::move(args_))};
using Out = decltype(out); using Out = decltype(out);
submit( ::folly::pushmi::submit(
in,
::folly::pushmi::detail::receiver_from_fn<In>()(
Pull<In, Out>{std::move(out)}));
return in;
}
PUSHMI_TEMPLATE(class In)
(requires Sender<In>&& Constrained<In>&& Flow<In>&& Many<In>)
In operator()(In in) {
auto out{::folly::pushmi::detail::receiver_from_fn<subset<
is_sender<>,
property_set_index_t<properties_t<In>, is_single<>>>>()(
std::move(args_))};
using Out = decltype(out);
submit(
in, in,
::folly::pushmi::top(in),
::folly::pushmi::detail::receiver_from_fn<In>()( ::folly::pushmi::detail::receiver_from_fn<In>()(
Pull<In, Out>{std::move(out)})); Pull<In, Out>{std::move(out)}));
return in; return in;
...@@ -88,7 +84,7 @@ struct for_each_fn { ...@@ -88,7 +84,7 @@ struct for_each_fn {
public: public:
template <class... AN> template <class... AN>
auto operator()(AN&&... an) const { auto operator()(AN&&... an) const {
return for_each_fn::fn<AN...>{{(AN &&) an...}}; return for_each_fn::fn<AN...>{std::tuple<AN...>{(AN &&) an...}};
} }
}; };
......
...@@ -102,32 +102,35 @@ struct flow_from_up { ...@@ -102,32 +102,35 @@ struct flow_from_up {
return; return;
} }
// submit work to exec // submit work to exec
submit(p->exec, make_receiver([p = p, requested](auto) { ::folly::pushmi::submit(
auto remaining = requested; p->exec, make_receiver([p = p, requested](auto) {
// this loop is structured to work when there is auto remaining = requested;
// re-entrancy out.value in the loop may call up.value. // this loop is structured to work when there is
// to handle this the state of p->c must be captured and // re-entrancy out.value in the loop may call up.value.
// the remaining and p->c must be changed before // to handle this the state of p->c must be captured and
// out.value is called. // the remaining and p->c must be changed before
while (remaining-- > 0 && !p->stop && p->c != p->end) { // out.value is called.
auto i = (p->c)++; while (remaining-- > 0 && !p->stop && p->c != p->end) {
set_value(p->out, ::folly::pushmi::detail::as_const(*i)); auto i = (p->c)++;
} set_value(p->out, ::folly::pushmi::detail::as_const(*i));
if (p->c == p->end) { }
set_done(p->out); if (p->c == p->end) {
} set_done(p->out);
})); }
}));
} }
template <class E> template <class E>
void error(E) noexcept { void error(E) noexcept {
p->stop.store(true); p->stop.store(true);
submit(p->exec, make_receiver([p = p](auto) { set_done(p->out); })); ::folly::pushmi::submit(
p->exec, make_receiver([p = p](auto) { set_done(p->out); }));
} }
void done() { void done() {
p->stop.store(true); p->stop.store(true);
submit(p->exec, make_receiver([p = p](auto) { set_done(p->out); })); ::folly::pushmi::submit(
p->exec, make_receiver([p = p](auto) { set_done(p->out); }));
} }
}; };
...@@ -147,10 +150,11 @@ PUSHMI_INLINE_VAR constexpr struct flow_from_fn { ...@@ -147,10 +150,11 @@ PUSHMI_INLINE_VAR constexpr struct flow_from_fn {
auto p = std::make_shared<Producer>( auto p = std::make_shared<Producer>(
begin_, end_, std::move(out), exec_, false); begin_, end_, std::move(out), exec_, false);
submit(exec_, make_receiver([p](auto) { ::folly::pushmi::submit(
// pass reference for cancellation. exec_, make_receiver([p](auto) {
set_starting(p->out, make_receiver(flow_from_up<Producer>{p})); // pass reference for cancellation.
})); set_starting(p->out, make_receiver(flow_from_up<Producer>{p}));
}));
} }
}; };
......
...@@ -58,7 +58,7 @@ struct submit_fn { ...@@ -58,7 +58,7 @@ struct submit_fn {
In operator()(In in) { In operator()(In in) {
auto out{ auto out{
::folly::pushmi::detail::receiver_from_fn<In>{}(std::move(args_))}; ::folly::pushmi::detail::receiver_from_fn<In>{}(std::move(args_))};
submit(in, std::move(out)); ::folly::pushmi::submit(in, std::move(out));
return in; return in;
} }
}; };
...@@ -81,7 +81,7 @@ struct submit_at_fn { ...@@ -81,7 +81,7 @@ struct submit_at_fn {
In operator()(In in) { In operator()(In in) {
auto out{ auto out{
::folly::pushmi::detail::receiver_from_fn<In>()(std::move(args_))}; ::folly::pushmi::detail::receiver_from_fn<In>()(std::move(args_))};
submit(in, std::move(at_), std::move(out)); ::folly::pushmi::submit(in, std::move(at_), std::move(out));
return in; return in;
} }
}; };
...@@ -90,7 +90,8 @@ struct submit_at_fn { ...@@ -90,7 +90,8 @@ struct submit_at_fn {
PUSHMI_TEMPLATE(class TP, class... AN) PUSHMI_TEMPLATE(class TP, class... AN)
(requires Regular<TP>) (requires Regular<TP>)
auto operator()(TP at, AN... an) const { auto operator()(TP at, AN... an) const {
return submit_at_fn::fn<TP, AN...>{std::move(at), {(AN &&) an...}}; return submit_at_fn::fn<TP, AN...>{std::move(at),
std::tuple<AN...>{(AN &&) an...}};
} }
}; };
...@@ -109,7 +110,7 @@ struct submit_after_fn { ...@@ -109,7 +110,7 @@ struct submit_after_fn {
auto out{ auto out{
::folly::pushmi::detail::receiver_from_fn<In>()(std::move(args_))}; ::folly::pushmi::detail::receiver_from_fn<In>()(std::move(args_))};
auto at = ::folly::pushmi::now(in) + std::move(after_); auto at = ::folly::pushmi::now(in) + std::move(after_);
submit(in, std::move(at), std::move(out)); ::folly::pushmi::submit(in, std::move(at), std::move(out));
return in; return in;
} }
}; };
...@@ -118,7 +119,8 @@ struct submit_after_fn { ...@@ -118,7 +119,8 @@ struct submit_after_fn {
PUSHMI_TEMPLATE(class D, class... AN) PUSHMI_TEMPLATE(class D, class... AN)
(requires Regular<D>) (requires Regular<D>)
auto operator()(D after, AN... an) const { auto operator()(D after, AN... an) const {
return submit_after_fn::fn<D, AN...>{std::move(after), {(AN &&) an...}}; return submit_after_fn::fn<D, AN...>{std::move(after),
std::tuple<AN...>{(AN &&) an...}};
} }
}; };
...@@ -159,7 +161,7 @@ struct blocking_submit_fn { ...@@ -159,7 +161,7 @@ struct blocking_submit_fn {
using properties = properties_t<Exec>; using properties = properties_t<Exec>;
auto executor() { auto executor() {
return make(state_, executor(ex_)); return make(state_, ::folly::pushmi::executor(ex_));
} }
PUSHMI_TEMPLATE(class... ZN) PUSHMI_TEMPLATE(class... ZN)
...@@ -172,14 +174,16 @@ struct blocking_submit_fn { ...@@ -172,14 +174,16 @@ struct blocking_submit_fn {
(requires Receiver<Out>&& Constrained<Exec>) (requires Receiver<Out>&& Constrained<Exec>)
void submit(CV cv, Out out) { void submit(CV cv, Out out) {
++state_->nested; ++state_->nested;
submit(ex_, cv, nested_receiver_impl<Out>{state_, std::move(out)}); ::folly::pushmi::submit(
ex_, cv, nested_receiver_impl<Out>{state_, std::move(out)});
} }
PUSHMI_TEMPLATE(class Out) PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out> && not Constrained<Exec>) (requires Receiver<Out> && not Constrained<Exec>)
void submit(Out out) { void submit(Out out) {
++state_->nested; ++state_->nested;
submit(ex_, nested_receiver_impl<Out>{state_, std::move(out)}); ::folly::pushmi::submit(
ex_, nested_receiver_impl<Out>{state_, std::move(out)});
} }
}; };
template <class Out> template <class Out>
...@@ -293,7 +297,7 @@ struct blocking_submit_fn { ...@@ -293,7 +297,7 @@ struct blocking_submit_fn {
PUSHMI_TEMPLATE(class Out) PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out>&& SenderTo<In, Out>) (requires Receiver<Out>&& SenderTo<In, Out>)
void operator()(In& in, Out out) const { void operator()(In& in, Out out) const {
submit(in, std::move(out)); ::folly::pushmi::submit(in, std::move(out));
} }
}; };
// TODO - only move, move-only types.. // TODO - only move, move-only types..
......
...@@ -203,7 +203,8 @@ class strand_executor { ...@@ -203,7 +203,8 @@ class strand_executor {
queue_->items_.push(any_receiver<E, any_executor_ref<E>>{std::move(out)}); queue_->items_.push(any_receiver<E, any_executor_ref<E>>{std::move(out)});
if (queue_->remaining_ == 0) { if (queue_->remaining_ == 0) {
// noone is minding the shop, send a worker // noone is minding the shop, send a worker
submit(queue_->ex_, strand_queue_receiver<E, Executor>{queue_}); ::folly::pushmi::submit(
queue_->ex_, strand_queue_receiver<E, Executor>{queue_});
} }
} }
}; };
......
...@@ -25,6 +25,11 @@ ...@@ -25,6 +25,11 @@
using namespace folly::pushmi::aliases; using namespace folly::pushmi::aliases;
#include <folly/portability/GMock.h>
#include <folly/portability/GTest.h>
using namespace testing;
using namespace std::literals; using namespace std::literals;
#if __cpp_deduction_guides >= 201703 #if __cpp_deduction_guides >= 201703
...@@ -562,3 +567,5 @@ void flow_many_sender_test() { ...@@ -562,3 +567,5 @@ void flow_many_sender_test() {
mi::Executor<mi::executor_t<decltype(in0)>>, mi::Executor<mi::executor_t<decltype(in0)>>,
"sender has invalid executor"); "sender has invalid executor");
} }
TEST(CompileTest, Test) {}
This diff is collapsed.
...@@ -29,140 +29,169 @@ using namespace std::literals; ...@@ -29,140 +29,169 @@ using namespace std::literals;
#include <folly/experimental/pushmi/o/tap.h> #include <folly/experimental/pushmi/o/tap.h>
#include <folly/experimental/pushmi/o/transform.h> #include <folly/experimental/pushmi/o/transform.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <folly/experimental/pushmi/new_thread.h> #include <folly/experimental/pushmi/new_thread.h>
#include <folly/experimental/pushmi/trampoline.h>
using namespace folly::pushmi::aliases; using namespace folly::pushmi::aliases;
#if 0 #include <folly/portability/GMock.h>
SCENARIO( "empty can be used with tap and submit", "[empty][sender]" ) { #include <folly/portability/GTest.h>
GIVEN( "An empty sender" ) { using namespace testing;
auto e = op::empty();
using E = decltype(e); TEST(EmptyNoArgSingleSender, TapAndSubmit) {
auto e = op::empty();
REQUIRE( v::SenderTo<E, v::any_receiver<>, v::is_single<>> ); using E = decltype(e);
WHEN( "tap and submit are applied" ) { EXPECT_THAT((v::SenderTo<E, v::any_receiver<>, v::is_single<>>), Eq(true))
int signals = 0; << "expected empty to return a single sender that can take an any_receiver";
e |
op::tap( int signals = 0;
[&](){ signals += 100; }, e |
[&](auto e) noexcept { signals += 1000; }, op::tap(
[&](){ signals += 10; }) | [&]() { signals += 100; },
op::submit( [&](auto) noexcept { signals += 1000; },
[&](){ signals += 100; }, [&]() { signals += 10; }) |
[&](auto e) noexcept { signals += 1000; }, op::submit(
[&](){ signals += 10; }); [&]() { signals += 100; },
[&](auto) noexcept { signals += 1000; },
THEN( "the done signal is recorded twice" ) { [&]() { signals += 10; });
REQUIRE( signals == 20 );
} EXPECT_THAT(signals, Eq(20))
<< "expected the done signal to be recorded twice";
WHEN( "future_from is applied" ) {
REQUIRE_THROWS_AS(v::future_from(e).get(), std::future_error); EXPECT_THROW(v::future_from(e).get(), std::future_error)
<< "expected future_error when future_from is applied";
THEN( "future_from(e) returns std::future<void>" ) {
REQUIRE( std::is_same<std::future<void>, decltype(v::future_from(e))>::value ); EXPECT_THAT(
} (std::is_same<std::future<void>, decltype(v::future_from(e))>::value),
} Eq(true))
} << "expected future_from(e) to return std::future<void>";
} }
GIVEN( "An empty int single_sender" ) { TEST(EmptyIntSingleSender, TapAndSubmit) {
auto e = op::empty<int>(); auto e = op::empty<int>();
using E = decltype(e); using E = decltype(e);
REQUIRE( v::SenderTo<E, v::any_receiver<std::exception_ptr, int>, v::is_single<>> ); EXPECT_THAT(
(v::SenderTo<
WHEN( "tap and submit are applied" ) { E,
v::any_receiver<std::exception_ptr, int>,
int signals = 0; v::is_single<>>),
e | Eq(true))
op::tap( << "expected empty to return a single sender that can take an any_receiver<int>";
[&](auto v){ signals += 100; },
[&](auto e) noexcept { signals += 1000; }, int signals = 0;
[&](){ signals += 10; }) | e |
op::submit( op::tap(
[&](auto v){ signals += 100; }, [&](auto) { signals += 100; },
[&](auto e) noexcept { signals += 1000; }, [&](auto) noexcept { signals += 1000; },
[&](){ signals += 10; }); [&]() { signals += 10; }) |
op::submit(
THEN( "the done signal is recorded twice" ) { [&](auto) { signals += 100; },
REQUIRE( signals == 20 ); [&](auto) noexcept { signals += 1000; },
} [&]() { signals += 10; });
}
} EXPECT_THAT(signals, Eq(20))
<< "expected the done signal to be recorded twice";
EXPECT_THROW(v::future_from<int>(e).get(), std::future_error)
<< "expected future_error when future_from is applied";
EXPECT_THAT(
(std::is_same<std::future<int>, decltype(v::future_from<int>(e))>::value),
Eq(true))
<< "expected future_from(e) to return std::future<void>";
} }
SCENARIO( "just() can be used with transform and submit", "[just][sender]" ) { TEST(JustIntSingleSender, TransformAndSubmit) {
auto j = op::just(20);
GIVEN( "A just int single_sender" ) { using J = decltype(j);
auto j = op::just(20);
using J = decltype(j); EXPECT_THAT(
(v::SenderTo<
REQUIRE( v::SenderTo<J, v::any_receiver<std::exception_ptr, int>, v::is_single<>> ); J,
v::any_receiver<std::exception_ptr, int>,
WHEN( "transform and submit are applied" ) { v::is_single<>>),
int signals = 0; Eq(true))
int value = 0; << "expected empty to return a single sender that can take an any_receiver<int>";
j |
op::transform( int signals = 0;
[&](int v){ signals += 10000; return v + 1; }, int value = 0;
[&](auto v){ std:abort(); return v; }) | j |
op::transform( op::transform(
[&](int v){ signals += 10000; return v * 2; }) | [&](int v) {
op::submit( signals += 10000;
[&](auto v){ value = v; signals += 100; }, return v + 1;
[&](auto e) noexcept { signals += 1000; }, },
[&](){ signals += 10; }); [&](auto v) {
std::abort();
THEN( "the transform signal is recorded twice, the value and done signals once and the result is correct" ) { return v;
REQUIRE( signals == 20110 ); }) |
REQUIRE( value == 42 ); op::transform([&](int v) {
} signals += 10000;
} return v * 2;
}) |
WHEN( "future_from<int> is applied" ) { op::submit(
auto twenty = v::future_from<int>(j).get(); [&](auto v) {
value = v;
THEN( "the value signal is recorded once and the result is correct" ) { signals += 100;
REQUIRE( twenty == 20 ); },
REQUIRE( std::is_same<std::future<int>, decltype(v::future_from<int>(j))>::value ); [&](auto) noexcept { signals += 1000; },
} [&]() { signals += 10; });
}
} EXPECT_THAT(signals, Eq(20110))
<< "expected that the transform signal is recorded twice and that the value and done signals once each";
EXPECT_THAT(value, Eq(42)) << "expected a different result";
auto twenty = v::future_from<int>(j).get();
EXPECT_THAT(twenty, Eq(20))
<< "expected a different result from future_from(e).get()";
EXPECT_THAT(
(std::is_same<std::future<int>, decltype(v::future_from<int>(j))>::value),
Eq(true))
<< "expected future_from(e) to return std::future<int>";
} }
SCENARIO( "from() can be used with transform and submit", "[from][sender]" ) { TEST(FromIntManySender, TransformAndSubmit) {
std::array<int, 3> arr{0, 9, 99};
GIVEN( "A from int many_sender" ) { auto m = op::from(arr);
int arr[] = {0, 9, 99}; using M = decltype(m);
auto m = op::from(arr);
using M = decltype(m); EXPECT_THAT(
(v::SenderTo<M, v::any_receiver<std::exception_ptr, int>, v::is_many<>>),
REQUIRE( v::SenderTo<M, v::any_receiver<std::exception_ptr, int>, v::is_many<>> ); Eq(true))
<< "expected empty to return a many sender that can take an any_receiver<int>";
WHEN( "transform and submit are applied" ) {
int signals = 0; int signals = 0;
int value = 0; int value = 0;
m | m |
op::transform( op::transform(
[&](int v){ signals += 10000; return v + 1; }, [&](int v) {
[&](auto v){ std:abort(); return v; }) | signals += 10000;
op::transform( return v + 1;
[&](int v){ signals += 10000; return v * 2; }) | },
op::submit( [&](auto v) {
[&](auto v){ value += v; signals += 100; }, std::abort();
[&](auto e) noexcept { signals += 1000; }, return v;
[&](){ signals += 10; }); }) |
op::transform([&](int v) {
THEN( "the transform signal is recorded twice, the value signal once and the result is correct" ) { signals += 10000;
REQUIRE( signals == 60310 ); return v * 2;
REQUIRE( value == 222 ); }) |
} op::submit(
} [&](auto v) {
value += v;
} signals += 100;
},
[&](auto) noexcept { signals += 1000; },
[&]() { signals += 10; });
EXPECT_THAT(signals, Eq(60310))
<< "expected that the transform signal is recorded six times and that the value signal three times and done signal once";
EXPECT_THAT(value, Eq(222)) << "expected a different result";
} }
#endif
...@@ -21,23 +21,28 @@ using namespace std::literals; ...@@ -21,23 +21,28 @@ using namespace std::literals;
#include <folly/experimental/pushmi/flow_single_sender.h> #include <folly/experimental/pushmi/flow_single_sender.h>
#include <folly/experimental/pushmi/o/empty.h> #include <folly/experimental/pushmi/o/empty.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/just.h> #include <folly/experimental/pushmi/o/just.h>
#include <folly/experimental/pushmi/o/on.h> #include <folly/experimental/pushmi/o/on.h>
#include <folly/experimental/pushmi/o/transform.h> #include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/o/tap.h> #include <folly/experimental/pushmi/o/tap.h>
#include <folly/experimental/pushmi/o/transform.h>
#include <folly/experimental/pushmi/o/via.h> #include <folly/experimental/pushmi/o/via.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/inline.h> #include <folly/experimental/pushmi/inline.h>
#include <folly/experimental/pushmi/trampoline.h> #include <folly/experimental/pushmi/trampoline.h>
using namespace folly::pushmi::aliases; using namespace folly::pushmi::aliases;
#if 0 #include <folly/Conv.h>
#include <folly/portability/GMock.h>
#include <folly/portability/GTest.h>
using namespace testing;
struct countdownsingle { struct countdownsingle {
countdownsingle(int& c) explicit countdownsingle(int& c) : counter(&c) {}
: counter(&c) {}
int* counter; int* counter;
...@@ -49,102 +54,102 @@ struct countdownsingle { ...@@ -49,102 +54,102 @@ struct countdownsingle {
} }
}; };
SCENARIO( "trampoline executor", "[trampoline][sender]" ) { using TR = decltype(mi::trampoline());
GIVEN( "A trampoline single_sender" ) {
auto tr = v::trampoline();
using TR = decltype(tr);
WHEN( "submit" ) {
auto signals = 0;
tr |
op::transform([](auto){ return 42; }) |
op::submit(
[&](auto){
signals += 100; },
[&](auto e) noexcept { signals += 1000; },
[&](){ signals += 10; });
THEN( "the value and done signals are each recorded once" ) {
REQUIRE( signals == 110 );
}
}
WHEN( "blocking get" ) { class TrampolineExecutor : public Test {
auto v = tr | protected:
op::transform([](auto){ return 42; }) | TR tr_{mi::trampoline()};
op::get<int>; };
THEN( "the result is" ) { TEST_F(TrampolineExecutor, TransformAndSubmit) {
REQUIRE( v == 42 ); auto signals = 0;
} tr_ | op::transform([](auto) { return 42; }) |
} op::submit(
[&](auto) { signals += 100; },
[&](auto) noexcept { signals += 1000; },
[&]() { signals += 10; });
WHEN( "virtual derecursion is triggered" ) { EXPECT_THAT(signals, Eq(110))
int counter = 100'000; << "expected that the value and done signals are each recorded once";
std::function<void(::folly::pushmi::any_executor_ref<> exec)> recurse; }
recurse = [&](::folly::pushmi::any_executor_ref<> tr) {
if (--counter <= 0)
return;
tr | op::submit(recurse);
};
tr | op::submit([&](auto exec) { recurse(exec); });
THEN( "all nested submissions complete" ) {
REQUIRE( counter == 0 );
}
}
WHEN( "static derecursion is triggered" ) { TEST_F(TrampolineExecutor, BlockingGet) {
int counter = 100'000; auto v = tr_ | op::transform([](auto) { return 42; }) | op::get<int>;
countdownsingle single{counter};
tr | op::submit(single);
THEN( "all nested submissions complete" ) {
REQUIRE( counter == 0 );
}
}
WHEN( "used with on" ) { EXPECT_THAT(v, Eq(42)) << "expected that the result would be different";
std::vector<std::string> values; }
auto sender = ::folly::pushmi::make_single_sender([](auto out) {
::folly::pushmi::set_value(out, 2.0);
::folly::pushmi::set_done(out);
// ignored
::folly::pushmi::set_value(out, 1);
::folly::pushmi::set_value(out, std::numeric_limits<int8_t>::min());
::folly::pushmi::set_value(out, std::numeric_limits<int8_t>::max());
});
auto inlineon = sender | op::on([&](){return mi::inline_executor();});
inlineon |
op::submit(v::on_value([&](auto v) { values.push_back(std::to_string(v)); }));
THEN( "only the first item was pushed" ) {
REQUIRE(values == std::vector<std::string>{"2.000000"});
}
THEN( "executor was not changed by on" ) {
REQUIRE(std::is_same<mi::executor_t<decltype(sender)>, mi::executor_t<decltype(inlineon)>>::value);
}
}
WHEN( "used with via" ) { TEST_F(TrampolineExecutor, VirtualDerecursion) {
std::vector<std::string> values; int counter = 100'000;
auto sender = ::folly::pushmi::make_single_sender([](auto out) { std::function<void(::folly::pushmi::any_executor_ref<> exec)> recurse;
::folly::pushmi::set_value(out, 2.0); recurse = [&](::folly::pushmi::any_executor_ref<> tr) {
::folly::pushmi::set_done(out); if (--counter <= 0)
// ignored return;
::folly::pushmi::set_value(out, 1); tr | op::submit(recurse);
::folly::pushmi::set_value(out, std::numeric_limits<int8_t>::min()); };
::folly::pushmi::set_value(out, std::numeric_limits<int8_t>::max()); tr_ | op::submit([&](auto exec) { recurse(exec); });
});
auto inlinevia = sender | op::via([&](){return mi::inline_executor();}); EXPECT_THAT(counter, Eq(0))
inlinevia | << "expected that all nested submissions complete";
op::submit(v::on_value([&](auto v) { values.push_back(std::to_string(v)); })); }
THEN( "only the first item was pushed" ) {
REQUIRE(values == std::vector<std::string>{"2.000000"}); TEST_F(TrampolineExecutor, StaticDerecursion) {
} int counter = 100'000;
THEN( "executor was changed by via" ) { countdownsingle single{counter};
REQUIRE(!std::is_same<mi::executor_t<decltype(sender)>, mi::executor_t<decltype(inlinevia)>>::value); tr_ | op::submit(single);
}
} EXPECT_THAT(counter, Eq(0))
} << "expected that all nested submissions complete";
}
TEST_F(TrampolineExecutor, UsedWithOn) {
std::vector<std::string> values;
auto sender = ::folly::pushmi::make_single_sender([](auto out) {
::folly::pushmi::set_value(out, 2.0);
::folly::pushmi::set_done(out);
// ignored
::folly::pushmi::set_value(out, 1);
::folly::pushmi::set_value(out, std::numeric_limits<int8_t>::min());
::folly::pushmi::set_value(out, std::numeric_limits<int8_t>::max());
});
auto inlineon = sender | op::on([&]() { return mi::inline_executor(); });
inlineon | op::submit(v::on_value([&](auto v) {
values.push_back(folly::to<std::string>(v));
}));
EXPECT_THAT(values, ElementsAre(folly::to<std::string>(2.0)))
<< "expected that only the first item was pushed";
EXPECT_THAT(
(std::is_same<
mi::executor_t<decltype(sender)>,
mi::executor_t<decltype(inlineon)>>::value),
Eq(true))
<< "expected that executor was not changed by on";
}
TEST_F(TrampolineExecutor, UsedWithVia) {
std::vector<std::string> values;
auto sender = ::folly::pushmi::make_single_sender([](auto out) {
::folly::pushmi::set_value(out, 2.0);
::folly::pushmi::set_done(out);
// ignored
::folly::pushmi::set_value(out, 1);
::folly::pushmi::set_value(out, std::numeric_limits<int8_t>::min());
::folly::pushmi::set_value(out, std::numeric_limits<int8_t>::max());
});
auto inlinevia = sender | op::via([&]() { return mi::inline_executor(); });
inlinevia | op::submit(v::on_value([&](auto v) {
values.push_back(folly::to<std::string>(v));
}));
EXPECT_THAT(values, ElementsAre(folly::to<std::string>(2.0)))
<< "expected that only the first item was pushed";
EXPECT_THAT(
(!std::is_same<
mi::executor_t<decltype(sender)>,
mi::executor_t<decltype(inlinevia)>>::value),
Eq(true))
<< "expected that executor was changed by via";
} }
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment