mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-04-03 11:12:46 +00:00
79 lines
2.6 KiB
Go
79 lines
2.6 KiB
Go
package executor
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestParseCodexRetryAfter(t *testing.T) {
|
|
now := time.Unix(1_700_000_000, 0)
|
|
|
|
t.Run("resets_in_seconds", func(t *testing.T) {
|
|
body := []byte(`{"error":{"type":"usage_limit_reached","resets_in_seconds":123}}`)
|
|
retryAfter := parseCodexRetryAfter(http.StatusTooManyRequests, body, now)
|
|
if retryAfter == nil {
|
|
t.Fatalf("expected retryAfter, got nil")
|
|
}
|
|
if *retryAfter != 123*time.Second {
|
|
t.Fatalf("retryAfter = %v, want %v", *retryAfter, 123*time.Second)
|
|
}
|
|
})
|
|
|
|
t.Run("prefers resets_at", func(t *testing.T) {
|
|
resetAt := now.Add(5 * time.Minute).Unix()
|
|
body := []byte(`{"error":{"type":"usage_limit_reached","resets_at":` + itoa(resetAt) + `,"resets_in_seconds":1}}`)
|
|
retryAfter := parseCodexRetryAfter(http.StatusTooManyRequests, body, now)
|
|
if retryAfter == nil {
|
|
t.Fatalf("expected retryAfter, got nil")
|
|
}
|
|
if *retryAfter != 5*time.Minute {
|
|
t.Fatalf("retryAfter = %v, want %v", *retryAfter, 5*time.Minute)
|
|
}
|
|
})
|
|
|
|
t.Run("fallback when resets_at is past", func(t *testing.T) {
|
|
resetAt := now.Add(-1 * time.Minute).Unix()
|
|
body := []byte(`{"error":{"type":"usage_limit_reached","resets_at":` + itoa(resetAt) + `,"resets_in_seconds":77}}`)
|
|
retryAfter := parseCodexRetryAfter(http.StatusTooManyRequests, body, now)
|
|
if retryAfter == nil {
|
|
t.Fatalf("expected retryAfter, got nil")
|
|
}
|
|
if *retryAfter != 77*time.Second {
|
|
t.Fatalf("retryAfter = %v, want %v", *retryAfter, 77*time.Second)
|
|
}
|
|
})
|
|
|
|
t.Run("non-429 status code", func(t *testing.T) {
|
|
body := []byte(`{"error":{"type":"usage_limit_reached","resets_in_seconds":30}}`)
|
|
if got := parseCodexRetryAfter(http.StatusBadRequest, body, now); got != nil {
|
|
t.Fatalf("expected nil for non-429, got %v", *got)
|
|
}
|
|
})
|
|
|
|
t.Run("non usage_limit_reached error type", func(t *testing.T) {
|
|
body := []byte(`{"error":{"type":"server_error","resets_in_seconds":30}}`)
|
|
if got := parseCodexRetryAfter(http.StatusTooManyRequests, body, now); got != nil {
|
|
t.Fatalf("expected nil for non-usage_limit_reached, got %v", *got)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestNewCodexStatusErrTreatsCapacityAsRetryableRateLimit(t *testing.T) {
|
|
body := []byte(`{"error":{"message":"Selected model is at capacity. Please try a different model."}}`)
|
|
|
|
err := newCodexStatusErr(http.StatusBadRequest, body)
|
|
|
|
if got := err.StatusCode(); got != http.StatusTooManyRequests {
|
|
t.Fatalf("status code = %d, want %d", got, http.StatusTooManyRequests)
|
|
}
|
|
if err.RetryAfter() != nil {
|
|
t.Fatalf("expected nil explicit retryAfter for capacity fallback, got %v", *err.RetryAfter())
|
|
}
|
|
}
|
|
|
|
func itoa(v int64) string {
|
|
return strconv.FormatInt(v, 10)
|
|
}
|