package backup import ( "context" "strings" "testing" "gitea.dooplex.hu/admin/felhom-agent/internal/proxmox" ) // R-685 (v0.134.0) — a whole-box backup that cannot fit its LOCAL target is a named skip BEFORE anything // starts, with the numbers in the record's Error, never a vzdump that fills the disk and fails. const gib = int64(1) << 30 func spaceAPI(avail int64, lastArchive int64, typ string) *fakeBackupAPI { api := &fakeBackupAPI{vzdumpUPID: "UPID:vzdump:1", storages: []proxmox.Storage{{Storage: "local", Type: typ, Content: "backup", Avail: avail}}} if lastArchive > 0 { api.content = []proxmox.StorageContent{{VolID: "local:backup/vzdump-lxc-9201-2026_09_24-21_59_25.tar.zst", Content: "backup", VMID: 9201, Size: lastArchive, CTime: 1790280000}} } return api } // TestR685_BackupThatCannotFitIsSkipped — demo-hp's shape: an 8.2 GB archive, 4 GiB free. No vzdump is // started; the record says why, with the numbers, under a stable prefix. // // COMPANION RED-PROOF (REPORT.md): drop the spaceFits call from backup() — this test fails at "a vzdump // was started on a target that cannot hold it". func TestR685_BackupThatCannotFitIsSkipped(t *testing.T) { api := spaceAPI(4*gib, 8182759056, "dir") r := NewBackupRunner(api, "local", proxmox.ModeSnapshot, "", "keep-last=1", quiet()) rec, err := r.Backup(context.Background(), 9201) if len(api.vzdumps) != 0 { t.Fatalf("a vzdump was started on a target that cannot hold it: %+v", api.vzdumps) } if err == nil || rec.Success || !strings.HasPrefix(rec.Error, BackupSkipNoSpacePrefix) { t.Fatalf("want a named skip, got err=%v rec=%+v", err, rec) } for _, want := range []string{"4.0 GiB free", "7.6 GiB", "10.5 GiB"} { if !strings.Contains(rec.Error, want) { t.Errorf("the reason must carry the numbers (%q missing): %s", want, rec.Error) } } } // TestR685_BackupThatFitsRuns — the same archive with 16 GiB free (demo-hp after tonight's prune) runs. func TestR685_BackupThatFitsRuns(t *testing.T) { api := spaceAPI(16*gib, 8182759056, "dir") r := NewBackupRunner(api, "local", proxmox.ModeSnapshot, "", "keep-last=1", quiet()) _, _ = r.Backup(context.Background(), 9201) if len(api.vzdumps) != 1 { t.Fatalf("a backup that fits must run, vzdumps=%d", len(api.vzdumps)) } } // TestR685_FailsOpen — never refuse on what is not KNOWN: a PBS target, a first backup (no archive to // size from), an unknown free figure, or a storage list that cannot be read. func TestR685_FailsOpen(t *testing.T) { cases := map[string]*fakeBackupAPI{ "pbs target": spaceAPI(1*gib, 8*gib, "pbs"), "first backup": spaceAPI(1*gib, 0, "dir"), "avail unknown": spaceAPI(0, 8*gib, "dir"), "storage list error": func() *fakeBackupAPI { a := spaceAPI(1*gib, 8*gib, "dir") a.storageErr = context.DeadlineExceeded return a }(), } for name, api := range cases { target := "local" if name == "pbs target" { api.storages[0].Storage = "felhom-pbs" target = "felhom-pbs" } r := NewBackupRunner(api, target, proxmox.ModeSnapshot, "", "", quiet()) _, _ = r.Backup(context.Background(), 9201) if len(api.vzdumps) != 1 { t.Errorf("%s: the preflight must fail OPEN, but no vzdump ran", name) } } }