@@ -311,6 +311,7 @@ def test_call_propagates_token_refresh_failure(self, refresh_already_failed):
311311 auth .refresh_token = jwt .encode ({"exp" : 4_000_000_000 }, "x" * 32 , algorithm = "HS256" )
312312 auth .token_endpoint = KeyAuth .DEFAULT_TOKEN_ENDPOINT
313313 auth .refresh_future = None
314+ auth ._stop = Event ()
314315 original_token = auth .access_token
315316 request = Request ("GET" , "https://example.com" )
316317 refresh_error = requests .RequestException ("refresh failed" )
@@ -425,6 +426,35 @@ def set_initial_token(auth):
425426 time .sleep (0.1 ) # ten refresh intervals
426427 assert mock_post .call_count == requests_after_close
427428
429+ def test_close_waits_for_a_refresh_in_progress (self , service_account_key_file_json ):
430+ def set_initial_token (auth ):
431+ auth .initial_token = "test-initial-token"
432+
433+ expired = jwt .encode ({"exp" : 1 }, "secret" , algorithm = "HS256" )
434+ refresh_started = Event ()
435+ with (
436+ patch .object (KeyAuth , "_KeyAuth__create_initial_token" , new = set_initial_token ),
437+ patch .object (KeyAuth , "TOKEN_EXPIRY_CHECK_INTERVAL" , timedelta (milliseconds = 10 )),
438+ patch ("requests.post" ) as mock_post ,
439+ ):
440+ auth = self ._make_auth (service_account_key_file_json , mock_post , expired )
441+ initial_response = mock_post .return_value
442+
443+ def slow_refresh (* args , ** kwargs ):
444+ refresh_started .set ()
445+ time .sleep (0.2 )
446+ return initial_response
447+
448+ mock_post .side_effect = slow_refresh
449+ assert refresh_started .wait (timeout = 5 )
450+
451+ auth .close ()
452+
453+ assert auth .refresh_future is not None and auth .refresh_future .done ()
454+ requests_after_close = mock_post .call_count
455+ time .sleep (0.1 )
456+ assert mock_post .call_count == requests_after_close
457+
428458 def test_close_is_idempotent (self , service_account_key_file_json ):
429459 def set_initial_token (auth ):
430460 auth .initial_token = "test-initial-token"
0 commit comments