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) } }