retry_policy_ut.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include "retry_policy.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. Y_UNIT_TEST_SUITE(RetryPolicy) {
  4. Y_UNIT_TEST(NoRetryPolicy) {
  5. auto policy = IRetryPolicy<int>::GetNoRetryPolicy();
  6. UNIT_ASSERT(!policy->CreateRetryState()->GetNextRetryDelay(42));
  7. }
  8. using ITestPolicy = IRetryPolicy<ERetryErrorClass>;
  9. ERetryErrorClass ErrorClassFunction(ERetryErrorClass err) {
  10. return err;
  11. }
  12. #define ASSERT_INTERVAL(from, to, val) { \
  13. auto v = val; \
  14. UNIT_ASSERT(v); \
  15. UNIT_ASSERT_GE_C(*v, from, *v); \
  16. UNIT_ASSERT_LE_C(*v, to, *v); \
  17. }
  18. Y_UNIT_TEST(FixedIntervalPolicy) {
  19. auto policy = ITestPolicy::GetFixedIntervalPolicy(ErrorClassFunction, TDuration::MilliSeconds(100), TDuration::Seconds(100));
  20. auto state = policy->CreateRetryState();
  21. for (int i = 0; i < 5; ++i) {
  22. ASSERT_INTERVAL(TDuration::MilliSeconds(50), TDuration::MilliSeconds(100), state->GetNextRetryDelay(ERetryErrorClass::ShortRetry));
  23. ASSERT_INTERVAL(TDuration::Seconds(50), TDuration::Seconds(100), state->GetNextRetryDelay(ERetryErrorClass::LongRetry));
  24. UNIT_ASSERT(!state->GetNextRetryDelay(ERetryErrorClass::NoRetry));
  25. }
  26. }
  27. Y_UNIT_TEST(ExponentialBackoffPolicy) {
  28. auto policy = ITestPolicy::GetExponentialBackoffPolicy(ErrorClassFunction, TDuration::MilliSeconds(100), TDuration::Seconds(100), TDuration::Seconds(500));
  29. auto state = policy->CreateRetryState();
  30. // Step 1
  31. ASSERT_INTERVAL(TDuration::MilliSeconds(50), TDuration::MilliSeconds(100), state->GetNextRetryDelay(ERetryErrorClass::ShortRetry));
  32. // Step 2
  33. ASSERT_INTERVAL(TDuration::Seconds(50), TDuration::Seconds(100), state->GetNextRetryDelay(ERetryErrorClass::LongRetry));
  34. // Step 3
  35. ASSERT_INTERVAL(TDuration::Seconds(100), TDuration::Seconds(200), state->GetNextRetryDelay(ERetryErrorClass::ShortRetry));
  36. // Step 4
  37. ASSERT_INTERVAL(TDuration::Seconds(200), TDuration::Seconds(400), state->GetNextRetryDelay(ERetryErrorClass::LongRetry));
  38. // Step 5. Max delay
  39. ASSERT_INTERVAL(TDuration::Seconds(250), TDuration::Seconds(500), state->GetNextRetryDelay(ERetryErrorClass::LongRetry));
  40. ASSERT_INTERVAL(TDuration::Seconds(250), TDuration::Seconds(500), state->GetNextRetryDelay(ERetryErrorClass::ShortRetry));
  41. // No retry
  42. UNIT_ASSERT(!state->GetNextRetryDelay(ERetryErrorClass::NoRetry));
  43. }
  44. void TestMaxRetries(bool exponentialBackoff) {
  45. ITestPolicy::TPtr policy;
  46. if (exponentialBackoff) {
  47. policy = ITestPolicy::GetExponentialBackoffPolicy(ErrorClassFunction, TDuration::MilliSeconds(10), TDuration::MilliSeconds(200), TDuration::Seconds(30), 3);
  48. } else {
  49. policy = ITestPolicy::GetFixedIntervalPolicy(ErrorClassFunction, TDuration::MilliSeconds(100), TDuration::MilliSeconds(300), 3);
  50. }
  51. auto state = policy->CreateRetryState();
  52. UNIT_ASSERT(state->GetNextRetryDelay(ERetryErrorClass::ShortRetry));
  53. UNIT_ASSERT(state->GetNextRetryDelay(ERetryErrorClass::ShortRetry));
  54. UNIT_ASSERT(state->GetNextRetryDelay(ERetryErrorClass::ShortRetry));
  55. UNIT_ASSERT(!state->GetNextRetryDelay(ERetryErrorClass::ShortRetry));
  56. UNIT_ASSERT(!state->GetNextRetryDelay(ERetryErrorClass::ShortRetry));
  57. }
  58. void TestMaxTime(bool exponentialBackoff) {
  59. ITestPolicy::TPtr policy;
  60. const TDuration maxDelay = TDuration::Seconds(2);
  61. if (exponentialBackoff) {
  62. policy = ITestPolicy::GetExponentialBackoffPolicy(ErrorClassFunction, TDuration::MilliSeconds(10), TDuration::MilliSeconds(200), TDuration::Seconds(30), 100500, maxDelay);
  63. } else {
  64. policy = ITestPolicy::GetFixedIntervalPolicy(ErrorClassFunction, TDuration::MilliSeconds(100), TDuration::MilliSeconds(300), 100500, maxDelay);
  65. }
  66. const TInstant start = TInstant::Now();
  67. auto state = policy->CreateRetryState();
  68. for (int i = 0; i < 3; ++i) {
  69. auto delay = state->GetNextRetryDelay(ERetryErrorClass::ShortRetry);
  70. const TInstant now = TInstant::Now();
  71. UNIT_ASSERT(delay || now - start >= maxDelay);
  72. }
  73. Sleep(maxDelay);
  74. UNIT_ASSERT(!state->GetNextRetryDelay(ERetryErrorClass::ShortRetry));
  75. UNIT_ASSERT(!state->GetNextRetryDelay(ERetryErrorClass::ShortRetry));
  76. }
  77. Y_UNIT_TEST(MaxRetriesExponentialBackoff) {
  78. TestMaxRetries(true);
  79. }
  80. Y_UNIT_TEST(MaxRetriesFixedInterval) {
  81. TestMaxRetries(false);
  82. }
  83. Y_UNIT_TEST(MaxTimeExponentialBackoff) {
  84. TestMaxTime(true);
  85. }
  86. Y_UNIT_TEST(MaxTimeFixedInterval) {
  87. TestMaxTime(false);
  88. }
  89. }