Files
mesh-controller/internal/link/order_test.go
T

82 lines
3.4 KiB
Go

package link
import (
"encoding/json"
"testing"
)
// The contract of order.go, case by case: what the controller refuses of a node-engine's facts (the node-engine's own order)
// and the bytes on the wire.
func TestAnAccountIsOlderByEpochThenSequenceThenReportSequence(t *testing.T) {
for _, c := range []struct {
name string
arriving Account
kept Account
older bool
}{
// Issue 267: a reconcile's account of declaration 11 arrives after the apply's of 12.
{"an account of an older declaration", Account{Order{57, 11}, 40}, Account{Order{57, 12}, 41}, true},
{"an older report of the same declaration", Account{Order{57, 12}, 40}, Account{Order{57, 12}, 41}, true},
{"a newer report of the same declaration (a reconcile after the apply)",
Account{Order{57, 12}, 42}, Account{Order{57, 12}, 41}, false},
{"the same report again (redelivered)", Account{Order{57, 12}, 41}, Account{Order{57, 12}, 41}, false},
{"an account of a newer declaration, whatever its report sequence",
Account{Order{57, 13}, 1}, Account{Order{57, 12}, 41}, false},
{"an account of an older epoch", Account{Order{41, 99}, 50}, Account{Order{57, 12}, 41}, true},
{"an account of a newer epoch", Account{Order{58, 1}, 2}, Account{Order{57, 12}, 41}, false},
{"no epoch either side: the sequences", Account{Order{0, 11}, 50}, Account{Order{0, 12}, 41}, true},
{"no report sequence: the declaration's alone", Account{Order{57, 12}, 0}, Account{Order{57, 12}, 41}, false},
{"an unordered declaration: the report sequences", Account{Order{}, 40}, Account{Order{}, 41}, true},
{"nothing kept yet", Account{Order{57, 3}, 1}, Account{}, false},
} {
t.Run(c.name, func(t *testing.T) {
if got := c.arriving.OlderThan(c.kept); got != c.older {
t.Fatalf("%+v against %+v: older %v, want %v", c.arriving, c.kept, got, c.older)
}
})
}
}
// The bytes, as mesh-host's report writes them: every key optional, absent when zero.
func TestTheOrderOnTheWire(t *testing.T) {
// A stale refusal, as the node-engine says it: the refused declaration's order at the top, the one
// it holds in older_than, and how many it has refused ever.
raw := []byte(`{"node":"anchor","refused":"older","declared":"d1","epoch":41,"sequence":11,` +
`"report_sequence":7,"older_than":{"epoch":57,"sequence":12},"refused_older":3}`)
var r Report
if err := json.Unmarshal(raw, &r); err != nil {
t.Fatal(err)
}
if r.Order != (Order{41, 11}) || r.ReportSequence != 7 || r.OlderThan == nil || *r.OlderThan != (Order{57, 12}) ||
r.RefusedOlder != 3 {
t.Fatalf("a node-engine's stale refusal reads as %+v", r)
}
if !r.Ordered() {
t.Fatalf("a node-engine that orders its reports reads as one that does not: %+v", r)
}
// A report from a node-engine older than the contract says none of it.
var older Report
if err := json.Unmarshal([]byte(`{"node":"anchor","applied":["a"],"declared":"d1"}`), &older); err != nil {
t.Fatal(err)
}
if older.Ordered() {
t.Fatalf("an older node-engine's report reads as ordered: %+v", older)
}
// And a report with no order puts no order key on the wire.
raw, err := json.Marshal(Report{Node: "anchor", Declared: "d1"})
if err != nil {
t.Fatal(err)
}
var keys map[string]any
if err := json.Unmarshal(raw, &keys); err != nil {
t.Fatal(err)
}
for _, key := range []string{"epoch", "sequence", "report_sequence", "older_than", "refused_older"} {
if _, there := keys[key]; there {
t.Fatalf("an unordered report carries %s: %s", key, raw)
}
}
}