Files
story/internal/diagnostics/acceptance_snapshot_integration_test.go
T

91 lines
4.3 KiB
Go
Raw Normal View History

2026-08-26 06:41:07 +08:00
package diagnostics
import (
"context"
"errors"
"os"
"testing"
"data-terminal-cloud/internal/audit"
"data-terminal-cloud/internal/database"
"data-terminal-cloud/internal/idempotency"
"data-terminal-cloud/internal/identity"
"github.com/google/uuid"
)
func TestAcceptanceSnapshotIsAuditedIdempotentAndTenantScoped(t *testing.T) {
databaseURL := os.Getenv("TEST_DATABASE_URL")
if databaseURL == "" {
t.Skip("TEST_DATABASE_URL is not set")
}
ctx := context.Background()
pool, err := database.Open(ctx, databaseURL, "acceptance-snapshot-test")
if err != nil {
t.Fatal(err)
}
defer pool.Close()
service, err := NewService(pool, idempotency.NewExecutor(pool), audit.NewRepository())
if err != nil {
t.Fatal(err)
}
admin := identity.Principal{Issuer: "http://localhost:58180/realms/voice-local", Subject: "00000000-0000-0000-0000-000000000101"}
tenantPublicID := "10000000-0000-0000-0000-000000000010"
key := "acceptance-snapshot-" + uuid.NewString()
requestID := "acceptance-snapshot-test-" + uuid.NewString()
alertID := uuid.NewString()
missingConversationID := uuid.NewString()
defer func() {
_, _ = pool.Exec(context.Background(), `DELETE FROM audit_event WHERE request_id=$1`, requestID)
_, _ = pool.Exec(context.Background(), `DELETE FROM idempotency_record WHERE idempotency_key=$1`, key)
_, _ = pool.Exec(context.Background(), `DELETE FROM alert_incident WHERE public_id=$1::uuid`, alertID)
}()
if _, err = pool.Exec(ctx, `INSERT INTO alert_incident(public_id,tenant_id,rule_code,category,severity,status,fingerprint,title,summary,resource_type,resource_public_id,first_detected_at,last_detected_at) VALUES($1::uuid,'10000000-0000-0000-0000-000000000001'::uuid,'ACCEPTANCE_SNAPSHOT_TEST','TECHNICAL','HIGH','OPEN',$2,'验收快照合成阻断','验证缺失资源定位','conversation',$3::uuid,now(),now())`, alertID, "acceptance-snapshot-test:"+alertID, missingConversationID); err != nil {
t.Fatal(err)
}
input := AcceptanceSnapshotInput{
CandidateVersion: "0.50.0-rc.1",
BuildDigest: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
Environment: "LAB",
RunType: "REAL_DEVICE_PROVIDER",
Scope: "本地真实OIDC与平台技术预检",
RequiredDependencies: []string{
"oidc_jwks",
},
Reason: "生成可归档的阶段8技术验收证据",
}
first, created, err := service.ExportAcceptanceSnapshot(ctx, admin, tenantPublicID, key, requestID, input)
if err != nil || !created {
t.Fatalf("first=%+v created=%t err=%v", first, created, err)
}
if first.ID == "" || first.Database.MigrationVersion < 39 || first.Database.Dirty || first.RedactionPolicy != "ops-acceptance-minimal-v1" || len(first.ExternalDependencies) != 1 || len(first.Gates) != 8 {
2026-08-26 06:41:07 +08:00
t.Fatalf("unexpected snapshot=%+v", first)
}
if first.ExternalDependencies[0].Dependency != "oidc_jwks" || first.ExternalDependencies[0].ServiceName != "api" {
t.Fatalf("unexpected dependency=%+v", first.ExternalDependencies[0])
}
var foundBlockingAlert bool
for _, item := range first.Alerts.BlockingItems {
if item.ID == alertID {
foundBlockingAlert = item.RuleCode == "ACCEPTANCE_SNAPSHOT_TEST" && item.ResourceID == missingConversationID && item.ResourceState == "MISSING"
}
}
if !foundBlockingAlert || first.Alerts.Blocking == 0 || first.Gates[5].Code != "critical_alerts_clear" || first.Gates[5].Satisfied {
t.Fatalf("blocking alert evidence=%+v gates=%+v", first.Alerts, first.Gates)
}
2026-08-26 22:04:38 +08:00
if first.Gates[6].Code != "platform_health_current" || first.PlatformHealth.State == "" {
t.Fatalf("platform health=%+v gates=%+v", first.PlatformHealth, first.Gates)
}
if first.Gates[7].Code != "production_infrastructure_ready" || !first.Gates[7].Satisfied || first.ProductionInfrastructure.Applicable {
t.Fatalf("production infrastructure=%+v gates=%+v", first.ProductionInfrastructure, first.Gates)
}
2026-08-26 06:41:07 +08:00
replayed, createdAgain, err := service.ExportAcceptanceSnapshot(ctx, admin, tenantPublicID, key, requestID, input)
if err != nil || createdAgain || replayed.ID != first.ID || !replayed.GeneratedAt.Equal(first.GeneratedAt) {
t.Fatalf("replayed=%+v created=%t err=%v", replayed, createdAgain, err)
}
if _, _, err = service.ExportAcceptanceSnapshot(ctx, admin, "20000000-0000-0000-0000-000000000010", "cross-"+key, requestID, input); !errors.Is(err, ErrAccessDenied) {
t.Fatalf("cross tenant error=%v", err)
}
}