Commit b70fcab6 authored by Nathan Bronson's avatar Nathan Bronson Committed by facebook-github-bot-4

make RetryingTest more robust

Summary: Make RetryingTest more robust by giving it multiple chances to
meeting timing criteria.

Reviewed By: @yfeldblum

Differential Revision: D2306245
parent 77f6a914
...@@ -14,8 +14,10 @@ ...@@ -14,8 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
#include <algorithm>
#include <atomic> #include <atomic>
#include <exception> #include <exception>
#include <vector>
#include <folly/futures/Future.h> #include <folly/futures/Future.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
...@@ -24,6 +26,33 @@ using namespace std; ...@@ -24,6 +26,33 @@ using namespace std;
using namespace std::chrono; using namespace std::chrono;
using namespace folly; using namespace folly;
// Runs func num_times in parallel, expects that all of them will take
// at least min_duration and at least 1 execution will take less than
// max_duration.
template <typename D, typename F>
void multiAttemptExpectDurationWithin(size_t num_tries,
D min_duration,
D max_duration,
const F& func) {
vector<thread> threads(num_tries);
vector<D> durations(num_tries, D::min());
for (size_t i = 0; i < num_tries; ++i) {
threads[i] = thread([&,i]{
auto start = steady_clock::now();
func();
durations[i] = duration_cast<D>(steady_clock::now() - start);
});
}
for (auto& t : threads) {
t.join();
}
sort(durations.begin(), durations.end());
for (auto d : durations) {
EXPECT_GE(d, min_duration);
}
EXPECT_LE(durations[0], max_duration);
}
TEST(RetryingTest, has_op_call) { TEST(RetryingTest, has_op_call) {
using ew = exception_wrapper; using ew = exception_wrapper;
auto policy_raw = [](size_t n, const ew&) { return n < 3; }; auto policy_raw = [](size_t n, const ew&) { return n < 3; };
...@@ -76,8 +105,8 @@ TEST(RetryingTest, policy_basic) { ...@@ -76,8 +105,8 @@ TEST(RetryingTest, policy_basic) {
} }
TEST(RetryingTest, policy_capped_jittered_exponential_backoff) { TEST(RetryingTest, policy_capped_jittered_exponential_backoff) {
multiAttemptExpectDurationWithin(5, milliseconds(200), milliseconds(400), []{
using ms = milliseconds; using ms = milliseconds;
auto start = steady_clock::now();
auto r = futures::retrying( auto r = futures::retrying(
futures::retryingPolicyCappedJitteredExponentialBackoff( futures::retryingPolicyCappedJitteredExponentialBackoff(
3, ms(100), ms(1000), 0.1, mt19937_64(0), 3, ms(100), ms(1000), 0.1, mt19937_64(0),
...@@ -88,19 +117,14 @@ TEST(RetryingTest, policy_capped_jittered_exponential_backoff) { ...@@ -88,19 +117,14 @@ TEST(RetryingTest, policy_capped_jittered_exponential_backoff) {
: makeFuture(n); : makeFuture(n);
} }
).wait(); ).wait();
auto finish = steady_clock::now();
auto duration = duration_cast<milliseconds>(finish - start);
EXPECT_EQ(2, r.value()); EXPECT_EQ(2, r.value());
EXPECT_NEAR( });
milliseconds(300).count(),
duration.count(),
milliseconds(25).count());
} }
TEST(RetryingTest, policy_sleep_defaults) { TEST(RetryingTest, policy_sleep_defaults) {
multiAttemptExpectDurationWithin(5, milliseconds(200), milliseconds(400), []{
// To ensure that this compiles with default params. // To ensure that this compiles with default params.
using ms = milliseconds; using ms = milliseconds;
auto start = steady_clock::now();
auto r = futures::retrying( auto r = futures::retrying(
futures::retryingPolicyCappedJitteredExponentialBackoff( futures::retryingPolicyCappedJitteredExponentialBackoff(
3, ms(100), ms(1000), 0.1), 3, ms(100), ms(1000), 0.1),
...@@ -110,20 +134,15 @@ TEST(RetryingTest, policy_sleep_defaults) { ...@@ -110,20 +134,15 @@ TEST(RetryingTest, policy_sleep_defaults) {
: makeFuture(n); : makeFuture(n);
} }
).wait(); ).wait();
auto finish = steady_clock::now();
auto duration = duration_cast<milliseconds>(finish - start);
EXPECT_EQ(2, r.value()); EXPECT_EQ(2, r.value());
EXPECT_NEAR( });
milliseconds(300).count(),
duration.count(),
milliseconds(100).count());
} }
/* /*
TEST(RetryingTest, policy_sleep_cancel) { TEST(RetryingTest, policy_sleep_cancel) {
multiAttemptExpectDurationWithin(5, milliseconds(0), milliseconds(10), []{
mt19937_64 rng(0); mt19937_64 rng(0);
using ms = milliseconds; using ms = milliseconds;
auto start = steady_clock::now();
auto r = futures::retrying( auto r = futures::retrying(
futures::retryingPolicyCappedJitteredExponentialBackoff( futures::retryingPolicyCappedJitteredExponentialBackoff(
5, ms(100), ms(1000), 0.1, rng, 5, ms(100), ms(1000), 0.1, rng,
...@@ -136,12 +155,7 @@ TEST(RetryingTest, policy_sleep_cancel) { ...@@ -136,12 +155,7 @@ TEST(RetryingTest, policy_sleep_cancel) {
); );
r.cancel(); r.cancel();
r.wait(); r.wait();
auto finish = steady_clock::now();
auto duration = duration_cast<milliseconds>(finish - start);
EXPECT_EQ(2, r.value()); EXPECT_EQ(2, r.value());
EXPECT_NEAR( });
milliseconds(0).count(),
duration.count(),
milliseconds(10).count());
} }
*/ */
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