R-403: the restore OUTCOME names the package's date, not the run's
gates / gates (push) Successful in 11s
gates / gates (push) Successful in 11s
Live on demo-hp the confirm said 11:43 (the preserved package) and the outcome said 14:23 (the copy's newest run) for the same restore. A customer reading both cannot tell which one they had, and one of the two is the flattering sentence. Part 2.3's rule is 'not a plain green success ANYWHERE', and the outcome is an anywhere. tier2UnitSourceMsg now asks UnitRestoreDate, the same resolver the confirm uses, so the two cannot disagree. TestR403_OutcomeNamesThePackageDateNotTheRunDate pins it, with a negative control for the ordinary case.
This commit is contained in:
@@ -1724,7 +1724,12 @@ func tier2UnitConfirmWithStaleness(copyDate string, proven bool, stale bool) str
|
|||||||
// date it puts in the confirm — so the sentence the customer approves and the sentence they are left
|
// date it puts in the confirm — so the sentence the customer approves and the sentence they are left
|
||||||
// with cannot name different copies.
|
// with cannot name different copies.
|
||||||
func tier2UnitSourceMsg(cov backup.Tier2Coverage) string {
|
func tier2UnitSourceMsg(cov backup.Tier2Coverage) string {
|
||||||
date, proven := cov.Tier2CopyDate()
|
// R-403: the OUTCOME names the same date the CONFIRM did — the PACKAGE's, not the copy's newest
|
||||||
|
// run. Live on demo-hp 2026-08-31 these disagreed by two and a half hours (confirm 11:43, outcome
|
||||||
|
// 14:23) after a preserved leg, and a customer reading both would not know which restore they had
|
||||||
|
// just had. §2.3's rule is "not a plain green success ANYWHERE", and the outcome is an anywhere.
|
||||||
|
date, _ := cov.UnitRestoreDate()
|
||||||
|
_, proven := cov.Tier2CopyDate()
|
||||||
if date == "" {
|
if date == "" {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package web
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"gitea.dooplex.hu/admin/felhom-controller/internal/backup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// R-403 Group D — the surfaces must not call a PRESERVED package a FRESH one.
|
// R-403 Group D — the surfaces must not call a PRESERVED package a FRESH one.
|
||||||
@@ -99,3 +101,37 @@ func TestR403_TheOrdinaryConfirmIsUnchanged(t *testing.T) {
|
|||||||
t.Error("the two-argument confirm is no longer the not-stale case")
|
t.Error("the two-argument confirm is no longer the not-stale case")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// D3 — the OUTCOME names the same date the CONFIRM did.
|
||||||
|
//
|
||||||
|
// Live on demo-hp 2026-08-31 they disagreed after a preserved leg: the confirm said 11:43 (the
|
||||||
|
// package) and the outcome said 14:23 (the copy's newest run). A customer reading both cannot tell
|
||||||
|
// which restore they just had, and one of the two sentences is flattering.
|
||||||
|
func TestR403_OutcomeNamesThePackageDateNotTheRunDate(t *testing.T) {
|
||||||
|
cov := backup.Tier2Coverage{
|
||||||
|
CopyLastSuccess: "2026-08-31T12:23:51Z", // the run
|
||||||
|
UnitPackageDate: "2026-08-31T09:43:41Z", // the preserved package
|
||||||
|
UnitLegPreserved: true,
|
||||||
|
}
|
||||||
|
msg := tier2UnitSourceMsg(cov)
|
||||||
|
pkg := fmtRFC3339Local("2026-08-31T09:43:41Z")
|
||||||
|
run := fmtRFC3339Local("2026-08-31T12:23:51Z")
|
||||||
|
if !strings.Contains(msg, pkg) {
|
||||||
|
t.Errorf("the outcome does not name the package's date %q: %q", pkg, msg)
|
||||||
|
}
|
||||||
|
if strings.Contains(msg, run) {
|
||||||
|
t.Errorf("the outcome names the RUN's date %q — the flattering one: %q", run, msg)
|
||||||
|
}
|
||||||
|
// The confirm and the outcome must agree.
|
||||||
|
date, stale := cov.UnitRestoreDate()
|
||||||
|
confirm := tier2UnitConfirmWithStaleness(date, true, stale)
|
||||||
|
if !strings.Contains(confirm, pkg) {
|
||||||
|
t.Errorf("the confirm does not name %q either: %q", pkg, confirm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NEGATIVE CONTROL: with no preserved leg, the package date IS the fresh one and both agree on it.
|
||||||
|
fresh := backup.Tier2Coverage{CopyLastSuccess: "2026-08-31T12:23:51Z", UnitPackageDate: "2026-08-31T12:23:00Z"}
|
||||||
|
if !strings.Contains(tier2UnitSourceMsg(fresh), fmtRFC3339Local("2026-08-31T12:23:00Z")) {
|
||||||
|
t.Error("the ordinary outcome stopped naming its own package date")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user