package backup import ( "encoding/json" "os" "path/filepath" "testing" "time" ) func writeKeptUnit(t *testing.T, unitDir, hdd string, withData bool, at time.Time) { t.Helper() if err := os.MkdirAll(filepath.Join(unitDir, "compose"), 0o755); err != nil { t.Fatal(err) } man := RecoveryManifest{SchemaVersion: 2, AppName: "nextcloud"} if withData { man.DBDumps = []string{"nextcloud-mariadb.sql"} } b, _ := json.Marshal(man) if err := os.WriteFile(UnitManifestFile(unitDir), b, 0o644); err != nil { t.Fatal(err) } _ = os.Chtimes(UnitManifestFile(unitDir), at, at) if hdd != "" { if err := os.WriteFile(filepath.Join(unitDir, "compose", "app.yaml"), []byte("env:\n HDD_PATH: "+hdd+"\n"), 0o600); err != nil { t.Fatal(err) } } } // `09` §3 decision 36 — „use my kept data" loads only a copy that (1) holds the app's data and (2) was // taken of THIS drive's install; the newest such copy on any local tier wins. // COMPANION RED-PROOF: drop the HDD_PATH comparison in KeptCopyAt → a unit taken of ANOTHER drive is // offered and the first assertion fails. func TestKept_DBCopyIsTheNewestUsableForThisDrive(t *testing.T) { m, sett, drive := r690Manager(t) _ = sett unit := RecoveryUnitPath(m.namespaceRoot(drive), "nextcloud") writeKeptUnit(t, unit, "/mnt/felhom-drives/other", true, time.Now().Add(-time.Hour)) if c, ok := m.KeptDBCopy("nextcloud", drive); ok { t.Fatalf("a unit taken of another drive was offered: %+v", c) } writeKeptUnit(t, unit, drive, false, time.Now().Add(-time.Hour)) if c, ok := m.KeptDBCopy("nextcloud", drive); ok { t.Fatalf("a unit holding no data was offered: %+v", c) } writeKeptUnit(t, unit, drive, true, time.Now().Add(-time.Hour)) c, ok := m.KeptDBCopy("nextcloud", drive) if !ok || c.UnitDir != unit || c.Tier != 1 { t.Fatalf("own unit not offered: %+v ok=%v", c, ok) } // An INSTALLED app's unit is its live backup, never a kept-data offer. if c, ok := m.KeptDBCopy("still-here", drive); ok { t.Fatalf("an installed app's unit was offered: %+v", c) } // The start-fresh hook names the unit only on the same drive. if got := m.RemovedUnitOnDrive("nextcloud", drive); got != unit { t.Fatalf("RemovedUnitOnDrive = %q, want %q", got, unit) } if got := m.RemovedUnitOnDrive("nextcloud", "/elsewhere"); got != "" { t.Fatalf("RemovedUnitOnDrive named a unit on another drive: %q", got) } }