package backup import ( "context" "encoding/json" "strings" "testing" "time" "gitea.dooplex.hu/admin/felhom-agent/internal/hub" "gitea.dooplex.hu/admin/felhom-agent/internal/proxmox" ) // R-366 slice 2 (`09` §3 decision 168) — the restore-test's skip of an archive written with another key stops being // silent: the pick records, per tier, how many it skipped and their time range, and the host report carries it. // // COMPANION RED-PROOF (observed): remove the `r.foreign.set(...)` call from PickSettledRestoreCandidateOn → this fails // with "after one evaluation the ledger must report felhom-pbs: 2 archives …; got []". Restored. func TestR366_PickRecordsArchivesWrittenWithAnotherKey(t *testing.T) { api := &fakeBackupAPI{ storages: []proxmox.Storage{{Storage: "felhom-pbs", Type: "pbs", EncryptionKey: thisBoxKey}}, content: []proxmox.StorageContent{ {VolID: "felhom-pbs:backup/ct/9201/2026-09-16T17:27:32Z", Content: "backup", VMID: 9201, Size: 4774114206, CTime: 1789579652, Encrypted: earlierBox2}, {VolID: "felhom-pbs:backup/ct/9201/2026-09-16T21:59:54Z", Content: "backup", VMID: 9201, Size: 20811501236, CTime: 1789595994, Encrypted: earlierBox1}, {VolID: "felhom-pbs:backup/ct/9201/2026-09-29T19:37:07Z", Content: "backup", VMID: 9201, Size: 3490689830, CTime: 1790710627, Encrypted: thisBoxKey}, }, } r := NewBackupRunner(api, "local", proxmox.ModeSnapshot, "", "keep-last=1", quiet()) l := NewForeignKeyLedger() r.SetForeignKeyLedger(l) if got := l.ForeignKeyArchives(context.Background()); got != nil { t.Fatalf("before any evaluation the ledger must be nil (the hub keeps its state); got %v", got) } if _, _, err := r.PickSettledRestoreCandidateOn(context.Background(), "felhom-pbs", time.Time{}); err != nil { t.Fatal(err) } st := l.ForeignKeyArchives(context.Background()) want := hub.ForeignKeyArchives{Target: "felhom-pbs", Count: 2, Oldest: "2026-09-16T17:27:32Z", Newest: "2026-09-16T21:59:54Z"} var got []hub.ForeignKeyArchives if st != nil { got = st.Tiers } if len(got) != 1 || got[0] != want { t.Fatalf("after one evaluation the ledger must report felhom-pbs: 2 archives 2026-09-16T17:27:32Z…21:59:54Z; got %v", got) } } // Evaluated and none found → the stanza with `tiers: []`; not evaluated → no stanza at all. Never a null on the wire. func TestR366_EvaluatedWithNoneIsAnEmptyList(t *testing.T) { api := &fakeBackupAPI{ storages: []proxmox.Storage{{Storage: "felhom-pbs", Type: "pbs", EncryptionKey: thisBoxKey}}, content: []proxmox.StorageContent{{VolID: "felhom-pbs:backup/ct/9201/2026-09-29T19:37:07Z", Content: "backup", VMID: 9201, Size: 3490689830, CTime: 1790710627, Encrypted: thisBoxKey}}, } r := NewBackupRunner(api, "local", proxmox.ModeSnapshot, "", "keep-last=1", quiet()) l := NewForeignKeyLedger() r.SetForeignKeyLedger(l) b, _ := json.Marshal(hub.HostReport{ForeignKeyArchives: l.ForeignKeyArchives(context.Background())}) if strings.Contains(string(b), "foreign_key_archives") { t.Fatalf("not evaluated must omit the stanza; got %s", b) } if _, _, err := r.PickSettledRestoreCandidateOn(context.Background(), "felhom-pbs", time.Time{}); err != nil { t.Fatal(err) } b, _ = json.Marshal(hub.HostReport{ForeignKeyArchives: l.ForeignKeyArchives(context.Background())}) if !strings.Contains(string(b), `"foreign_key_archives":{"tiers":[]}`) { t.Fatalf("evaluated with none must report tiers: []; got %s", b) } }