R-699: a unit that holds no data is never an update-precondition copy (found live on 9202)
gates / gates (push) Successful in 25s
gates / gates (push) Successful in 25s
A just-installed app's unit, captured by the status refresh before any backup, satisfied the precondition on its manifest time; tandoor's PostgreSQL was converted with no backup of its database. Listed still; never a copy on Tier 1 or Tier 2. Red-proof RP6. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -574,3 +574,47 @@ func TestA4_TheOffsiteRunRecordsThePushedDataTime(t *testing.T) {
|
||||
t.Fatalf("after a successful push the data-time record is %+v ok=%v, want the unit's data time", rec, ok)
|
||||
}
|
||||
}
|
||||
|
||||
// R-699 (v0.275.0) — a just-installed app's unit, captured by the status refresh before any backup ran,
|
||||
// holds only the definition. It stays LISTED (restorable as the definition) but is never a copy the
|
||||
// update's precondition leans on; after a data run it is.
|
||||
//
|
||||
// COMPANION RED-PROOF (REPORT.md): drop the DataProven skip in updateTierPoint — the precondition then
|
||||
// accepts the dump-less unit ("Tier 1 … 0s old"), which is what 9202 logged for tandoor on 2026-09-27.
|
||||
func TestR699_ADefinitionOnlyUnitIsNotAPreconditionCopy(t *testing.T) {
|
||||
v := newVTStack(t, "16")
|
||||
if err := v.m.captureRecoveryUnit("app", false); err != nil { // the refresh, right after the install
|
||||
t.Fatal(err)
|
||||
}
|
||||
pts, _ := v.m.ListRestorePoints("app")
|
||||
if len(pts) != 1 || pts[0].DataProven {
|
||||
t.Fatalf("points = %+v, want one listed, NOT proven", pts)
|
||||
}
|
||||
any := func(UpdateTierPoint) bool { return true }
|
||||
if p, ok, _ := v.m.UpdateRestorePoints(context.Background(), "app", any); ok {
|
||||
t.Fatalf("the precondition accepted tier %d at %s — a unit with no data is not a copy", p.Tier, p.At)
|
||||
}
|
||||
// The update's own "back up first" is a data run: afterwards the unit IS a copy.
|
||||
v.m.discoverDBs = func(context.Context) ([]DiscoveredDB, error) {
|
||||
return []DiscoveredDB{{StackName: "app", ContainerName: "app-db", DBType: DBTypePostgres}}, nil
|
||||
}
|
||||
v.m.dumpOne = func(_ context.Context, db DiscoveredDB, dir string, _ *log.Logger, _ bool) DumpResult {
|
||||
p := filepath.Join(dir, "app-postgres.sql")
|
||||
mustWrite(t, p, pgDump(1))
|
||||
return DumpResult{DB: db, FilePath: p}
|
||||
}
|
||||
v.m.perAppTier2 = func(string) error { return nil }
|
||||
if err := v.m.RunAppBackupNow(context.Background(), "app"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok, _ := v.m.UpdateRestorePoints(context.Background(), "app", any); !ok {
|
||||
t.Fatal("after a backup the own unit is still not a copy")
|
||||
}
|
||||
}
|
||||
|
||||
func TestR699_ADefinitionOnlyMirrorIsNotAPreconditionCopy(t *testing.T) {
|
||||
p := Tier2RestorePoint{Restorable: true, CopyDateProven: true, CopyLastSuccess: "2026-09-27T09:36:36Z", DataDate: "2026-09-27T09:36:36Z", DataUnproven: true}
|
||||
if _, ok := p.ProvenCopyTime(); ok {
|
||||
t.Fatal("a mirror of a definition-only unit counted as a proven copy")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user