Files
supply-intelligence/internal/probe/service_test.go
2026-05-12 18:49:52 +08:00

150 lines
4.9 KiB
Go

package probe
import (
"context"
"errors"
"testing"
"time"
"supply-intelligence/internal/domain"
"supply-intelligence/internal/repository"
)
func TestServiceEvaluateHTTPResultSuccess(t *testing.T) {
repo := repository.NewMemoryRepository()
service := NewService(repo)
service.now = func() time.Time { return time.Unix(1000, 0).UTC() }
result, err := service.EvaluateHTTPResult(context.Background(), EvaluateInput{
AccountID: 1,
Platform: "openai",
CurrentStatus: domain.AccountStatusSuspended,
StatusCode: 200,
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result.Classification != domain.ProbeClassificationSuccess {
t.Fatalf("unexpected classification: %q", result.Classification)
}
if result.RoutingState.AccountStatus != domain.AccountStatusActive {
t.Fatalf("unexpected account status: %q", result.RoutingState.AccountStatus)
}
if !result.RoutingState.RoutingEnabled {
t.Fatalf("expected routing enabled")
}
if result.RoutingState.ReasonCode != "ok" {
t.Fatalf("unexpected reason code: %q", result.RoutingState.ReasonCode)
}
if result.RoutingState.Version != 1 {
t.Fatalf("unexpected version: %d", result.RoutingState.Version)
}
}
func TestServiceEvaluateHTTPResultExplicitFailure(t *testing.T) {
repo := repository.NewMemoryRepository()
service := NewService(repo)
service.now = func() time.Time { return time.Unix(1001, 0).UTC() }
repo.UpsertRoutingState(context.Background(), domain.AccountRoutingState{
AccountID: 2,
Platform: "openai",
AccountStatus: domain.AccountStatusActive,
RoutingEnabled: true,
RiskScore: 20,
ReasonCode: "ok",
LastProbeAt: time.Unix(999, 0).UTC(),
Version: 4,
})
result, err := service.EvaluateHTTPResult(context.Background(), EvaluateInput{
AccountID: 2,
Platform: "openai",
CurrentStatus: domain.AccountStatusActive,
StatusCode: 401,
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result.Classification != domain.ProbeClassificationExplicitFailure {
t.Fatalf("unexpected classification: %q", result.Classification)
}
if result.RoutingState.AccountStatus != domain.AccountStatusSuspended {
t.Fatalf("unexpected account status: %q", result.RoutingState.AccountStatus)
}
if result.RoutingState.RoutingEnabled {
t.Fatalf("expected routing disabled")
}
if result.RoutingState.ReasonCode != "auth_rejected" {
t.Fatalf("unexpected reason code: %q", result.RoutingState.ReasonCode)
}
if result.RoutingState.Version != 2 {
t.Fatalf("unexpected version: %d", result.RoutingState.Version)
}
}
func TestServiceEvaluateHTTPResultInconclusive(t *testing.T) {
repo := repository.NewMemoryRepository()
service := NewService(repo)
service.now = func() time.Time { return time.Unix(1002, 0).UTC() }
result, err := service.EvaluateHTTPResult(context.Background(), EvaluateInput{
AccountID: 3,
Platform: "openai",
CurrentStatus: domain.AccountStatusSuspended,
TransportError: errors.New("dial tcp timeout"),
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result.Classification != domain.ProbeClassificationInconclusive {
t.Fatalf("unexpected classification: %q", result.Classification)
}
if result.RoutingState.AccountStatus != domain.AccountStatusSuspended {
t.Fatalf("unexpected account status: %q", result.RoutingState.AccountStatus)
}
if result.RoutingState.RoutingEnabled {
t.Fatalf("expected routing disabled for suspended account")
}
if result.RoutingState.ReasonCode != "transport_error" {
t.Fatalf("unexpected reason code: %q", result.RoutingState.ReasonCode)
}
if result.RoutingState.RiskScore != 60 {
t.Fatalf("unexpected risk score: %d", result.RoutingState.RiskScore)
}
}
func TestServiceEvaluateHTTPResultDisablesOnlyAfterThirdExplicitFailure(t *testing.T) {
repo := repository.NewMemoryRepository()
service := NewService(repo)
service.now = func() time.Time { return time.Unix(1003, 0).UTC() }
result, err := service.EvaluateHTTPResult(context.Background(), EvaluateInput{
AccountID: 4,
Platform: "openai",
CurrentStatus: domain.AccountStatusSuspended,
StatusCode: 401,
ConsecutiveExplicitFailures: 2,
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result.RoutingState.AccountStatus != domain.AccountStatusSuspended {
t.Fatalf("expected suspended before threshold, got %q", result.RoutingState.AccountStatus)
}
result, err = service.EvaluateHTTPResult(context.Background(), EvaluateInput{
AccountID: 4,
Platform: "openai",
CurrentStatus: domain.AccountStatusSuspended,
StatusCode: 401,
ConsecutiveExplicitFailures: 3,
})
if err != nil {
t.Fatalf("unexpected error on threshold failure: %v", err)
}
if result.RoutingState.AccountStatus != domain.AccountStatusDisabled {
t.Fatalf("expected disabled at threshold, got %q", result.RoutingState.AccountStatus)
}
}