@@ -2839,6 +2839,18 @@ func TestDo_rateLimit_sleepUntilClientResetLimit(t *testing.T) {
28392839}
28402840
28412841// Ensure sleep is aborted when the context is cancelled.
2842+ //
2843+ // The test verifies that when a request receives a 403 rate-limit response,
2844+ // the client begins sleeping until the reset time, and that canceling the
2845+ // context during (or just before) that sleep aborts it and returns
2846+ // context.Canceled.
2847+ //
2848+ // Determinism: The handler signals via requestReceived once it has run,
2849+ // guaranteeing exactly one request before cancellation. A tiny goroutine
2850+ // waits for that signal and then calls cancel, so the context is cancelled
2851+ // after the handler returns but independently of wall-clock timing. There
2852+ // are no time.After timeouts or time.Sleep delays: the test either completes
2853+ // in microseconds or hangs (caught by the test framework's global timeout).
28422854func TestDo_rateLimit_abortSleepContextCancelled (t * testing.T ) {
28432855 t .Parallel ()
28442856 client , mux , _ := setup (t )
@@ -2870,42 +2882,31 @@ func TestDo_rateLimit_abortSleepContextCancelled(t *testing.T) {
28702882
28712883 req , _ := client .NewRequest (context .WithValue (ctx , SleepUntilPrimaryRateLimitResetWhenRateLimited , true ), "GET" , "." , nil )
28722884
2873- errCh := make (chan error , 1 )
2885+ // Cancel the context as soon as the handler has processed the request.
2886+ // The handler always runs and returns before the client begins the
2887+ // rate-limit sleep (the HTTP transport is synchronous), so cancel fires
2888+ // either just before or during the sleep — both paths are handled
2889+ // identically by sleepUntilResetWithBuffer's select.
28742890 go func () {
2875- _ , err := client . Do ( req , nil )
2876- errCh <- err
2891+ <- requestReceived
2892+ cancel ()
28772893 }()
28782894
2879- // Wait until the handler has processed the request, ensuring exactly one
2880- // request was made before we cancel the context to abort the rate-limit
2881- // sleep. This decouples the request-count assertion from the timing of
2882- // the context cancellation, eliminating flakiness on slow runners.
2883- select {
2884- case <- requestReceived :
2885- case <- time .After (10 * time .Second ):
2886- t .Fatal ("Timed out waiting for request to be received." )
2887- }
2895+ _ , err := client .Do (req , nil )
28882896
28892897 if got , want := int (requestCount .Load ()), 1 ; got != want {
28902898 t .Errorf ("Expected 1 request, got %v" , got )
28912899 }
2892-
2893- // Now cancel the context while the client is sleeping waiting for the
2894- // rate limit to reset. This should abort the sleep and return the
2895- // context error.
2896- cancel ()
2897-
2898- select {
2899- case err := <- errCh :
2900- if ! errors .Is (err , context .Canceled ) {
2901- t .Errorf ("Expected context cancelled error, got: %v" , err )
2902- }
2903- case <- time .After (10 * time .Second ):
2904- t .Fatal ("Timed out waiting for Do to return after context cancellation." )
2900+ if ! errors .Is (err , context .Canceled ) {
2901+ t .Errorf ("Expected context cancelled error, got: %v" , err )
29052902 }
29062903}
29072904
29082905// Ensure sleep is aborted when the context is cancelled on initial request.
2906+ //
2907+ // Determinism: The context is pre-cancelled before Do is called, so
2908+ // checkRateLimitBeforeDo → sleepUntilResetWithBuffer sees ctx.Done() already
2909+ // closed and returns immediately. No wall-clock timeout is involved.
29092910func TestDo_rateLimit_abortSleepContextCancelledClientLimit (t * testing.T ) {
29102911 t .Parallel ()
29112912 client , mux , _ := setup (t )
@@ -2924,8 +2925,12 @@ func TestDo_rateLimit_abortSleepContextCancelledClientLimit(t *testing.T) {
29242925 w .WriteHeader (http .StatusOK )
29252926 fmt .Fprintln (w , `{}` )
29262927 })
2927- ctx , cancel := context .WithTimeout (t .Context (), 10 * time .Millisecond )
2928- defer cancel ()
2928+ // Pre-cancel the context: checkRateLimitBeforeDo will call
2929+ // sleepUntilResetWithBuffer which immediately returns ctx.Err() because
2930+ // ctx.Done() is already closed. This is fully deterministic — no timing
2931+ // race between a short timeout and goroutine scheduling.
2932+ ctx , cancel := context .WithCancel (t .Context ())
2933+ cancel ()
29292934 req , _ := client .NewRequest (context .WithValue (ctx , SleepUntilPrimaryRateLimitResetWhenRateLimited , true ), "GET" , "." , nil )
29302935 _ , err := client .Do (req , nil )
29312936 var rateLimitError * RateLimitError
@@ -2936,7 +2941,7 @@ func TestDo_rateLimit_abortSleepContextCancelledClientLimit(t *testing.T) {
29362941 t .Errorf ("Expected request to be prevented because context cancellation, got: %v." , got )
29372942 }
29382943 if got , want := int (requestCount .Load ()), 0 ; got != want {
2939- t .Errorf ("Expected 1 requests, got %v" , got )
2944+ t .Errorf ("Expected 0 requests, got %v" , got )
29402945 }
29412946}
29422947
0 commit comments