package orchestrator import ( "fmt" "os" "path/filepath" "testing" "time" "scm.bstein.dev/bstein/ananke/internal/state" ) // TestHookReportWrappersCoverage runs one orchestration or CLI step. // Signature: TestHookReportWrappersCoverage(t *testing.T). // Why: ensures every report-specific testing hook is exercised from the top-level // testing module so hook coverage never drifts below quality gates. func TestHookReportWrappersCoverage(t *testing.T) { cfg := lifecycleConfig(t) orch := newLiveHookOrchestrator(t, cfg) if got := orch.TestHookReportArchiveDir(); got == "" { t.Fatalf("expected non-empty report archive dir") } if got := orch.TestHookStartupReportPath(); got == "" { t.Fatalf("expected startup report path") } if got := orch.TestHookStartupProgressPath(); got == "" { t.Fatalf("expected startup progress path") } if got := orch.TestHookLastShutdownReportPath(); got == "" { t.Fatalf("expected last shutdown report path") } orch.TestHookBeginStartupReport("wrapper-coverage") orch.TestHookSetStartupPhase("wrapper-phase", "coverage detail") orch.TestHookNoteStartupCheckState("wrapper-check", "running", "detail") orch.TestHookNoteStartupCheck("wrapper-final", true, "ok") orch.TestHookNoteStartupAutoHeal("auto-heal detail") orch.TestHookPersistStartupProgress("running") orch.TestHookPersistStartupProgressNil() orch.TestHookFinalizeStartupReport(fmt.Errorf("intentional failure")) if !orch.TestHookFinalizeStartupReportSnapshot(nil) { t.Fatalf("expected finalize snapshot wrapper success") } orch.TestHookFinalizeStartupReport(nil) // nil-active-report branch progressPath := orch.TestHookStartupProgressPath() if _, err := os.Stat(progressPath); err != nil { t.Fatalf("expected startup progress at %s: %v", progressPath, err) } if err := orch.TestHookWriteStartupReportFileNil(filepath.Join(cfg.State.Dir, "nil-report.json")); err != nil { t.Fatalf("expected nil report write no-op, got %v", err) } if err := orch.TestHookWriteStartupReportFile(filepath.Join(cfg.State.Dir, "wrapper-report.json"), "running"); err != nil { t.Fatalf("expected startup report write success, got %v", err) } recStartup := state.RunRecord{ ID: "wrapper-startup-1", Action: "startup", Reason: "wrapper", StartedAt: time.Now().UTC().Add(-2 * time.Second), EndedAt: time.Now().UTC(), Success: true, } if err := orch.TestHookWriteRunRecordArtifact(recStartup); err != nil { t.Fatalf("expected startup artifact write success, got %v", err) } recShutdown := state.RunRecord{ ID: "wrapper-shutdown-1", Action: "shutdown", Reason: "wrapper", StartedAt: time.Now().UTC().Add(-2 * time.Second), EndedAt: time.Now().UTC(), Success: true, } if err := orch.TestHookWriteRunRecordArtifact(recShutdown); err != nil { t.Fatalf("expected shutdown artifact write success, got %v", err) } orch.TestHookFinalizeRecord("startup", "wrapper-finalize-ok", "") orch.TestHookFinalizeRecord("startup", "wrapper-finalize-fail", "boom") t.Run("report-writer-error-branches", func(t *testing.T) { cfgErr := lifecycleConfig(t) root := t.TempDir() reportDirFile := filepath.Join(root, "reports-file") if err := os.WriteFile(reportDirFile, []byte("x"), 0o644); err != nil { t.Fatalf("write report dir file: %v", err) } cfgErr.State.ReportsDir = reportDirFile orchErr := newLiveHookOrchestrator(t, cfgErr) if err := orchErr.TestHookWriteRunRecordArtifact(state.RunRecord{ ID: "startup-error-path", Action: "startup", Reason: "test", StartedAt: time.Now().UTC(), }); err == nil { t.Fatalf("expected report archive dir creation failure") } cfgWriteErr := lifecycleConfig(t) cfgWriteErr.State.ReportsDir = filepath.Join(root, "reports-ok") orchWriteErr := newLiveHookOrchestrator(t, cfgWriteErr) if err := os.MkdirAll(cfgWriteErr.State.ReportsDir, 0o755); err != nil { t.Fatalf("mkdir reports dir: %v", err) } blockPath := filepath.Join(cfgWriteErr.State.ReportsDir, "collision.json") if err := os.Mkdir(blockPath, 0o755); err != nil { t.Fatalf("mkdir collision path: %v", err) } if err := orchWriteErr.TestHookWriteRunRecordArtifact(state.RunRecord{ ID: "collision", Action: "startup", Reason: "test", StartedAt: time.Now().UTC(), }); err == nil { t.Fatalf("expected artifact write collision error") } cfgStartupWriteErr := lifecycleConfig(t) parentFile := filepath.Join(root, "startup-parent-file") if err := os.WriteFile(parentFile, []byte("x"), 0o644); err != nil { t.Fatalf("write parent file: %v", err) } cfgStartupWriteErr.State.Dir = filepath.Join(root, "startup-state-ok") orchStartupWriteErr := newLiveHookOrchestrator(t, cfgStartupWriteErr) if err := orchStartupWriteErr.TestHookWriteStartupReportFile(filepath.Join(parentFile, "report.json"), "running"); err == nil { t.Fatalf("expected startup report mkdir error") } orchStartupWriteErr.TestHookPersistStartupProgress("running") }) }