diff --git a/go/compose/judge/judge.go b/go/compose/judge/judge.go index a6780db..1b3cab5 100644 --- a/go/compose/judge/judge.go +++ b/go/compose/judge/judge.go @@ -209,7 +209,7 @@ func JudgeAnswers(p delivery.PlacementProposal, intended map[string]map[string]b } // Brief is the verdict as the ask's brief shows it, by node (ยง5): what the proposal changes and what each node answered -// beside it, marked, with the proposal's why. +// beside it, marked, and what stays held as the node holds it today, with the proposal's why. func Brief(p delivery.PlacementProposal, v delivery.PlacementVerdict) string { var b strings.Builder fmt.Fprintf(&b, "%s (proposed by %s)", p.Why, p.By) @@ -223,6 +223,11 @@ func Brief(p delivery.PlacementProposal, v delivery.PlacementVerdict) string { for _, n := range p.Nodes() { nodes[n] = true } + for n, a := range v.Answers { + if len(a.Held) > 0 { + nodes[n] = true + } + } names := make([]string, 0, len(nodes)) for n := range nodes { names = append(names, n) @@ -238,6 +243,13 @@ func Brief(p delivery.PlacementProposal, v delivery.PlacementVerdict) string { if m := v.Unintended[n]; len(m) > 0 { fmt.Fprintf(&b, "; also differs, not computed: %s", strings.Join(m, ", ")) } + if held := v.Answers[n].Held; len(held) > 0 { + var names []string + for _, h := range held { + names = append(names, h.Module) + } + fmt.Fprintf(&b, "; stays held as today: %s", strings.Join(names, ", ")) + } } return b.String() } diff --git a/go/compose/judge/judge_test.go b/go/compose/judge/judge_test.go index caf5111..077d644 100644 --- a/go/compose/judge/judge_test.go +++ b/go/compose/judge/judge_test.go @@ -52,6 +52,8 @@ func TestJudge(t *testing.T) { Refusals: []delivery.ModuleRefused{{Module: "web", Why: "no own secret"}}}}, nil, delivery.VerdictFail, "laptop refuses", ""}, {"a node not answering, within its bound", false, map[string]*delivery.CandidateAnswer{"anchor": same(7)}, map[string]bool{"laptop": true}, delivery.VerdictWaits, "laptop (offline)", ""}, {"an answer of an earlier revision, past its bound", false, map[string]*delivery.CandidateAnswer{"anchor": same(6), "laptop": same(8)}, nil, delivery.VerdictFail, "anchor did not answer", ""}, + {"a module held as today passes, shown in the brief", false, map[string]*delivery.CandidateAnswer{"anchor": same(7), "laptop": {Proposal: "p-one", Revision: 8, + Verdict: delivery.CandidateSame, Held: []delivery.ModuleRefused{{Module: "spiegel", Why: "a required value is unset"}}}}, nil, delivery.VerdictPass, "", ""}, {"its later answer", false, map[string]*delivery.CandidateAnswer{"anchor": same(7), "laptop": same(8)}, nil, delivery.VerdictPass, "", ""}, } { q := p @@ -61,6 +63,9 @@ func TestJudge(t *testing.T) { if v.State != row.state || !strings.Contains(all, row.words) { t.Errorf("%s: %s, %q", row.name, v.State, all) } + if strings.HasPrefix(row.name, "a module held as today") && !strings.Contains(Brief(q, v), "stays held as today: spiegel") { + t.Errorf("%s: the brief does not show it: %s", row.name, Brief(q, v)) + } if row.marked != "" && (!slices.Contains(v.Unintended["anchor"], row.marked) || !strings.Contains(Brief(q, v), "not computed: "+row.marked)) { t.Errorf("%s: the difference is not marked: %+v, %s", row.name, v.Unintended, Brief(q, v)) }