• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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