proxygen
RetryingTest.cpp File Reference
#include <algorithm>
#include <atomic>
#include <vector>
#include <folly/futures/Retrying.h>
#include <folly/futures/test/TestExecutor.h>
#include <folly/portability/GTest.h>
#include <folly/portability/SysResource.h>

Go to the source code of this file.

Functions

template<typename D , typename F >
void multiAttemptExpectDurationWithin (size_t num_tries, D min_duration, D max_duration, const F &func)
 
 TEST (RetryingTest, has_op_call)
 
 TEST (RetryingTest, basic)
 
 TEST (RetryingTest, future_factory_throws)
 
 TEST (RetryingTest, policy_throws)
 
 TEST (RetryingTest, policy_future)
 
 TEST (RetryingTest, policy_basic)
 
 TEST (RetryingTest, policy_capped_jittered_exponential_backoff)
 
 TEST (RetryingTest, policy_capped_jittered_exponential_backoff_many_retries)
 
 TEST (RetryingTest, policy_sleep_defaults)
 
 TEST (RetryingTest, large_retries)
 

Function Documentation

template<typename D , typename F >
void multiAttemptExpectDurationWithin ( size_t  num_tries,
D  min_duration,
D  max_duration,
const F &  func 
)

Definition at line 34 of file RetryingTest.cpp.

References D, EXPECT_GE, EXPECT_LE, i, min, now(), start, folly::pushmi::detail::t, and threads.

Referenced by TEST().

38  {
39  vector<thread> threads(num_tries);
40  vector<D> durations(num_tries, D::min());
41  for (size_t i = 0; i < num_tries; ++i) {
42  threads[i] = thread([&, i] {
43  auto start = steady_clock::now();
44  func();
45  durations[i] = duration_cast<D>(steady_clock::now() - start);
46  });
47  }
48  for (auto& t : threads) {
49  t.join();
50  }
51  sort(durations.begin(), durations.end());
52  for (auto d : durations) {
53  EXPECT_GE(d, min_duration);
54  }
55  EXPECT_LE(durations[0], max_duration);
56 }
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
std::chrono::steady_clock::time_point now()
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
std::vector< std::thread::id > threads
LogLevel min
Definition: LogLevel.cpp:30
#define D(name, bit)
Definition: CpuId.h:145
auto start
TEST ( RetryingTest  ,
has_op_call   
)

Definition at line 58 of file RetryingTest.cpp.

References EXPECT_TRUE, folly::makeFuture(), and value.

58  {
59  using ew = exception_wrapper;
60  auto policy_raw = [](size_t n, const ew&) { return n < 3; };
61  auto policy_fut = [](size_t n, const ew&) { return makeFuture(n < 3); };
62  using namespace futures::detail;
63  EXPECT_TRUE(retrying_policy_traits<decltype(policy_raw)>::is_raw::value);
64  EXPECT_TRUE(retrying_policy_traits<decltype(policy_fut)>::is_fut::value);
65 }
static const char *const value
Definition: Conv.cpp:50
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
TEST ( RetryingTest  ,
basic   
)

Definition at line 67 of file RetryingTest.cpp.

References EXPECT_EQ, folly::makeFuture(), folly::futures::retrying(), and folly::detail::distributed_mutex::wait().

67  {
68  auto r = futures::retrying(
69  [](size_t n, const exception_wrapper&) { return n < 3; },
70  [](size_t n) {
71  return n < 2 ? makeFuture<size_t>(runtime_error("ha"))
72  : makeFuture(n);
73  })
74  .wait();
75  EXPECT_EQ(2, r.value());
76 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
bool wait(Waiter *waiter, bool shouldSleep, Waiter *&next)
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
invoke_result_t< FF, size_t > retrying(Policy &&p, FF &&ff)
Definition: Retrying.h:234
TEST ( RetryingTest  ,
future_factory_throws   
)

Definition at line 78 of file RetryingTest.cpp.

References EXPECT_THROW, folly::makeFuture(), folly::futures::retrying(), and folly::detail::distributed_mutex::wait().

78  {
79  struct ReturnedException : exception {};
80  struct ThrownException : exception {};
81  auto result = futures::retrying(
82  [](size_t n, const exception_wrapper&) { return n < 2; },
83  [](size_t n) {
84  switch (n) {
85  case 0:
86  return makeFuture<size_t>(
87  make_exception_wrapper<ReturnedException>());
88  case 1:
89  throw ThrownException();
90  default:
91  return makeFuture(n);
92  }
93  })
94  .wait()
95  .getTry();
96  EXPECT_THROW(result.throwIfFailed(), ThrownException);
97 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
bool wait(Waiter *waiter, bool shouldSleep, Waiter *&next)
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
invoke_result_t< FF, size_t > retrying(Policy &&p, FF &&ff)
Definition: Retrying.h:234
TEST ( RetryingTest  ,
policy_throws   
)

Definition at line 99 of file RetryingTest.cpp.

References eggs, EXPECT_THROW, folly::gen::move, and folly::futures::retrying().

99  {
100  struct eggs : exception {};
101  auto r = futures::retrying(
102  [](size_t, exception_wrapper) -> bool { throw eggs(); },
103  [](size_t) -> Future<size_t> { throw std::runtime_error("ha"); });
104  EXPECT_THROW(std::move(r).get(), eggs);
105 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
static eggs_t eggs("eggs")
invoke_result_t< FF, size_t > retrying(Policy &&p, FF &&ff)
Definition: Retrying.h:234
TEST ( RetryingTest  ,
policy_future   
)

Definition at line 107 of file RetryingTest.cpp.

References EXPECT_EQ, folly::makeFuture(), folly::futures::retrying(), and folly::detail::distributed_mutex::wait().

107  {
108  atomic<size_t> sleeps{0};
109  auto r =
111  [&](size_t n, const exception_wrapper&) {
112  return n < 3
113  ? makeFuture(++sleeps).thenValue([](auto&&) { return true; })
114  : makeFuture(false);
115  },
116  [](size_t n) {
117  return n < 2 ? makeFuture<size_t>(runtime_error("ha"))
118  : makeFuture(n);
119  })
120  .wait();
121  EXPECT_EQ(2, r.value());
122  EXPECT_EQ(2, sleeps);
123 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
bool wait(Waiter *waiter, bool shouldSleep, Waiter *&next)
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
invoke_result_t< FF, size_t > retrying(Policy &&p, FF &&ff)
Definition: Retrying.h:234
TEST ( RetryingTest  ,
policy_basic   
)

Definition at line 125 of file RetryingTest.cpp.

References EXPECT_EQ, folly::makeFuture(), folly::futures::retrying(), folly::futures::retryingPolicyBasic(), and folly::detail::distributed_mutex::wait().

125  {
126  auto r = futures::retrying(
128  [](size_t n) {
129  return n < 2 ? makeFuture<size_t>(runtime_error("ha"))
130  : makeFuture(n);
131  })
132  .wait();
133  EXPECT_EQ(2, r.value());
134 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
bool wait(Waiter *waiter, bool shouldSleep, Waiter *&next)
std::function< bool(size_t, const exception_wrapper &)> retryingPolicyBasic(size_t max_tries)
Definition: Retrying.h:240
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
invoke_result_t< FF, size_t > retrying(Policy &&p, FF &&ff)
Definition: Retrying.h:234
TEST ( RetryingTest  ,
policy_capped_jittered_exponential_backoff   
)

Definition at line 136 of file RetryingTest.cpp.

References EXPECT_EQ, folly::makeFuture(), multiAttemptExpectDurationWithin(), folly::futures::retrying(), folly::futures::detail::retryingPolicyCappedJitteredExponentialBackoff(), and folly::detail::distributed_mutex::wait().

136  {
137  multiAttemptExpectDurationWithin(5, milliseconds(200), milliseconds(400), [] {
138  using ms = milliseconds;
139  auto r = futures::retrying(
141  3,
142  ms(100),
143  ms(1000),
144  0.1,
145  mt19937_64(0),
146  [](size_t, const exception_wrapper&) { return true; }),
147  [](size_t n) {
148  return n < 2 ? makeFuture<size_t>(runtime_error("ha"))
149  : makeFuture(n);
150  })
151  .wait();
152  EXPECT_EQ(2, r.value());
153  });
154 }
std::function< Future< bool >size_t, const exception_wrapper &)> retryingPolicyCappedJitteredExponentialBackoff(size_t max_tries, Duration backoff_min, Duration backoff_max, double jitter_param, URNG &&rng, Policy &&p)
Definition: Retrying.h:159
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
bool wait(Waiter *waiter, bool shouldSleep, Waiter *&next)
void multiAttemptExpectDurationWithin(size_t num_tries, D min_duration, D max_duration, const F &func)
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
invoke_result_t< FF, size_t > retrying(Policy &&p, FF &&ff)
Definition: Retrying.h:234
TEST ( RetryingTest  ,
policy_capped_jittered_exponential_backoff_many_retries   
)

Definition at line 156 of file RetryingTest.cpp.

References EXPECT_EQ, EXPECT_LT, max, folly::futures::detail::retryingJitteredExponentialBackoffDur(), and rng.

156  {
157  using namespace futures::detail;
158  mt19937_64 rng(0);
159  Duration min_backoff(1);
160 
161  Duration max_backoff(10000000);
163  80, min_backoff, max_backoff, 0, rng);
164  EXPECT_EQ(backoff, max_backoff);
165 
168  63, min_backoff, max_backoff, 0, rng);
169  EXPECT_LT(backoff, max_backoff);
170 
173  64, min_backoff, max_backoff, 0, rng);
174  EXPECT_EQ(backoff, max_backoff);
175 }
LogLevel max
Definition: LogLevel.cpp:31
Duration retryingJitteredExponentialBackoffDur(size_t n, Duration backoff_min, Duration backoff_max, double jitter_param, URNG &rng)
Definition: Retrying.h:141
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
auto rng
Definition: CollectTest.cpp:31
std::chrono::milliseconds Duration
Definition: Types.h:36
StatsClock::duration Duration
#define EXPECT_LT(val1, val2)
Definition: gtest.h:1930
TEST ( RetryingTest  ,
policy_sleep_defaults   
)

Definition at line 177 of file RetryingTest.cpp.

References EXPECT_EQ, folly::makeFuture(), multiAttemptExpectDurationWithin(), folly::futures::retrying(), folly::futures::detail::retryingPolicyCappedJitteredExponentialBackoff(), and folly::detail::distributed_mutex::wait().

177  {
178  multiAttemptExpectDurationWithin(5, milliseconds(200), milliseconds(400), [] {
179  // To ensure that this compiles with default params.
180  using ms = milliseconds;
181  auto r = futures::retrying(
183  3, ms(100), ms(1000), 0.1),
184  [](size_t n) {
185  return n < 2 ? makeFuture<size_t>(runtime_error("ha"))
186  : makeFuture(n);
187  })
188  .wait();
189  EXPECT_EQ(2, r.value());
190  });
191 }
std::function< Future< bool >size_t, const exception_wrapper &)> retryingPolicyCappedJitteredExponentialBackoff(size_t max_tries, Duration backoff_min, Duration backoff_max, double jitter_param, URNG &&rng, Policy &&p)
Definition: Retrying.h:159
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
bool wait(Waiter *waiter, bool shouldSleep, Waiter *&next)
void multiAttemptExpectDurationWithin(size_t num_tries, D min_duration, D max_duration, const F &func)
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
invoke_result_t< FF, size_t > retrying(Policy &&p, FF &&ff)
Definition: Retrying.h:234
TEST ( RetryingTest  ,
large_retries   
)

Definition at line 193 of file RetryingTest.cpp.

References folly::pushmi::executor, EXPECT_TRUE, f, folly::kIsSanitizeAddress, min, folly::futures::retrying(), SCOPE_EXIT, and folly::pushmi::operators::via.

193  {
194 #ifndef _WIN32
195  rlimit oldMemLimit;
196  PCHECK(getrlimit(RLIMIT_AS, &oldMemLimit) == 0);
197 
198  rlimit newMemLimit;
199  newMemLimit.rlim_cur =
200  std::min(static_cast<rlim_t>(1UL << 30), oldMemLimit.rlim_max);
201  newMemLimit.rlim_max = oldMemLimit.rlim_max;
202  if (!folly::kIsSanitizeAddress) { // ASAN reserves outside of the rlimit
203  PCHECK(setrlimit(RLIMIT_AS, &newMemLimit) == 0);
204  }
205  SCOPE_EXIT {
206  PCHECK(setrlimit(RLIMIT_AS, &oldMemLimit) == 0);
207  };
208 #endif
209 
211  // size of implicit promise is at least the size of the return.
212  using LargeReturn = array<uint64_t, 16000>;
213  auto func = [&executor](size_t retryNum) -> Future<LargeReturn> {
214  return via(&executor).thenValue([retryNum](auto&&) {
215  return retryNum < 10000
216  ? makeFuture<LargeReturn>(
217  make_exception_wrapper<std::runtime_error>("keep trying"))
218  : makeFuture<LargeReturn>(LargeReturn());
219  });
220  };
221 
222  vector<Future<LargeReturn>> futures;
223  for (auto idx = 0; idx < 40; ++idx) {
224  futures.emplace_back(futures::retrying(
225  [&executor](size_t, const exception_wrapper&) {
226  return via(&executor).thenValue([](auto&&) { return true; });
227  },
228  func));
229  }
230 
231  // 40 * 10,000 * 16,000B > 1GB; we should avoid OOM
232 
233  for (auto& f : futures) {
234  f.wait();
235  EXPECT_TRUE(f.hasValue());
236  }
237 }
auto f
constexpr bool kIsSanitizeAddress
Definition: Portability.h:118
#define SCOPE_EXIT
Definition: ScopeGuard.h:274
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
PUSHMI_INLINE_VAR constexpr detail::via_fn via
Definition: via.h:166
LogLevel min
Definition: LogLevel.cpp:30
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
invoke_result_t< FF, size_t > retrying(Policy &&p, FF &&ff)
Definition: Retrying.h:234