R-1252 (P2): a rejected or absent backup block never deletes second-drive copies — reconcile only on a valid classification; a rejected block is said on the app's status and once a day to the operator (backup_run_failures); kept copies stay kept (H2); Remove drops the kept records it deleted (H9). Commit only.
gates / gates (push) Successful in 1m18s
gates / gates (push) Successful in 1m18s
This commit is contained in:
@@ -215,3 +215,26 @@ func TestCatalogBlocks_Fidelity(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// R-1252: the second-drive copy must tell a REJECTED block from an absent one (a rejected one keeps every copy and
|
||||
// alarms; an absent one is quiet). Through the REAL LoadMetadata path. RED-PROOF: drop the BackupRejected assignment
|
||||
// in LoadMetadata → the rejected fixture reads "" and this fails.
|
||||
func TestR1252_BackupBlockRejectedNamesTheReason(t *testing.T) {
|
||||
compose := `services:
|
||||
app:
|
||||
volumes:
|
||||
- ${USERDATA_PATH}/media/audiobooks:/audiobooks
|
||||
`
|
||||
bad := newClassifyManager(t, "display_name: App\nbackup:\n userdata:\n - path: media/nope\n class: mandatory\n", compose)
|
||||
if why := bad.BackupBlockRejected("app"); why == "" {
|
||||
t.Fatal("a block whose path matches no compose bind must be reported as rejected, with its reason")
|
||||
}
|
||||
good := newClassifyManager(t, "display_name: App\nbackup:\n userdata:\n - path: media/audiobooks\n class: mandatory\n", compose)
|
||||
if why := good.BackupBlockRejected("app"); why != "" {
|
||||
t.Fatalf("a valid block is not rejected, got %q", why)
|
||||
}
|
||||
none := newClassifyManager(t, "display_name: App\n", compose)
|
||||
if why := none.BackupBlockRejected("app"); why != "" {
|
||||
t.Fatalf("an absent block is not rejected, got %q", why)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user