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/grpc.h>
24 #include <grpc/support/log.h>
25
26 #include <gtest/gtest.h>
27 #include "test/core/util/test_config.h"
28
29 namespace grpc {
30 namespace testing {
31 namespace {
32
33 using grpc_core::BackOff;
34
TEST(BackOffTest,ConstantBackOff)35 TEST(BackOffTest, ConstantBackOff) {
36 const grpc_millis initial_backoff = 200;
37 const double multiplier = 1.0;
38 const double jitter = 0.0;
39 const grpc_millis max_backoff = 1000;
40 grpc_core::ExecCtx exec_ctx;
41 BackOff::Options options;
42 options.set_initial_backoff(initial_backoff)
43 .set_multiplier(multiplier)
44 .set_jitter(jitter)
45 .set_max_backoff(max_backoff);
46 BackOff backoff(options);
47
48 grpc_millis next_attempt_start_time = backoff.NextAttemptTime();
49 EXPECT_EQ(next_attempt_start_time - grpc_core::ExecCtx::Get()->Now(),
50 initial_backoff);
51 for (int i = 0; i < 10000; i++) {
52 next_attempt_start_time = backoff.NextAttemptTime();
53 EXPECT_EQ(next_attempt_start_time - grpc_core::ExecCtx::Get()->Now(),
54 initial_backoff);
55 }
56 }
57
TEST(BackOffTest,MinConnect)58 TEST(BackOffTest, MinConnect) {
59 const grpc_millis initial_backoff = 100;
60 const double multiplier = 1.0;
61 const double jitter = 0.0;
62 const grpc_millis max_backoff = 1000;
63 grpc_core::ExecCtx exec_ctx;
64 BackOff::Options options;
65 options.set_initial_backoff(initial_backoff)
66 .set_multiplier(multiplier)
67 .set_jitter(jitter)
68 .set_max_backoff(max_backoff);
69 BackOff backoff(options);
70 grpc_millis next = backoff.NextAttemptTime();
71 EXPECT_EQ(next - grpc_core::ExecCtx::Get()->Now(), initial_backoff);
72 }
73
TEST(BackOffTest,NoJitterBackOff)74 TEST(BackOffTest, NoJitterBackOff) {
75 const grpc_millis initial_backoff = 2;
76 const double multiplier = 2.0;
77 const double jitter = 0.0;
78 const grpc_millis max_backoff = 513;
79 BackOff::Options options;
80 options.set_initial_backoff(initial_backoff)
81 .set_multiplier(multiplier)
82 .set_jitter(jitter)
83 .set_max_backoff(max_backoff);
84 BackOff backoff(options);
85 // x_1 = 2
86 // x_n = 2**i + x_{i-1} ( = 2**(n+1) - 2 )
87 grpc_core::ExecCtx exec_ctx;
88 grpc_core::ExecCtx::Get()->TestOnlySetNow(0);
89 grpc_millis next = backoff.NextAttemptTime();
90 EXPECT_EQ(next, 2);
91 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
92 next = backoff.NextAttemptTime();
93 EXPECT_EQ(next, 6);
94 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
95 next = backoff.NextAttemptTime();
96 EXPECT_EQ(next, 14);
97 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
98 next = backoff.NextAttemptTime();
99 EXPECT_EQ(next, 30);
100 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
101 next = backoff.NextAttemptTime();
102 EXPECT_EQ(next, 62);
103 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
104 next = backoff.NextAttemptTime();
105 EXPECT_EQ(next, 126);
106 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
107 next = backoff.NextAttemptTime();
108 EXPECT_EQ(next, 254);
109 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
110 next = backoff.NextAttemptTime();
111 EXPECT_EQ(next, 510);
112 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
113 next = backoff.NextAttemptTime();
114 EXPECT_EQ(next, 1022);
115 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
116 next = backoff.NextAttemptTime();
117 // Hit the maximum timeout. From this point onwards, retries will increase
118 // only by max timeout.
119 EXPECT_EQ(next, 1535);
120 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
121 next = backoff.NextAttemptTime();
122 EXPECT_EQ(next, 2048);
123 grpc_core::ExecCtx::Get()->TestOnlySetNow(next);
124 next = backoff.NextAttemptTime();
125 EXPECT_EQ(next, 2561);
126 }
127
TEST(BackOffTest,JitterBackOff)128 TEST(BackOffTest, JitterBackOff) {
129 const grpc_millis initial_backoff = 500;
130 grpc_millis current_backoff = initial_backoff;
131 const grpc_millis max_backoff = 1000;
132 const double multiplier = 1.0;
133 const double jitter = 0.1;
134 BackOff::Options options;
135 options.set_initial_backoff(initial_backoff)
136 .set_multiplier(multiplier)
137 .set_jitter(jitter)
138 .set_max_backoff(max_backoff);
139 BackOff backoff(options);
140
141 backoff.SetRandomSeed(0); // force consistent PRNG
142
143 grpc_core::ExecCtx exec_ctx;
144 grpc_millis next = backoff.NextAttemptTime();
145 EXPECT_EQ(next - grpc_core::ExecCtx::Get()->Now(), initial_backoff);
146
147 grpc_millis expected_next_lower_bound = static_cast<grpc_millis>(
148 static_cast<double>(current_backoff) * (1 - jitter));
149 grpc_millis expected_next_upper_bound = static_cast<grpc_millis>(
150 static_cast<double>(current_backoff) * (1 + jitter));
151
152 for (int i = 0; i < 10000; i++) {
153 next = backoff.NextAttemptTime();
154 // next-now must be within (jitter*100)% of the current backoff (which
155 // increases by * multiplier up to max_backoff).
156 const grpc_millis timeout_millis = next - grpc_core::ExecCtx::Get()->Now();
157 EXPECT_GE(timeout_millis, expected_next_lower_bound);
158 EXPECT_LE(timeout_millis, expected_next_upper_bound);
159 current_backoff =
160 std::min(static_cast<grpc_millis>(static_cast<double>(current_backoff) *
161 multiplier),
162 max_backoff);
163 expected_next_lower_bound = static_cast<grpc_millis>(
164 static_cast<double>(current_backoff) * (1 - jitter));
165 expected_next_upper_bound = static_cast<grpc_millis>(
166 static_cast<double>(current_backoff) * (1 + jitter));
167 }
168 }
169
170 } // namespace
171 } // namespace testing
172 } // namespace grpc
173
main(int argc,char ** argv)174 int main(int argc, char** argv) {
175 ::testing::InitGoogleTest(&argc, argv);
176 grpc::testing::TestEnvironment env(argc, argv);
177 grpc_init();
178 int ret = RUN_ALL_TESTS();
179 grpc_shutdown();
180 return ret;
181 }
182