test: cover openai admin test state transitions
This commit is contained in:
@@ -61,10 +61,12 @@ func newTestContext() (*gin.Context, *httptest.ResponseRecorder) {
|
|||||||
|
|
||||||
type openAIAccountTestRepo struct {
|
type openAIAccountTestRepo struct {
|
||||||
mockAccountRepoForGemini
|
mockAccountRepoForGemini
|
||||||
updatedExtra map[string]any
|
updatedExtra map[string]any
|
||||||
rateLimitedID int64
|
rateLimitedID int64
|
||||||
rateLimitedAt *time.Time
|
rateLimitedAt *time.Time
|
||||||
clearedErrorID int64
|
clearedErrorID int64
|
||||||
|
setErrorID int64
|
||||||
|
setErrorMsg string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *openAIAccountTestRepo) UpdateExtra(_ context.Context, _ int64, updates map[string]any) error {
|
func (r *openAIAccountTestRepo) UpdateExtra(_ context.Context, _ int64, updates map[string]any) error {
|
||||||
@@ -83,6 +85,12 @@ func (r *openAIAccountTestRepo) ClearError(_ context.Context, id int64) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *openAIAccountTestRepo) SetError(_ context.Context, id int64, errorMsg string) error {
|
||||||
|
r.setErrorID = id
|
||||||
|
r.setErrorMsg = errorMsg
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestAccountTestService_OpenAISuccessPersistsSnapshotFromHeaders(t *testing.T) {
|
func TestAccountTestService_OpenAISuccessPersistsSnapshotFromHeaders(t *testing.T) {
|
||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
ctx, recorder := newTestContext()
|
ctx, recorder := newTestContext()
|
||||||
@@ -148,4 +156,120 @@ func TestAccountTestService_OpenAI429PersistsSnapshotAndRateLimitState(t *testin
|
|||||||
require.Equal(t, account.ID, repo.rateLimitedID)
|
require.Equal(t, account.ID, repo.rateLimitedID)
|
||||||
require.NotNil(t, repo.rateLimitedAt)
|
require.NotNil(t, repo.rateLimitedAt)
|
||||||
require.Equal(t, account.ID, repo.clearedErrorID)
|
require.Equal(t, account.ID, repo.clearedErrorID)
|
||||||
|
require.Equal(t, StatusActive, account.Status)
|
||||||
|
require.Empty(t, account.ErrorMessage)
|
||||||
|
require.NotNil(t, account.RateLimitResetAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccountTestService_OpenAI429BodyOnlyPersistsRateLimitAndClearsStaleError(t *testing.T) {
|
||||||
|
gin.SetMode(gin.TestMode)
|
||||||
|
ctx, _ := newTestContext()
|
||||||
|
|
||||||
|
resp := newJSONResponse(http.StatusTooManyRequests, `{"error":{"type":"usage_limit_reached","message":"limit reached","resets_at":"1777283883"}}`)
|
||||||
|
|
||||||
|
repo := &openAIAccountTestRepo{}
|
||||||
|
upstream := &queuedHTTPUpstream{responses: []*http.Response{resp}}
|
||||||
|
svc := &AccountTestService{accountRepo: repo, httpUpstream: upstream}
|
||||||
|
account := &Account{
|
||||||
|
ID: 77,
|
||||||
|
Platform: PlatformOpenAI,
|
||||||
|
Type: AccountTypeOAuth,
|
||||||
|
Status: StatusError,
|
||||||
|
ErrorMessage: "Access forbidden (403): account may be suspended or lack permissions",
|
||||||
|
Concurrency: 1,
|
||||||
|
Credentials: map[string]any{"access_token": "test-token"},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := svc.testOpenAIAccountConnection(ctx, account, "gpt-5.4")
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, account.ID, repo.rateLimitedID)
|
||||||
|
require.NotNil(t, repo.rateLimitedAt)
|
||||||
|
require.Equal(t, account.ID, repo.clearedErrorID)
|
||||||
|
require.Equal(t, StatusActive, account.Status)
|
||||||
|
require.Empty(t, account.ErrorMessage)
|
||||||
|
require.NotNil(t, account.RateLimitResetAt)
|
||||||
|
require.Empty(t, repo.updatedExtra)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccountTestService_OpenAI429ActiveAccountDoesNotClearError(t *testing.T) {
|
||||||
|
gin.SetMode(gin.TestMode)
|
||||||
|
ctx, _ := newTestContext()
|
||||||
|
|
||||||
|
resp := newJSONResponse(http.StatusTooManyRequests, `{"error":{"type":"usage_limit_reached","message":"limit reached","resets_in_seconds":3600}}`)
|
||||||
|
|
||||||
|
repo := &openAIAccountTestRepo{}
|
||||||
|
upstream := &queuedHTTPUpstream{responses: []*http.Response{resp}}
|
||||||
|
svc := &AccountTestService{accountRepo: repo, httpUpstream: upstream}
|
||||||
|
account := &Account{
|
||||||
|
ID: 78,
|
||||||
|
Platform: PlatformOpenAI,
|
||||||
|
Type: AccountTypeOAuth,
|
||||||
|
Status: StatusActive,
|
||||||
|
Concurrency: 1,
|
||||||
|
Credentials: map[string]any{"access_token": "test-token"},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := svc.testOpenAIAccountConnection(ctx, account, "gpt-5.4")
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, account.ID, repo.rateLimitedID)
|
||||||
|
require.NotNil(t, repo.rateLimitedAt)
|
||||||
|
require.Zero(t, repo.clearedErrorID)
|
||||||
|
require.Equal(t, StatusActive, account.Status)
|
||||||
|
require.NotNil(t, account.RateLimitResetAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccountTestService_OpenAI429WithoutResetSignalDoesNotMutateRuntimeState(t *testing.T) {
|
||||||
|
gin.SetMode(gin.TestMode)
|
||||||
|
ctx, _ := newTestContext()
|
||||||
|
|
||||||
|
resp := newJSONResponse(http.StatusTooManyRequests, `{"error":{"type":"usage_limit_reached","message":"limit reached"}}`)
|
||||||
|
|
||||||
|
repo := &openAIAccountTestRepo{}
|
||||||
|
upstream := &queuedHTTPUpstream{responses: []*http.Response{resp}}
|
||||||
|
svc := &AccountTestService{accountRepo: repo, httpUpstream: upstream}
|
||||||
|
account := &Account{
|
||||||
|
ID: 79,
|
||||||
|
Platform: PlatformOpenAI,
|
||||||
|
Type: AccountTypeOAuth,
|
||||||
|
Status: StatusError,
|
||||||
|
ErrorMessage: "stale 403",
|
||||||
|
Concurrency: 1,
|
||||||
|
Credentials: map[string]any{"access_token": "test-token"},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := svc.testOpenAIAccountConnection(ctx, account, "gpt-5.4")
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Zero(t, repo.rateLimitedID)
|
||||||
|
require.Nil(t, repo.rateLimitedAt)
|
||||||
|
require.Zero(t, repo.clearedErrorID)
|
||||||
|
require.Equal(t, StatusError, account.Status)
|
||||||
|
require.Equal(t, "stale 403", account.ErrorMessage)
|
||||||
|
require.Nil(t, account.RateLimitResetAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccountTestService_OpenAI401SetsPermanentErrorOnly(t *testing.T) {
|
||||||
|
gin.SetMode(gin.TestMode)
|
||||||
|
ctx, _ := newTestContext()
|
||||||
|
|
||||||
|
resp := newJSONResponse(http.StatusUnauthorized, `{"error":"bad token"}`)
|
||||||
|
|
||||||
|
repo := &openAIAccountTestRepo{}
|
||||||
|
upstream := &queuedHTTPUpstream{responses: []*http.Response{resp}}
|
||||||
|
svc := &AccountTestService{accountRepo: repo, httpUpstream: upstream}
|
||||||
|
account := &Account{
|
||||||
|
ID: 80,
|
||||||
|
Platform: PlatformOpenAI,
|
||||||
|
Type: AccountTypeOAuth,
|
||||||
|
Status: StatusActive,
|
||||||
|
Concurrency: 1,
|
||||||
|
Credentials: map[string]any{"access_token": "test-token"},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := svc.testOpenAIAccountConnection(ctx, account, "gpt-5.4")
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, account.ID, repo.setErrorID)
|
||||||
|
require.Contains(t, repo.setErrorMsg, "Authentication failed (401)")
|
||||||
|
require.Zero(t, repo.rateLimitedID)
|
||||||
|
require.Zero(t, repo.clearedErrorID)
|
||||||
|
require.Nil(t, account.RateLimitResetAt)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user