From 3b3e0d1141c1f9e8d3813181bf47f225175d347b Mon Sep 17 00:00:00 2001 From: lyd123qw2008 <326643467@qq.com> Date: Mon, 23 Feb 2026 22:41:33 +0800 Subject: [PATCH] test(codex): log non-retryable refresh error and cover single-attempt behavior --- internal/auth/codex/openai_auth.go | 1 + internal/auth/codex/openai_auth_test.go | 44 +++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 internal/auth/codex/openai_auth_test.go diff --git a/internal/auth/codex/openai_auth.go b/internal/auth/codex/openai_auth.go index b3620b8a..8c32f3eb 100644 --- a/internal/auth/codex/openai_auth.go +++ b/internal/auth/codex/openai_auth.go @@ -267,6 +267,7 @@ func (o *CodexAuth) RefreshTokensWithRetry(ctx context.Context, refreshToken str return tokenData, nil } if isNonRetryableRefreshErr(err) { + log.Warnf("Token refresh attempt %d failed with non-retryable error: %v", attempt+1, err) return nil, err } diff --git a/internal/auth/codex/openai_auth_test.go b/internal/auth/codex/openai_auth_test.go new file mode 100644 index 00000000..3327eb4a --- /dev/null +++ b/internal/auth/codex/openai_auth_test.go @@ -0,0 +1,44 @@ +package codex + +import ( + "context" + "io" + "net/http" + "strings" + "sync/atomic" + "testing" +) + +type roundTripFunc func(*http.Request) (*http.Response, error) + +func (f roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) { + return f(req) +} + +func TestRefreshTokensWithRetry_NonRetryableOnlyAttemptsOnce(t *testing.T) { + var calls int32 + auth := &CodexAuth{ + httpClient: &http.Client{ + Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) { + atomic.AddInt32(&calls, 1) + return &http.Response{ + StatusCode: http.StatusBadRequest, + Body: io.NopCloser(strings.NewReader(`{"error":"invalid_grant","code":"refresh_token_reused"}`)), + Header: make(http.Header), + Request: req, + }, nil + }), + }, + } + + _, err := auth.RefreshTokensWithRetry(context.Background(), "dummy_refresh_token", 3) + if err == nil { + t.Fatalf("expected error for non-retryable refresh failure") + } + if !strings.Contains(strings.ToLower(err.Error()), "refresh_token_reused") { + t.Fatalf("expected refresh_token_reused in error, got: %v", err) + } + if got := atomic.LoadInt32(&calls); got != 1 { + t.Fatalf("expected 1 refresh attempt, got %d", got) + } +}