package service import ( "context" "encoding/json" "fmt" "io" "net/http" "net/http/httptest" "net/url" "strings" "testing" "time" "github.com/Wei-Shaw/sub2api/internal/config" "github.com/Wei-Shaw/sub2api/internal/pkg/tlsfingerprint" "github.com/gin-gonic/gin" "github.com/stretchr/testify/require" ) type intelligentRunnerRepo struct { AccountRepository account *Account writes int } func (r *intelligentRunnerRepo) GetByID(context.Context, int64) (*Account, error) { return r.account, nil } func (r *intelligentRunnerRepo) SetError(context.Context, int64, string) error { r.writes++ return nil } func (r *intelligentRunnerRepo) UpdateExtra(context.Context, int64, map[string]any) error { r.writes++ return nil } func (r *intelligentRunnerRepo) SetRateLimited(context.Context, int64, time.Time) error { r.writes++ return nil } type intelligentNetworkUpstream struct{ client *http.Client } func (h intelligentNetworkUpstream) Do(req *http.Request, _ string, _ int64, _ int) (*http.Response, error) { return h.client.Do(req) } func (h intelligentNetworkUpstream) DoWithTLS(req *http.Request, p string, id int64, n int, _ *tlsfingerprint.Profile) (*http.Response, error) { return h.Do(req, p, id, n) } func intelligentRunnerFixture(t *testing.T, upstream http.HandlerFunc) (*AccountTestService, *intelligentRunnerRepo) { t.Helper() server := httptest.NewServer(upstream) t.Cleanup(server.Close) repo := &intelligentRunnerRepo{account: &Account{ID: 81, Platform: PlatformOpenAI, Type: AccountTypeAPIKey, Concurrency: 1, Credentials: map[string]any{"api_key": "sk-private-test-secret-abc123", "base_url": server.URL}, Extra: map[string]any{"anti_degradation": true}}} cfg := &config.Config{} cfg.Security.URLAllowlist.AllowInsecureHTTP = true svc := NewAccountTestService(repo, nil, nil, nil, nil, intelligentNetworkUpstream{client: server.Client()}, cfg, nil) return svc, repo } func TestResolveIntelligentTestModelCodexFallback(t *testing.T) { codex := &Account{Platform: PlatformOpenAI, Type: AccountTypeOAuth} require.Equal(t, "gpt-5.3-codex", resolveIntelligentTestModel(codex, "")) for _, configured := range []string{"gpt-5.4", "GPT-5.4", "gpt-5.4-mini"} { require.Equal(t, configured, resolveIntelligentTestModel(codex, configured)) } require.Equal(t, "gpt-5.3-codex", resolveIntelligentTestModel(codex, "gpt-5.3-codex")) apiKey := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey} require.Equal(t, "gpt-5.4", resolveIntelligentTestModel(apiKey, "gpt-5.4")) } func TestIntelligentRunnerActualHTTPPromptOutputAndRaw(t *testing.T) { gin.SetMode(gin.TestMode) var received map[string]any svc, repo := intelligentRunnerFixture(t, func(w http.ResponseWriter, r *http.Request) { require.Equal(t, "/v1/responses", r.URL.Path) require.Equal(t, "Bearer sk-private-test-secret-abc123", r.Header.Get("Authorization")) require.NoError(t, json.NewDecoder(r.Body).Decode(&received)) w.Header().Set("Content-Type", "text/event-stream") fmt.Fprint(w, "data: {\"type\":\"response.output_text.delta\",\"delta\":\"24 - 6 = 18; 18 / 2 + 3 = 12.\\nANSWER: 12\"}\n\ndata: {\"type\":\"response.completed\"}\n\n") }) record := &IntelligentTestRecord{AccountID: 81, Input: "Please solve the configured candy question", Model: "test-model", ConfigSnapshot: &IntelligentTestConfig{Model: "test-model"}} require.NoError(t, svc.RunIntelligentTest(context.Background(), record)) body, _ := json.Marshal(received) require.Contains(t, string(body), record.Input) require.NotContains(t, string(body), `"hi"`) require.Contains(t, record.Result, "ANSWER: 12") require.Contains(t, record.RawResponse, "response.completed") require.NotContains(t, record.RawResponse, "sk-private") require.Equal(t, 0, repo.writes) require.Equal(t, true, repo.account.Extra["anti_degradation"]) } func TestIntelligentRunnerFailureDoesNotModifyAccountAndRedacts(t *testing.T) { for _, status := range []int{401, 429, 404} { t.Run(fmt.Sprint(status), func(t *testing.T) { svc, repo := intelligentRunnerFixture(t, func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(status) fmt.Fprint(w, `{"error":{"message":"upstream error sk-private-test-secret-abc123"}}`) }) record := &IntelligentTestRecord{AccountID: 81, Input: "test", Model: "model", ConfigSnapshot: &IntelligentTestConfig{}} require.Error(t, svc.RunIntelligentTest(context.Background(), record)) require.Equal(t, map[int]string{401: "account_error", 429: "rate_limited", 404: "model_error"}[status], record.Status) require.NotContains(t, record.RawResponse, "sk-private-test-secret") require.NotContains(t, record.ErrorMessage, "sk-private-test-secret") require.Equal(t, 0, repo.writes) }) } } func TestIntelligentRunnerIncompleteAndSyntheticNeverSuccess(t *testing.T) { svc, repo := intelligentRunnerFixture(t, func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "data: {\"type\":\"response.output_text.delta\",\"delta\":\"ANSWER: 12\"}\n\n") }) record := &IntelligentTestRecord{AccountID: 81, Input: "test", Model: "model", ConfigSnapshot: &IntelligentTestConfig{}} require.Error(t, svc.RunIntelligentTest(context.Background(), record)) require.Equal(t, "failed", record.Status) repo.account.Extra["synthetic_ui_test"] = true require.Error(t, svc.RunIntelligentTest(context.Background(), record)) require.NotContains(t, record.Result, "healthy and interactive") } func TestIntelligentRunnerContextCancellation(t *testing.T) { svc, _ := intelligentRunnerFixture(t, func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/event-stream") fmt.Fprint(w, "data: {\"type\":\"response.output_text.delta\",\"delta\":\"working\"}\n\n") w.(http.Flusher).Flush() <-r.Context().Done() }) ctx, cancel := context.WithTimeout(context.Background(), 80*time.Millisecond) defer cancel() record := &IntelligentTestRecord{AccountID: 81, Input: "test", ConfigSnapshot: &IntelligentTestConfig{}} require.Error(t, svc.RunIntelligentTest(ctx, record)) } func TestIntelligentRawCompletionRejectsTruncation(t *testing.T) { cases := []struct { raw string ok bool }{{`{"stop_reason":"end_turn"}`, true}, {`{"stop_reason":"max_tokens"}`, false}, {"data: {\"candidates\":[{\"finishReason\":\"STOP\"}]}\n", true}, {"data: {\"candidates\":[{\"finishReason\":\"MAX_TOKENS\"}]}\n", false}, {"data: {\"type\":\"response.completed\",\"response\":{\"status\":\"incomplete\"}}\n", false}, {"data: {\"type\":\"message_stop\"}\n", true}, {`{"choices":[{"finish_reason":null}]}`, false}} for _, c := range cases { require.Equal(t, c.ok, intelligentRawComplete(c.raw), c.raw) } } func TestIntelligentSVGAndCandyEvaluation(t *testing.T) { good := `Pelican` safe, err := SanitizeIntelligentTestSVG("```svg\n" + good + "\n```") require.NoError(t, err) require.Contains(t, safe, "`, ``, ``, ``, ``, `only text`, ``} { _, err := SanitizeIntelligentTestSVG(bad) require.Error(t, err, bad) } evaluators := DefaultIntelligentTestEvaluators() result := evaluators["svg_structure"].Evaluate(good, IntelligentTestConfig{}) require.Equal(t, "completed", result.Status) require.Nil(t, result.Score) require.Equal(t, "not_evaluated", result.Detail["answer_verdict"]) cfg := IntelligentTestConfig{ExpectedAnswer: "12"} require.Equal(t, "incorrect", evaluators["exact_answer"].Evaluate("ANSWER: 11", cfg).Detail["answer_verdict"]) require.Equal(t, "undetermined", evaluators["exact_answer"].Evaluate("ANSWER: 12\nANSWER: 11", cfg).Detail["answer_verdict"]) require.Equal(t, "correct", evaluators["exact_answer"].Evaluate("12", cfg).Detail["answer_verdict"]) require.Equal(t, "completed", evaluators["exact_answer"].Evaluate("reasoning\nANSWER: 12", cfg).Status) } func TestIntelligentCaptureBounded(t *testing.T) { capture := &intelligentCapture{} n, err := io.Copy(capture, strings.NewReader(strings.Repeat("x", 2<<20))) require.NoError(t, err) require.EqualValues(t, 2<<20, n) require.Equal(t, 1<<20, capture.body.Len()) require.True(t, capture.truncated) } type intelligentRedirectUpstream struct { target *url.URL client *http.Client requests int } func (h *intelligentRedirectUpstream) Do(req *http.Request, _ string, _ int64, _ int) (*http.Response, error) { h.requests++ copy := req.Clone(req.Context()) target := *req.URL target.Scheme = h.target.Scheme target.Host = h.target.Host copy.URL = &target copy.Host = "" return h.client.Do(copy) } func (h *intelligentRedirectUpstream) DoWithTLS(req *http.Request, p string, id int64, n int, _ *tlsfingerprint.Profile) (*http.Response, error) { return h.Do(req, p, id, n) } func TestIntelligentAntigravitySingleObservationPreservesPolicy(t *testing.T) { var sent string server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { body, _ := io.ReadAll(r.Body) sent = string(body) w.WriteHeader(429) fmt.Fprint(w, `{"error":{"code":429,"status":"RESOURCE_EXHAUSTED"}}`) })) defer server.Close() target, _ := url.Parse(server.URL) transport := &intelligentRedirectUpstream{target: target, client: server.Client()} repo := &intelligentRunnerRepo{account: &Account{ID: 81, Platform: PlatformAntigravity, Type: AccountTypeOAuth, Concurrency: 1, Extra: map[string]any{"anti_degradation": true}}} gateway := &AntigravityGatewayService{httpUpstream: transport, accountRepo: repo} capture := &intelligentCapture{} ctx := context.WithValue(context.Background(), intelligentRunKey{}, &intelligentRunContext{prompt: "draw the configured pelican", capture: capture}) body, err := intelligentAntigravityBody(ctx, []byte(`{"model":"test","request":{"contents":[{"parts":[{"text":"."}]}],"generationConfig":{"maxOutputTokens":1}}}`)) require.NoError(t, err) resp, err := gateway.runIntelligentAntigravity(ctx, repo.account, "fake-access-token", body) require.NoError(t, err) _, err = io.ReadAll(resp.Body) require.NoError(t, err) require.NoError(t, resp.Body.Close()) require.Equal(t, 429, resp.StatusCode) require.Equal(t, 1, transport.requests) require.Zero(t, repo.writes) require.Contains(t, sent, "draw the configured pelican") require.Contains(t, sent, `"maxOutputTokens":8192`) require.Equal(t, true, repo.account.Extra["anti_degradation"]) }