proxygen
TrampolineTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <type_traits>
18 
19 #include <chrono>
20 using namespace std::literals;
21 
31 
34 
35 using namespace folly::pushmi::aliases;
36 
37 #include <folly/Conv.h>
38 
41 
42 using namespace testing;
43 
44 struct countdownsingle {
45  explicit countdownsingle(int& c) : counter(&c) {}
46 
47  int* counter;
48 
49  template <class ExecutorRef>
50  void operator()(ExecutorRef exec) {
51  if (--*counter > 0) {
52  exec | op::submit(*this);
53  }
54  }
55 };
56 
57 using TR = decltype(mi::trampoline());
58 
59 class TrampolineExecutor : public Test {
60  protected:
62 };
63 
64 TEST_F(TrampolineExecutor, TransformAndSubmit) {
65  auto signals = 0;
66  tr_ | op::transform([](auto) { return 42; }) |
67  op::submit(
68  [&](auto) { signals += 100; },
69  [&](auto) noexcept { signals += 1000; },
70  [&]() { signals += 10; });
71 
72  EXPECT_THAT(signals, Eq(110))
73  << "expected that the value and done signals are each recorded once";
74 }
75 
76 TEST_F(TrampolineExecutor, BlockingGet) {
77  auto v = tr_ | op::transform([](auto) { return 42; }) | op::get<int>;
78 
79  EXPECT_THAT(v, Eq(42)) << "expected that the result would be different";
80 }
81 
82 TEST_F(TrampolineExecutor, VirtualDerecursion) {
83  int counter = 100'000;
84  std::function<void(::folly::pushmi::any_executor_ref<> exec)> recurse;
85  recurse = [&](::folly::pushmi::any_executor_ref<> tr) {
86  if (--counter <= 0)
87  return;
88  tr | op::submit(recurse);
89  };
90  tr_ | op::submit([&](auto exec) { recurse(exec); });
91 
92  EXPECT_THAT(counter, Eq(0))
93  << "expected that all nested submissions complete";
94 }
95 
96 TEST_F(TrampolineExecutor, StaticDerecursion) {
97  int counter = 100'000;
98  countdownsingle single{counter};
99  tr_ | op::submit(single);
100 
101  EXPECT_THAT(counter, Eq(0))
102  << "expected that all nested submissions complete";
103 }
104 
106  std::vector<std::string> values;
107  auto sender = ::folly::pushmi::make_single_sender([](auto out) {
108  ::folly::pushmi::set_value(out, 2.0);
110  // ignored
114  });
115  auto inlineon = sender | op::on([&]() { return mi::inline_executor(); });
116  inlineon | op::submit(v::on_value([&](auto v) {
117  values.push_back(folly::to<std::string>(v));
118  }));
119 
120  EXPECT_THAT(values, ElementsAre(folly::to<std::string>(2.0)))
121  << "expected that only the first item was pushed";
122 
123  EXPECT_THAT(
124  (std::is_same<
125  mi::executor_t<decltype(sender)>,
126  mi::executor_t<decltype(inlineon)>>::value),
127  Eq(true))
128  << "expected that executor was not changed by on";
129 }
130 
131 TEST_F(TrampolineExecutor, UsedWithVia) {
132  std::vector<std::string> values;
133  auto sender = ::folly::pushmi::make_single_sender([](auto out) {
134  ::folly::pushmi::set_value(out, 2.0);
136  // ignored
140  });
141  auto inlinevia = sender | op::via([&]() { return mi::inline_executor(); });
142  inlinevia | op::submit(v::on_value([&](auto v) {
143  values.push_back(folly::to<std::string>(v));
144  }));
145 
146  EXPECT_THAT(values, ElementsAre(folly::to<std::string>(2.0)))
147  << "expected that only the first item was pushed";
148 
149  EXPECT_THAT(
150  (!std::is_same<
151  mi::executor_t<decltype(sender)>,
152  mi::executor_t<decltype(inlinevia)>>::value),
153  Eq(true))
154  << "expected that executor was changed by via";
155 }
TEST_F(TrampolineExecutor, TransformAndSubmit)
auto on_value(Fns...fns) -> on_value_fn< Fns... >
Definition: boosters.h:262
detail::delegator< E > trampoline()
Definition: trampoline.h:261
LogLevel max
Definition: LogLevel.cpp:31
internal::EqMatcher< T > Eq(T x)
void operator()(ExecutorRef exec)
requires E e noexcept(noexcept(s.error(std::move(e))))
decltype(tr) TR
PUSHMI_INLINE_VAR constexpr detail::transform_fn transform
Definition: transform.h:158
PUSHMI_INLINE_VAR constexpr detail::via_fn via
Definition: via.h:166
LogLevel min
Definition: LogLevel.cpp:30
static const char *const value
Definition: Conv.cpp:50
countdownsingle single
#define EXPECT_THAT(value, matcher)
std::atomic< int > counter
PUSHMI_INLINE_VAR constexpr __adl::set_value_fn set_value
inline_executor_t inline_executor()
Definition: inline.h:113
char c
internal::ElementsAreMatcher< ::testing::tuple<> > ElementsAre()
PUSHMI_INLINE_VAR constexpr detail::on_fn on
Definition: on.h:100
PUSHMI_INLINE_VAR constexpr struct folly::pushmi::make_single_sender_fn make_single_sender
std::vector< int > values(1'000)
PUSHMI_INLINE_VAR constexpr __adl::set_done_fn set_done