package host import ( "context" "encoding/json" "errors" "os" "os/exec" "path/filepath" "strings" "testing" "github.com/carlosframework/platform/internal/release" "github.com/carlosframework/platform/internal/rootparticipation" ) func TestPlan14GenerationInventoryProcessCrash(t *testing.T) { t.Parallel() if dir := os.Getenv("PLAN14_E24_INVENTORY_CHILD"); dir != "" { disk := &rollbackDisk{dir: dir} ledger := &release.RootGenerations{Store: disk} v := generationReconciler{read: func(context.Context) (generationInventory, error) { return generationInventory{Census: rootparticipation.Census{Schema: 1, Box: "box", Enrollment: "en", Migration: 1, Revision: 1, LaunchRevision: 1, Complete: true}}, nil }, kernel: func(context.Context) (string, string, error) { os.Exit(76); return "", "", nil }} if _, err := ledger.Certify(t.Context(), []release.GenerationReservation{}, v.reconcile); err != nil { t.Fatal(err) } t.Fatal("crash boundary not reached") } dir := t.TempDir() disk := &rollbackDisk{dir: dir} ledger := &release.RootGenerations{Store: disk} evidence := release.GenerationEvidence{Box: "box", Enrollment: "en", Migration: 1, Boot: "boot", Installations: strings.Repeat("a", 64), Launches: strings.Repeat("b", 64), Kernel: strings.Repeat("c", 64)} if _, err := ledger.Certify(t.Context(), []release.GenerationReservation{}, func(context.Context, []release.GenerationReservation) (release.GenerationEvidence, error) { return evidence, nil }); err != nil { t.Fatal(err) } cmd := exec.Command(os.Args[0], "-test.run=^TestPlan14GenerationInventoryProcessCrash$", "-test.count=1") cmd.Dir = dir cmd.Env = append(os.Environ(), "PLAN14_E24_INVENTORY_CHILD="+dir) out, err := cmd.CombinedOutput() var exit *exec.ExitError if !errors.As(err, &exit) || exit.ExitCode() != 76 { t.Fatalf("child: %v %s", err, out) } c, err := ledger.Completeness() if err != nil || c.Complete { t.Fatalf("stale certificate survived crash: %+v %v", c, err) } raw, err := os.ReadFile(filepath.Join(dir, "completeness.json")) if err != nil { t.Fatal(err) } var saved release.GenerationCompleteness if json.Unmarshal(raw, &saved) != nil || saved.Complete { t.Fatal("durable invalidation missing") } if _, err := ledger.Certify(t.Context(), []release.GenerationReservation{}, func(context.Context, []release.GenerationReservation) (release.GenerationEvidence, error) { return evidence, nil }); err != nil { t.Fatal(err) } }