@@ -167,6 +167,63 @@ public void refreshActionIsRemovedIfItErrorsTooMuch() throws Exception {
167167 verify (refreshAction , times (callsCountBeforeCancellation )).call ();
168168 }
169169
170+ @ Test
171+ public void errorInRefreshShouldBeRetried () throws Exception {
172+ DefaultCredentialsRefreshService .CredentialsProviderState state = new DefaultCredentialsRefreshService .CredentialsProviderState (
173+ credentialsProvider
174+ );
175+ doThrow (RuntimeException .class ).doThrow (RuntimeException .class )
176+ .doNothing ().when (credentialsProvider ).refresh ();
177+
178+ when (refreshAction .call ()).thenReturn (true );
179+
180+ state .add (new DefaultCredentialsRefreshService .Registration ("1" , refreshAction ));
181+
182+ state .refresh ();
183+
184+ verify (credentialsProvider , times (3 )).refresh ();
185+ verify (refreshAction , times (1 )).call ();
186+ }
187+
188+ @ Test
189+ public void callbacksAreNotCalledWhenRetryOnRefreshIsExhausted () throws Exception {
190+ DefaultCredentialsRefreshService .CredentialsProviderState state = new DefaultCredentialsRefreshService .CredentialsProviderState (
191+ credentialsProvider
192+ );
193+ doThrow (RuntimeException .class ).when (credentialsProvider ).refresh ();
194+
195+ state .add (new DefaultCredentialsRefreshService .Registration ("1" , refreshAction ));
196+
197+ state .refresh ();
198+
199+ verify (credentialsProvider , times (3 )).refresh ();
200+ verify (refreshAction , times (0 )).call ();
201+ }
202+
203+ @ Test
204+ public void refreshCanBeInterrupted () throws Exception {
205+ DefaultCredentialsRefreshService .CredentialsProviderState state = new DefaultCredentialsRefreshService .CredentialsProviderState (
206+ credentialsProvider
207+ );
208+
209+ AtomicInteger callbackCount = new AtomicInteger (10 );
210+ when (refreshAction .call ()).thenAnswer (invocation -> {
211+ callbackCount .decrementAndGet ();
212+ Thread .sleep (1000L );
213+ return true ;
214+ });
215+
216+ IntStream .range (0 , callbackCount .get ()).forEach (i -> state .add (new DefaultCredentialsRefreshService .Registration (i + "" , refreshAction )));
217+
218+ Thread refreshThread = new Thread (() -> state .refresh ());
219+ refreshThread .start ();
220+ Thread .sleep (1000L );
221+ refreshThread .interrupt ();
222+ refreshThread .join (5000 );
223+ assertThat (refreshThread .isAlive ()).isFalse ();
224+ assertThat (callbackCount ).hasValueGreaterThan (1 ); // not all the callbacks were called, because thread has been cancelled
225+ }
226+
170227 @ Test
171228 public void fixedDelayBeforeExpirationRefreshDelayStrategyTest () {
172229 Function <Duration , Duration > delayStrategy = fixedDelayBeforeExpirationRefreshDelayStrategy (ofSeconds (20 ));
0 commit comments