206022305abb7c90b4cd51b00d0a17d75c461392
[folly.git] / folly / futures / test / RetryingTest.cpp
1 /*
2  * Copyright 2015 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 <atomic>
18 #include <exception>
19 #include <folly/futures/Future.h>
20
21 #include <gtest/gtest.h>
22
23 using namespace std;
24 using namespace std::chrono;
25 using namespace folly;
26
27 TEST(RetryingTest, has_op_call) {
28   using ew = exception_wrapper;
29   auto policy_raw = [](size_t n, const ew&) { return n < 3; };
30   auto policy_fut = [](size_t n, const ew&) { return makeFuture(n < 3); };
31   using namespace futures::detail;
32   EXPECT_TRUE(retrying_policy_traits<decltype(policy_raw)>::is_raw::value);
33   EXPECT_TRUE(retrying_policy_traits<decltype(policy_fut)>::is_fut::value);
34 }
35
36 TEST(RetryingTest, basic) {
37   auto r = futures::retrying(
38       [](size_t n, const exception_wrapper&) { return n < 3; },
39       [](size_t n) {
40           return n < 2
41             ? makeFuture<size_t>(runtime_error("ha"))
42             : makeFuture(n);
43       }
44   ).wait();
45   EXPECT_EQ(2, r.value());
46 }
47
48 TEST(RetryingTest, policy_future) {
49   atomic<size_t> sleeps {0};
50   auto r = futures::retrying(
51       [&](size_t n, const exception_wrapper&) {
52           return n < 3
53             ? makeFuture(++sleeps).then([] { return true; })
54             : makeFuture(false);
55       },
56       [](size_t n) {
57           return n < 2
58             ? makeFuture<size_t>(runtime_error("ha"))
59             : makeFuture(n);
60       }
61   ).wait();
62   EXPECT_EQ(2, r.value());
63   EXPECT_EQ(2, sleeps);
64 }
65
66 TEST(RetryingTest, policy_basic) {
67   auto r = futures::retrying(
68       futures::retryingPolicyBasic(3),
69       [](size_t n) {
70           return n < 2
71             ? makeFuture<size_t>(runtime_error("ha"))
72             : makeFuture(n);
73       }
74   ).wait();
75   EXPECT_EQ(2, r.value());
76 }
77
78 TEST(RetryingTest, policy_capped_jittered_exponential_backoff) {
79   using ms = milliseconds;
80   auto start = steady_clock::now();
81   auto r = futures::retrying(
82       futures::retryingPolicyCappedJitteredExponentialBackoff(
83         3, ms(100), ms(1000), 0.1, mt19937_64(0),
84         [](size_t, const exception_wrapper&) { return true; }),
85       [](size_t n) {
86           return n < 2
87             ? makeFuture<size_t>(runtime_error("ha"))
88             : makeFuture(n);
89       }
90   ).wait();
91   auto finish = steady_clock::now();
92   auto duration = duration_cast<milliseconds>(finish - start);
93   EXPECT_EQ(2, r.value());
94   EXPECT_NEAR(
95       milliseconds(300).count(),
96       duration.count(),
97       milliseconds(25).count());
98 }
99
100 TEST(RetryingTest, policy_sleep_defaults) {
101   //  To ensure that this compiles with default params.
102   using ms = milliseconds;
103   auto start = steady_clock::now();
104   auto r = futures::retrying(
105       futures::retryingPolicyCappedJitteredExponentialBackoff(
106         3, ms(100), ms(1000), 0.1),
107       [](size_t n) {
108           return n < 2
109             ? makeFuture<size_t>(runtime_error("ha"))
110             : makeFuture(n);
111       }
112   ).wait();
113   auto finish = steady_clock::now();
114   auto duration = duration_cast<milliseconds>(finish - start);
115   EXPECT_EQ(2, r.value());
116   EXPECT_NEAR(
117       milliseconds(300).count(),
118       duration.count(),
119       milliseconds(100).count());
120 }
121
122 /*
123 TEST(RetryingTest, policy_sleep_cancel) {
124   mt19937_64 rng(0);
125   using ms = milliseconds;
126   auto start = steady_clock::now();
127   auto r = futures::retrying(
128       futures::retryingPolicyCappedJitteredExponentialBackoff(
129         5, ms(100), ms(1000), 0.1, rng,
130         [](size_t n, const exception_wrapper&) { return true; }),
131       [](size_t n) {
132           return n < 4
133             ? makeFuture<size_t>(runtime_error("ha"))
134             : makeFuture(n);
135       }
136   );
137   r.cancel();
138   r.wait();
139   auto finish = steady_clock::now();
140   auto duration = duration_cast<milliseconds>(finish - start);
141   EXPECT_EQ(2, r.value());
142   EXPECT_NEAR(
143       milliseconds(0).count(),
144       duration.count(),
145       milliseconds(10).count());
146 }
147 */