backoff_test.cc 7.0 KB

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