• 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/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