@@ -54,6 +54,12 @@ private static Instant getStaleAfter(CachedTokenSource source) throws Exception
5454 return (Instant ) staleAfterField .get (source );
5555 }
5656
57+ private static boolean getRefreshInProgress (CachedTokenSource source ) throws Exception {
58+ Field f = CachedTokenSource .class .getDeclaredField ("refreshInProgress" );
59+ f .setAccessible (true );
60+ return (boolean ) f .get (source );
61+ }
62+
5763 /**
5864 * Polls a condition until it becomes true or the timeout expires. This keeps the async-refresh
5965 * tests deterministic without relying on long fixed sleeps.
@@ -266,8 +272,10 @@ void testGetTokenDoesNotRetryBeforeAsyncBackoffElapses() throws Exception {
266272
267273 Instant backoffThreshold = BASE_TIME .plus (Duration .ofMinutes (7 ));
268274 awaitCondition (
269- "staleAfter should be pushed forward by the async refresh backoff" ,
270- () -> backoffThreshold .equals (getStaleAfterUnchecked (source )));
275+ "async refresh cycle should complete (staleAfter pushed forward, refreshInProgress reset)" ,
276+ () ->
277+ backoffThreshold .equals (getStaleAfterUnchecked (source ))
278+ && !getRefreshInProgressUnchecked (source ));
271279
272280 assertEquals (INITIAL_TOKEN , source .getToken ().getAccessToken ());
273281 assertFalse (
@@ -302,8 +310,10 @@ void testGetTokenRetriesAfterAsyncBackoffElapsesAndUpdatesToken() throws Excepti
302310
303311 Instant backoffThreshold = BASE_TIME .plus (Duration .ofMinutes (7 ));
304312 awaitCondition (
305- "staleAfter should be pushed forward by the async refresh backoff" ,
306- () -> backoffThreshold .equals (getStaleAfterUnchecked (source )));
313+ "async refresh cycle should complete (staleAfter pushed forward, refreshInProgress reset)" ,
314+ () ->
315+ backoffThreshold .equals (getStaleAfterUnchecked (source ))
316+ && !getRefreshInProgressUnchecked (source ));
307317
308318 clockSupplier .advanceTime (Duration .ofMinutes (2 ));
309319
@@ -320,7 +330,8 @@ void testGetTokenRetriesAfterAsyncBackoffElapsesAndUpdatesToken() throws Excepti
320330 /**
321331 * Verifies that an async refresh result is discarded when the cache already holds a token with a
322332 * later expiry. This covers the concurrent scenario where a blocking refresh runs while an async
323- * refresh is in flight: the async result is older and should not overwrite the newer cached token.
333+ * refresh is in flight: the async result is older and should not overwrite the newer cached
334+ * token.
324335 */
325336 @ Test
326337 void testAsyncRefreshDiscardsOlderToken () throws Exception {
@@ -360,9 +371,7 @@ void testAsyncRefreshDiscardsOlderToken() throws Exception {
360371 clockSupplier .advanceTime (Duration .ofMinutes (6 ));
361372 Token staleResult = source .getToken ();
362373 assertEquals (INITIAL_TOKEN , staleResult .getAccessToken ());
363- assertTrue (
364- asyncRefreshStarted .await (1 , TimeUnit .SECONDS ),
365- "Async refresh should have started" );
374+ assertTrue (asyncRefreshStarted .await (1 , TimeUnit .SECONDS ), "Async refresh should have started" );
366375
367376 // While async refresh is blocked, advance time so the token expires and force a blocking
368377 // refresh that installs a newer token.
@@ -374,15 +383,7 @@ void testAsyncRefreshDiscardsOlderToken() throws Exception {
374383 allowAsyncToFinish .countDown ();
375384 awaitCondition (
376385 "refreshInProgress should be reset after the async refresh completes" ,
377- () -> {
378- try {
379- Field f = CachedTokenSource .class .getDeclaredField ("refreshInProgress" );
380- f .setAccessible (true );
381- return !(boolean ) f .get (source );
382- } catch (Exception e ) {
383- throw new RuntimeException (e );
384- }
385- });
386+ () -> !getRefreshInProgressUnchecked (source ));
386387
387388 assertEquals (
388389 "newer-blocking-token" ,
@@ -413,4 +414,12 @@ private static Instant getStaleAfterUnchecked(CachedTokenSource source) {
413414 throw new RuntimeException (e );
414415 }
415416 }
417+
418+ private static boolean getRefreshInProgressUnchecked (CachedTokenSource source ) {
419+ try {
420+ return getRefreshInProgress (source );
421+ } catch (Exception e ) {
422+ throw new RuntimeException (e );
423+ }
424+ }
416425}
0 commit comments