package backup import ( "io" "log" "path/filepath" "testing" "gitea.dooplex.hu/admin/felhom-controller/internal/config" "gitea.dooplex.hu/admin/felhom-controller/internal/settings" ) // F6: a volume-only app (no HDD_PATH → data on sys_drive) must now flow through the tier-2 run — it // used to be skipped, leaving a single controller-level copy. COMPANION red-proof: restore the // `GetStackHDDPath == "" { continue }` skip in RunAllTier2 → "actualbudget" is absent → this fails. func TestRunAllTier2_IncludesVolumeOnlyApps(t *testing.T) { cfg := &config.Config{} cfg.Paths.SystemDataPath = filepath.Join(t.TempDir(), "sys") fake := &volDumpFakeProvider{ stacks: []StackSummary{{Name: "nextcloud"}, {Name: "actualbudget"}}, hdd: map[string]string{"nextcloud": filepath.Join(t.TempDir(), "usb")}, // actualbudget = volume-only } m := &Manager{cfg: cfg, logger: log.New(io.Discard, "", 0), systemDataPath: cfg.Paths.SystemDataPath, stackProvider: fake} var processed []string m.perAppTier2 = func(name string) error { processed = append(processed, name); return nil } m.RunAllTier2() var sawVolumeOnly bool for _, p := range processed { if p == "actualbudget" { sawVolumeOnly = true } } if !sawVolumeOnly { t.Errorf("volume-only app 'actualbudget' was NOT included in the tier-2 run (F6): processed=%v", processed) } } // F6: a single-drive box (no off-drive target) surfaces the honest single-copy notice; a box with an // off-drive target does not (never a faked 3-2-1 guarantee). func TestSingleCopyWarning_HonestOnSingleDrive(t *testing.T) { // Single-drive: only the system drive, no schedulable off-drive paths. m1, _ := newTestManager(t, "/srv/sys") if got := m1.singleCopyWarning(); got != singleCopyNotice { t.Errorf("single-drive box must surface the honest notice, got %q", got) } // Multi-drive: an enrolled off-drive path → no warning. m2, sett := newTestManager(t, "/srv/sys") if err := sett.AddStoragePath(settings.StoragePath{Path: "/mnt/usb", Label: "USB", Schedulable: true}); err != nil { t.Fatal(err) } if got := m2.singleCopyWarning(); got != "" { t.Errorf("a box with an off-drive target must NOT show the single-copy notice, got %q", got) } } // F6: a sys_drive (volume-only) app's restore point carries a clear drive label, never blank. func TestRestorePoint_SysDriveLabelNotBlank(t *testing.T) { cfg := &config.Config{} sysDrive := t.TempDir() cfg.Paths.SystemDataPath = sysDrive fake := &volDumpFakeProvider{ stacks: []StackSummary{{Name: "actualbudget"}}, volumes: map[string][]string{"actualbudget": {"actualbudget_data"}}, } m := &Manager{cfg: cfg, logger: log.New(io.Discard, "", 0), systemDataPath: sysDrive, stackProvider: fake} label := m.sysDriveLabelFor("actualbudget") if label != systemDriveLabel { t.Errorf("sys_drive app drive label = %q, want %q (never blank — F6)", label, systemDriveLabel) } }