//go:build linux package host import ( "os" "path/filepath" "reflect" "testing" "github.com/carlosframework/platform/internal/hostbox" ) func TestServingParkIncompleteRecoveryRechecksEnrollment(t *testing.T) { for _, change := range []string{"enrollment", "binding"} { t.Run(change, func(t *testing.T) { f := newServingRootFixture(t, true) a, err := f.park() if err != nil { t.Fatal(err) } f.tags(a.Successor.Stamp) before, err := f.p.ledger.read(a.ID) if err != nil || before.Complete || !before.Parked { t.Fatal("expected pending completion", err) } actor := f.actor if change == "enrollment" { f.actor.Enrollment = "new-enrollment" } else { f.actor.Binding = "8" } // Reconstruct the authority object, retaining only durable journals. root := &servingParkRoot{root: f.p.root, ledger: &servingParkLedger{state: f.p.ledger.state, fs: f.p.ledger.fs, journal: f.f.journal, now: f.p.ledger.now}} if err := root.completeServingDatabasePark(t.Context(), f.conn, a.ID, a.Successor); err == nil { t.Fatal("changed deployment identity completed old park") } if _, err := root.parkServingDatabase(t.Context(), f.conn, a.Successor, hostbox.ServingArtifactIdentity{}); err == nil { t.Fatal("changed deployment identity replayed old park") } after, err := root.ledger.read(a.ID) if err != nil || !reflect.DeepEqual(before, after) { t.Fatal("refusal rewrote pending evidence", err) } // Restoring the recorded identity permits the ordinary completion. // A real enrollment change needs separately established root evidence. f.actor = actor if err := root.completeServingDatabasePark(t.Context(), f.conn, a.ID, a.Successor); err != nil { t.Fatal(err) } after, err = root.ledger.read(a.ID) if err != nil || !after.Complete { t.Fatal("completion did not recover", err) } after.Complete = before.Complete if !reflect.DeepEqual(before, after) { t.Fatal("completion changed source, receipts or retention clock") } for suffix, want := range map[string]string{"": "served bytes", ".gen": "G", "-wal": "WAL", "-shm": "SHM"} { body, err := os.ReadFile(filepath.Join(f.f.guard.DataDir, "instances", ".serving-parked", a.ID, filepath.Base(f.db)+suffix)) if err != nil || string(body) != want { t.Fatalf("retained %s: %q %v", suffix, body, err) } } }) } }