69 lines
4.3 KiB
Go
69 lines
4.3 KiB
Go
package judge
|
|
|
|
import (
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// ADR 0567 §3, §4 (rows moved from the assigner's check of a pull request's placement, ADR 0559 §5): what a proposal
|
|
// changes by node, and the verdict of the answers: differences shown and failing nothing, a refusal and a silent node
|
|
// failing, a later answer judging again, the seed failing on any difference.
|
|
func TestJudge(t *testing.T) {
|
|
current := map[string]delivery.Placement{"anchor": {Node: "anchor", Modules: []delivery.PlacedModule{{Module: "mail"}}}, "server": {Node: "server"}}
|
|
laid := map[string]*delivery.Placement{
|
|
"anchor": {Node: "anchor", Modules: []delivery.PlacedModule{{Module: "mail", Ports: map[string]int{"25": 2525}}, {Module: "web"}}},
|
|
"laptop": {Node: "laptop", Modules: []delivery.PlacedModule{{Module: "web"}}}}
|
|
got, must, _ := Intended(nil, nil, current, laid, []string{"anchor", "laptop", "server"}, nil)
|
|
if !got["anchor"]["mail"] || !got["anchor"]["web"] || len(got["laptop"]) != 0 || !slices.Equal(must, []string{"anchor", "laptop"}) {
|
|
t.Errorf("intended = %v, must %v: want anchor's mail and web, nothing on the laptop that has no key, server untouched", got, must)
|
|
}
|
|
|
|
at := time.Date(2026, 10, 27, 2, 0, 0, 0, time.UTC)
|
|
p := delivery.PlacementProposal{ID: "p-one", By: "op", Why: "move web", Written: at, Base: map[string]uint64{"anchor": 3, "laptop": 0},
|
|
Must: []string{"anchor", "laptop"}}
|
|
revisions := map[string]uint64{"anchor": 7, "laptop": 8}
|
|
intended := map[string]map[string]bool{"anchor": {"web": true}}
|
|
same := func(rev uint64) *delivery.CandidateAnswer {
|
|
return &delivery.CandidateAnswer{Proposal: "p-one", Revision: rev, Verdict: delivery.CandidateSame, Same: []string{"mail"}}
|
|
}
|
|
differs := func(rev uint64, module string) *delivery.CandidateAnswer {
|
|
return &delivery.CandidateAnswer{Proposal: "p-one", Revision: rev, Verdict: delivery.CandidateDiffers,
|
|
Differs: []delivery.ModuleDiffers{{Module: module, Why: "the port differs"}}}
|
|
}
|
|
for _, row := range []struct {
|
|
name string
|
|
seed bool
|
|
answers map[string]*delivery.CandidateAnswer
|
|
pulsing map[string]bool
|
|
state string
|
|
words string
|
|
marked string
|
|
}{
|
|
{"all the same", false, map[string]*delivery.CandidateAnswer{"anchor": same(7), "laptop": same(8)}, nil, delivery.VerdictPass, "", ""},
|
|
{"a module added where intended", false, map[string]*delivery.CandidateAnswer{"anchor": {Proposal: "p-one", Revision: 7, Verdict: delivery.CandidateDiffers,
|
|
Added: []delivery.ModuleAdded{{Module: "web", Unissued: []string{"its own secret"}}}}, "laptop": same(8)}, nil, delivery.VerdictPass, "", ""},
|
|
{"a difference not computed passes, marked", false, map[string]*delivery.CandidateAnswer{"anchor": differs(7, "mail"), "laptop": same(8)}, nil, delivery.VerdictPass, "", "mail"},
|
|
{"the seed with a difference", true, map[string]*delivery.CandidateAnswer{"anchor": same(7), "laptop": differs(8, "web")}, nil, delivery.VerdictFail, "laptop composes web differently", ""},
|
|
{"a refusal", false, map[string]*delivery.CandidateAnswer{"anchor": same(7), "laptop": {Proposal: "p-one", Revision: 8, Verdict: delivery.CandidateRefused,
|
|
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", ""},
|
|
{"its later answer", false, map[string]*delivery.CandidateAnswer{"anchor": same(7), "laptop": same(8)}, nil, delivery.VerdictPass, "", ""},
|
|
} {
|
|
q := p
|
|
q.Seed = row.seed
|
|
v := JudgeAnswers(q, intended, row.answers, revisions, map[string]bool{"anchor": true}, row.pulsing, at)
|
|
all := strings.Join(append(append([]string{}, v.Fails...), v.Notes...), "; ")
|
|
if v.State != row.state || !strings.Contains(all, row.words) {
|
|
t.Errorf("%s: %s, %q", row.name, v.State, all)
|
|
}
|
|
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))
|
|
}
|
|
}
|
|
}
|