package audit import ( "context" "testing" "github.com/dtoro/oikos/internal/db" "github.com/google/uuid" ) // Integration tests against a real Postgres, guarded by // OIKOS_TEST_DATABASE_URL (same convention as internal/scheduler). func newAuditPool(t *testing.T) *db.Pool { t.Helper() base := getenvOrDefault("OIKOS_TEST_DATABASE_URL", "") if base == "" { t.Skip("OIKOS_TEST_DATABASE_URL not set — skipping integration test") } return createTestDB(t, base) } func TestReportFlagsOrphanAndDeadAndDown(t *testing.T) { pool := newAuditPool(t) ctx := context.Background() // An orphan check entity (truncated random slug, the legacy bug shape). mustExec(t, pool, ctx, `INSERT INTO entities (id, slug, type, name, state, attributes, version, created_at, updated_at) VALUES ($1,'check:ssh-script:0d31fdd1','check','check:ssh-script:0d31fdd1','active','{}'::jsonb,1,now(),now())`, uuid.New()) // An active entity + a check_def on it stuck down. target := uuid.New() mustExec(t, pool, ctx, `INSERT INTO entities (id, slug, type, name, state, attributes, version, created_at, updated_at) VALUES ($1,'service:demo','service','demo','active','{}'::jsonb,1,now(),now())`, target) checkE := uuid.New() mustExec(t, pool, ctx, `INSERT INTO entities (id, slug, type, name, state, attributes, version, created_at, updated_at) VALUES ($1,'check:http:service:demo:0','check','c','active','{}'::jsonb,1,now(),now())`, checkE) mustExec(t, pool, ctx, `INSERT INTO check_defs (entity_id, target_id, target_type, kind, config, interval_s, timeout_s, enabled, last_run_at, last_health) VALUES ($1,$2,'service','http','{}'::jsonb,60,30,true,now(),'down')`, checkE, target) // A deprecated entity still carrying an enabled check (dead_checks). dep := uuid.New() mustExec(t, pool, ctx, `INSERT INTO entities (id, slug, type, name, state, attributes, version, created_at, updated_at) VALUES ($1,'service:old','service','old','deprecated','{}'::jsonb,1,now(),now())`, dep) depCheck := uuid.New() mustExec(t, pool, ctx, `INSERT INTO entities (id, slug, type, name, state, attributes, version, created_at, updated_at) VALUES ($1,'check:http:service:old:0','check','c','active','{}'::jsonb,1,now(),now())`, depCheck) mustExec(t, pool, ctx, `INSERT INTO check_defs (entity_id, target_id, target_type, kind, config, interval_s, timeout_s, enabled, last_run_at) VALUES ($1,$2,'service','http','{}'::jsonb,60,30,true,now())`, depCheck, dep) findings, summary := Report(ctx, pool) byCat := map[string]int{} for _, f := range findings { byCat[f.Category] = f.Count } if byCat["orphan_checks"] < 1 { t.Errorf("orphan_checks = %d, want >=1", byCat["orphan_checks"]) } if byCat["down_checks"] < 1 { t.Errorf("down_checks = %d, want >=1", byCat["down_checks"]) } if byCat["dead_checks"] < 1 { t.Errorf("dead_checks = %d, want >=1", byCat["dead_checks"]) } if summary.TotalFindings < 3 { t.Errorf("TotalFindings = %d, want >=3", summary.TotalFindings) } }