controller v0.242.0: a removed app is listed with its kept backup; five small ones (R-487 R-491 R-490 R-489 R-476 R-456)
gates / gates (push) Successful in 14s

R-487: the local backup lists are keyed on the drives, not on what is
deployed — a removed app whose unit was kept is listed with the restore
that reinstalls it, the picker answers for it, and the restore opens the
unit where it sits. R-491: a removal clears the app's update hold.
R-490: /api/system/info reaches the API router and reads the default
storage path. R-489: volumes_removed is the real before/after difference,
[] when none. R-476: a Tier-2 copy is dated by its data, not its manifest.
R-456: the boot-orphan rule is pinned. Every fix red-proofed.
This commit is contained in:
2026-09-13 22:50:18 +02:00
parent c1f62ddae8
commit d698ce343b
22 changed files with 838 additions and 13 deletions
@@ -0,0 +1,37 @@
package backup
import (
"os"
"testing"
)
// R-476 — a refreshed Tier-2 copy is dated by its DATA (the newest dump), not by a manifest that
// moves only when the app's definition changes; a PRESERVED package keeps the manifest date (R-403).
func TestR476_UnitRestoreDateNamesTheDataTimeWhenTheLegWasRefreshed(t *testing.T) {
cov := Tier2Coverage{UnitPackageDate: "2026-09-12T02:15:29Z", UnitDataDate: "2026-09-13T00:30:00Z", CopyLastSuccess: "2026-09-13T01:30:00Z"}
if d, preserved := cov.UnitRestoreDate(); d != "2026-09-13T00:30:00Z" || preserved {
t.Errorf("refreshed leg: got %q preserved=%v, want the dump's time", d, preserved)
}
cov.UnitLegPreserved = true
if d, preserved := cov.UnitRestoreDate(); d != "2026-09-12T02:15:29Z" || !preserved {
t.Errorf("preserved leg: got %q preserved=%v, want the manifest's date", d, preserved)
}
older := Tier2Coverage{UnitPackageDate: "2026-09-13T02:00:00Z", UnitDataDate: "2026-09-12T00:30:00Z"}
if d, _ := older.UnitRestoreDate(); d != "2026-09-13T02:00:00Z" {
t.Errorf("data older than the manifest must not move the date backwards: %q", d)
}
}
// R-476 — the coverage reader fills the data date from the mirrored unit's own artifacts.
func TestR476_CoverageReadsTheUnitDataDate(t *testing.T) {
dest := t.TempDir()
u := tier2UnitDir(dest)
if err := os.MkdirAll(u, 0o755); err != nil {
t.Fatal(err)
}
writeUnitManifest(t, u, []string{"app.sql"}, nil)
cov := tier2CoverageAt(dest)
if cov.UnitDataDate == "" {
t.Fatal("UnitDataDate must be read from the unit")
}
}