1313package dev .openfga .sdk .util ;
1414
1515import static org .assertj .core .api .Assertions .assertThat ;
16+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
1617
1718import java .time .Duration ;
1819import java .util .Random ;
@@ -24,10 +25,11 @@ class ExponentialBackoffTest {
2425 void calculateDelay_withRetryCountZero_shouldReturnBaseDelay () {
2526 // Given
2627 int retryCount = 0 ;
28+ Duration baseDelay = Duration .ofMillis (100 );
2729 Random fixedRandom = new Random (42 ); // Fixed seed for deterministic testing
2830
2931 // When
30- Duration result = ExponentialBackoff .calculateDelay (retryCount , fixedRandom );
32+ Duration result = ExponentialBackoff .calculateDelay (retryCount , baseDelay , fixedRandom );
3133
3234 // Then
3335 // For retry count 0: 2^0 * 100ms = 100ms base
@@ -39,10 +41,11 @@ void calculateDelay_withRetryCountZero_shouldReturnBaseDelay() {
3941 void calculateDelay_withRetryCountOne_shouldReturnDoubledDelay () {
4042 // Given
4143 int retryCount = 1 ;
44+ Duration baseDelay = Duration .ofMillis (100 );
4245 Random fixedRandom = new Random (42 ); // Fixed seed for deterministic testing
4346
4447 // When
45- Duration result = ExponentialBackoff .calculateDelay (retryCount , fixedRandom );
48+ Duration result = ExponentialBackoff .calculateDelay (retryCount , baseDelay , fixedRandom );
4649
4750 // Then
4851 // For retry count 1: 2^1 * 100ms = 200ms base
@@ -54,10 +57,11 @@ void calculateDelay_withRetryCountOne_shouldReturnDoubledDelay() {
5457 void calculateDelay_withRetryCountTwo_shouldReturnQuadrupledDelay () {
5558 // Given
5659 int retryCount = 2 ;
60+ Duration baseDelay = Duration .ofMillis (100 );
5761 Random fixedRandom = new Random (42 ); // Fixed seed for deterministic testing
5862
5963 // When
60- Duration result = ExponentialBackoff .calculateDelay (retryCount , fixedRandom );
64+ Duration result = ExponentialBackoff .calculateDelay (retryCount , baseDelay , fixedRandom );
6165
6266 // Then
6367 // For retry count 2: 2^2 * 100ms = 400ms base
@@ -69,10 +73,11 @@ void calculateDelay_withRetryCountTwo_shouldReturnQuadrupledDelay() {
6973 void calculateDelay_withHighRetryCount_shouldCapAtMaximum () {
7074 // Given
7175 int retryCount = 10 ; // This would normally result in 2^10 * 100ms = 102400ms
76+ Duration baseDelay = Duration .ofMillis (100 );
7277 Random fixedRandom = new Random (42 ); // Fixed seed for deterministic testing
7378
7479 // When
75- Duration result = ExponentialBackoff .calculateDelay (retryCount , fixedRandom );
80+ Duration result = ExponentialBackoff .calculateDelay (retryCount , baseDelay , fixedRandom );
7681
7782 // Then
7883 // Should be capped at 120 seconds (120000ms)
@@ -85,7 +90,7 @@ void calculateDelay_withNegativeRetryCount_shouldReturnZero() {
8590 int retryCount = -1 ;
8691
8792 // When
88- Duration result = ExponentialBackoff .calculateDelay (retryCount );
93+ Duration result = ExponentialBackoff .calculateDelay (retryCount , Duration . ofMillis ( 100 ) );
8994
9095 // Then
9196 assertThat (result ).isEqualTo (Duration .ZERO );
@@ -97,7 +102,7 @@ void calculateDelay_withoutRandomParameter_shouldReturnValidRange() {
97102 int retryCount = 1 ;
98103
99104 // When
100- Duration result = ExponentialBackoff .calculateDelay (retryCount );
105+ Duration result = ExponentialBackoff .calculateDelay (retryCount , Duration . ofMillis ( 100 ) );
101106
102107 // Then
103108 // For retry count 1: 2^1 * 100ms = 200ms base
@@ -111,9 +116,9 @@ void calculateDelay_shouldProduceVariousResults() {
111116 int retryCount = 1 ;
112117
113118 // When - call multiple times to ensure randomness
114- Duration result1 = ExponentialBackoff .calculateDelay (retryCount );
115- Duration result2 = ExponentialBackoff .calculateDelay (retryCount );
116- Duration result3 = ExponentialBackoff .calculateDelay (retryCount );
119+ Duration result1 = ExponentialBackoff .calculateDelay (retryCount , Duration . ofMillis ( 100 ) );
120+ Duration result2 = ExponentialBackoff .calculateDelay (retryCount , Duration . ofMillis ( 100 ) );
121+ Duration result3 = ExponentialBackoff .calculateDelay (retryCount , Duration . ofMillis ( 100 ) );
117122
118123 // Then - all should be in valid range but likely different
119124 assertThat (result1 .toMillis ()).isBetween (200L , 400L );
@@ -125,12 +130,13 @@ void calculateDelay_shouldProduceVariousResults() {
125130 void calculateDelay_withFixedRandom_shouldBeDeterministic () {
126131 // Given
127132 int retryCount = 1 ;
133+ Duration baseDelay = Duration .ofMillis (100 );
128134 Random fixedRandom1 = new Random (123 );
129135 Random fixedRandom2 = new Random (123 ); // Same seed
130136
131137 // When
132- Duration result1 = ExponentialBackoff .calculateDelay (retryCount , fixedRandom1 );
133- Duration result2 = ExponentialBackoff .calculateDelay (retryCount , fixedRandom2 );
138+ Duration result1 = ExponentialBackoff .calculateDelay (retryCount , baseDelay , fixedRandom1 );
139+ Duration result2 = ExponentialBackoff .calculateDelay (retryCount , baseDelay , fixedRandom2 );
134140
135141 // Then
136142 assertThat (result1 ).isEqualTo (result2 );
@@ -139,13 +145,14 @@ void calculateDelay_withFixedRandom_shouldBeDeterministic() {
139145 @ Test
140146 void calculateDelay_progressionTest_shouldFollowExponentialPattern () {
141147 // Given
148+ Duration baseDelay = Duration .ofMillis (100 );
142149 Random fixedRandom = new Random (42 );
143150
144151 // When & Then - test the progression follows expected pattern
145152 for (int i = 0 ; i < 8 ; i ++) {
146153 // Reset the random seed for consistent results across iterations
147154 fixedRandom .setSeed (42 );
148- Duration delay = ExponentialBackoff .calculateDelay (i , fixedRandom );
155+ Duration delay = ExponentialBackoff .calculateDelay (i , baseDelay , fixedRandom );
149156 long expectedBaseMs = (long ) Math .pow (2 , i ) * 100 ;
150157 long expectedMaxMs = Math .min (expectedBaseMs * 2 , 120000 );
151158
@@ -160,13 +167,43 @@ void calculateDelay_progressionTest_shouldFollowExponentialPattern() {
160167 void calculateDelay_atCapThreshold_shouldCapCorrectly () {
161168 // Given - retry count that would exceed 120s base delay
162169 int retryCount = 11 ; // 2^11 * 100ms = 204800ms > 120000ms
170+ Duration baseDelay = Duration .ofMillis (100 );
163171 Random fixedRandom = new Random (42 );
164172
165173 // When
166- Duration result = ExponentialBackoff .calculateDelay (retryCount , fixedRandom );
174+ Duration result = ExponentialBackoff .calculateDelay (retryCount , baseDelay , fixedRandom );
167175
168176 // Then - should be capped at 120s maximum
169177 assertThat (result .toMillis ()).isLessThanOrEqualTo (120000L );
170178 assertThat (result .toMillis ()).isGreaterThanOrEqualTo (120000L ); // Should be exactly at cap for base delay
171179 }
180+
181+ @ Test
182+ void calculateDelay_withCustomBaseDelay_shouldUseConfigurableBase () {
183+ // Given - custom base delay of 500ms
184+ int retryCount = 1 ;
185+ Duration baseDelay = Duration .ofMillis (500 );
186+ Random fixedRandom = new Random (42 );
187+
188+ // When
189+ Duration result = ExponentialBackoff .calculateDelay (retryCount , baseDelay , fixedRandom );
190+
191+ // Then
192+ // For retry count 1 with 500ms base: 2^1 * 500ms = 1000ms base
193+ // With jitter: between 1000ms and 2000ms
194+ assertThat (result .toMillis ()).isBetween (1000L , 2000L );
195+ }
196+
197+ @ Test
198+ void calculateDelay_withNullBaseDelay_shouldThrowException () {
199+ // Given
200+ int retryCount = 0 ;
201+ Duration baseDelay = null ;
202+ Random fixedRandom = new Random (42 );
203+
204+ // When & Then
205+ assertThatThrownBy (() -> ExponentialBackoff .calculateDelay (retryCount , baseDelay , fixedRandom ))
206+ .isInstanceOf (IllegalArgumentException .class )
207+ .hasMessage ("baseDelay cannot be null" );
208+ }
172209}
0 commit comments