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