62 lines
2.3 KiB
Go
62 lines
2.3 KiB
Go
package backup
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
// R-1181 + D25 for app folders — the data-loss hunt's C3 case (felhom.eu audits/dataloss-hunt-2026-10-20/
|
|
// C3-D2-missing-leg/), asserting: a MISSING declared folder keeps its second-drive copy and is listed as kept; an
|
|
// EMPTIED folder is not mirrored over its full copy (the production `rsync -a --delete` mirror is used when present).
|
|
func TestR1181_MissingAndEmptiedAppFoldersKeepTheirCopies(t *testing.T) {
|
|
m, src, target, prov := newTier2V2(t, "app")
|
|
if _, err := exec.LookPath("rsync"); err == nil {
|
|
m.tier2Mirror = rsyncMirror
|
|
}
|
|
prov.has["app"] = true
|
|
prov.binds["app"] = []ClassifiedBind{mHDD("appdata/app/photos"), mHDD("appdata/app/docs")}
|
|
mustWrite(t, filepath.Join(src, "appdata", "app", "photos", "family.jpg"), "PHOTO")
|
|
mustWrite(t, filepath.Join(src, "appdata", "app", "docs", "contract.pdf"), "PDF")
|
|
if err := m.RunTier2("app"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
destBase := filepath.Join(target, "backups", "secondary", "app")
|
|
photo := filepath.Join(destBase, "hdd", "appdata", "app", "photos", "family.jpg")
|
|
doc := filepath.Join(destBase, "hdd", "appdata", "app", "docs", "contract.pdf")
|
|
if !exists(photo) || !exists(doc) {
|
|
t.Fatal("precondition: run 1 did not copy both folders")
|
|
}
|
|
if err := os.RemoveAll(filepath.Join(src, "appdata", "app", "photos")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.Remove(filepath.Join(src, "appdata", "app", "docs", "contract.pdf")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := m.RunTier2("app"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !exists(photo) {
|
|
t.Fatal("the MISSING folder's second-drive copy was deleted (R-1181)")
|
|
}
|
|
if !exists(doc) {
|
|
t.Fatal("the EMPTIED folder was mirrored over its full copy (R-1181)")
|
|
}
|
|
kept := m.KeptCopies()
|
|
if len(kept) != 1 || kept[0].Kind != "app" || kept[0].Reason != "folder_missing" {
|
|
t.Fatalf("kept copies = %+v, want the photos folder", kept)
|
|
}
|
|
if cd := m.settings.GetCrossDriveConfig("app"); cd == nil || cd.LastWarning == "" {
|
|
t.Fatalf("the run did not warn: %+v", cd)
|
|
}
|
|
// The folder comes back: mirrored again, the record goes.
|
|
mustWrite(t, filepath.Join(src, "appdata", "app", "photos", "family.jpg"), "PHOTO")
|
|
if err := m.RunTier2("app"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(m.KeptCopies()) != 0 {
|
|
t.Fatalf("the record outlived the folder's return: %+v", m.KeptCopies())
|
|
}
|
|
}
|