1 /*
2 *
3 * Copyright 2016 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include "src/core/lib/backoff/backoff.h"
20
21 #include <algorithm>
22
23 #include <grpc/support/log.h>
24
25 #include <gtest/gtest.h>
26 #include "test/core/util/test_config.h"
27
28 namespace grpc {
29 namespace testing {
30 namespace {
31
32 using grpc_core::BackOff;
33
TEST(BackOffTest,ConstantBackOff)34 TEST(BackOffTest, ConstantBackOff) {
35 const grpc_millis initial_backoff = 200;
36 const double multiplier = 1.0;
37 const double jitter = 0.0;
38 const grpc_millis max_backoff = 1000;
39 grpc_core::ExecCtx exec_ctx;
40 BackOff::Options options;
41 options.set_initial_backoff(initial_backoff)
42 .set_multiplier(multiplier)
43 .set_jitter(jitter)
44 .set_max_backoff(max_backoff);
45 BackOff backoff(options);
46
47 grpc_millis next_attempt_start_time = backoff.NextAttemptTime();
48 EXPECT_EQ(next_attempt_start_time - grpc_core::ExecCtx::Get()->Now(),
49 initial_backoff);
50 for (int i = 0; i < 10000; i++) {
51 next_attempt_start_time = backoff.NextAttemptTime();
52 EXPECT_EQ(next_attempt_start_time - grpc_core::ExecCtx::Get()->Now(),
53 initial_backoff);
54 }
55 }
56
TEST(BackOffTest,MinConnect)57 TEST(BackOffTest, MinConnect) {
58 const grpc_millis initial_backoff = 100;
59 const double multiplier = 1.0;
60 const double jitter = 0.0;
61 const grpc_millis max_backoff = 1000;
62 grpc_core::ExecCtx exec_ctx;
63 BackOff::Options options;
64 options.set_initial_backoff(initial_backoff)
65 .set_multiplier(multiplier)
66 .set_jitter(jitter)
67 .set_max_backoff(max_backoff);
68 BackOff backoff(options);
69 grpc_millis next = backoff.NextAttemptTime();
70 EXPECT_EQ(next - grpc_core::ExecCtx::Get()->Now(), initial_backoff);
71 }
72
TEST(BackOffTest,NoJitterBackOff)73 TEST(BackOffTest, NoJitterBackOff) {
74 const grpc_millis initial_backoff = 2;
75 const double multiplier = 2.0;
76 const double jitter = 0.0;
77 const grpc_millis max_backoff = 513;
78 BackOff::Options options;
79 options.set_initial_backoff(initial_backoff)
80 .set_multiplier(multiplier)
81 .set_jitter(jitter)
82 .set_max_backoff(max_backoff);
83 BackOff backoff(options);
84 // x_1 = 2
85 // x_n = 2**i + x_{i-1} ( = 2**(n+1) - 2 )
86 grpc_core::ExecCtx exec_ctx;
87 grpc_core::ExecCtx::Get()->TestOnlySetNow(0);
88 grpc_millis next = backoff.NextAttemptTime();
89 EXPECT_EQ(next, 2);
90 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
91 next = backoff.NextAttemptTime();
92 EXPECT_EQ(next, 6);
93 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
94 next = backoff.NextAttemptTime();
95 EXPECT_EQ(next, 14);
96 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
97 next = backoff.NextAttemptTime();
98 EXPECT_EQ(next, 30);
99 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
100 next = backoff.NextAttemptTime();
101 EXPECT_EQ(next, 62);
102 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
103 next = backoff.NextAttemptTime();
104 EXPECT_EQ(next, 126);
105 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
106 next = backoff.NextAttemptTime();
107 EXPECT_EQ(next, 254);
108 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
109 next = backoff.NextAttemptTime();
110 EXPECT_EQ(next, 510);
111 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
112 next = backoff.NextAttemptTime();
113 EXPECT_EQ(next, 1022);
114 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
115 next = backoff.NextAttemptTime();
116 // Hit the maximum timeout. From this point onwards, retries will increase
117 // only by max timeout.
118 EXPECT_EQ(next, 1535);
119 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
120 next = backoff.NextAttemptTime();
121 EXPECT_EQ(next, 2048);
122 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
123 next = backoff.NextAttemptTime();
124 EXPECT_EQ(next, 2561);
125 }
126
TEST(BackOffTest,JitterBackOff)127 TEST(BackOffTest, JitterBackOff) {
128 const grpc_millis initial_backoff = 500;
129 grpc_millis current_backoff = initial_backoff;
130 const grpc_millis max_backoff = 1000;
131 const double multiplier = 1.0;
132 const double jitter = 0.1;
133 BackOff::Options options;
134 options.set_initial_backoff(initial_backoff)
135 .set_multiplier(multiplier)
136 .set_jitter(jitter)
137 .set_max_backoff(max_backoff);
138 BackOff backoff(options);
139
140 backoff.SetRandomSeed(0); // force consistent PRNG
141
142 grpc_core::ExecCtx exec_ctx;
143 grpc_millis next = backoff.NextAttemptTime();
144 EXPECT_EQ(next - grpc_core::ExecCtx::Get()->Now(), initial_backoff);
145
146 grpc_millis expected_next_lower_bound = static_cast<grpc_millis>(
147 static_cast<double>(current_backoff) * (1 - jitter));
148 grpc_millis expected_next_upper_bound = static_cast<grpc_millis>(
149 static_cast<double>(current_backoff) * (1 + jitter));
150
151 for (int i = 0; i < 10000; i++) {
152 next = backoff.NextAttemptTime();
153 // next-now must be within (jitter*100)% of the current backoff (which
154 // increases by * multiplier up to max_backoff).
155 const grpc_millis timeout_millis = next - grpc_core::ExecCtx::Get()->Now();
156 EXPECT_GE(timeout_millis, expected_next_lower_bound);
157 EXPECT_LE(timeout_millis, expected_next_upper_bound);
158 current_backoff =
159 std::min(static_cast<grpc_millis>(static_cast<double>(current_backoff) *
160 multiplier),
161 max_backoff);
162 expected_next_lower_bound = static_cast<grpc_millis>(
163 static_cast<double>(current_backoff) * (1 - jitter));
164 expected_next_upper_bound = static_cast<grpc_millis>(
165 static_cast<double>(current_backoff) * (1 + jitter));
166 }
167 }
168
169 } // namespace
170 } // namespace testing
171 } // namespace grpc
172
main(int argc,char ** argv)173 int main(int argc, char** argv) {
174 grpc_test_init(argc, argv);
175 ::testing::InitGoogleTest(&argc, argv);
176 return RUN_ALL_TESTS();
177 }
178