58 lines
2.6 KiB
Go
58 lines
2.6 KiB
Go
package link_test
|
||
|
||
import (
|
||
"testing"
|
||
"time"
|
||
|
||
"github.com/novox/mesh-controller/internal/link"
|
||
)
|
||
|
||
// A report kept by its order (novox/hq to-be 45 §6, ADR 0227 rule 2): the contract test of the report,
|
||
// the message kind the controller consumes from every machine. Deliver n, then n−1: refused and counted.
|
||
// Of the same declaration, report r then r−1: refused. The digest the mesh last sent decides nothing
|
||
// for an ordered report; an unordered one, from an older node-engine, is judged by it as before.
|
||
|
||
func ordered(declared string, epoch, sequence, report int64, applied ...string) link.Report {
|
||
return link.Report{Node: "home-server", Declared: declared, Applied: applied,
|
||
Order: link.Order{Epoch: epoch, Sequence: sequence}, ReportSequence: report}
|
||
}
|
||
|
||
// Issue 267, ordered: a reconcile's account of declaration 11 reaches the mesh after the apply's of 12.
|
||
|
||
// An ordered account is judged by its order, not by the digest the mesh last sent: the account of 12
|
||
// is kept although the mesh has sent 13 since — it is still the newest account of the machine.
|
||
|
||
// A node-engine rolled back to one that orders nothing: its account is taken by the digest rule, the
|
||
// order kept is cleared, and it is no longer sent an epoch.
|
||
|
||
// A stale refusal names its writer by the epoch the refused declaration claimed, and a refusal whose
|
||
// own report was lost is still counted from the machine's own tally.
|
||
func TestAStaleRefusalIsCountedByItsWriter(t *testing.T) {
|
||
count := link.NewRefusalCount()
|
||
now := time.Now()
|
||
refusal := link.Report{Node: "anchor", Refused: "older", Order: link.Order{Epoch: 41, Sequence: 11},
|
||
OlderThan: &link.Order{Epoch: 57, Sequence: 12}, ReportSequence: 9, RefusedOlder: 3}
|
||
if !refusal.StaleRefusalOf() {
|
||
t.Fatal("a refusal naming the order it holds is not stale")
|
||
}
|
||
count.Lifetime("anchor", 2, now) // the machine's tally, as the controller first heard it
|
||
count.Refused(link.Refusal{Writer: link.WriterEpoch(refusal.Epoch), Epoch: refusal.Epoch, Receiver: "anchor", At: now})
|
||
count.Lifetime("anchor", refusal.RefusedOlder, now)
|
||
count.Lifetime("anchor", 5, now) // two more refused, their reports lost
|
||
got := count.Within(now.Add(-time.Minute))
|
||
if len(got) != 2 || got[0].Count != 2 || got[0].Epoch != 0 || got[1].Writer != "the controller of epoch 41" ||
|
||
got[1].Count != 1 || got[1].Receivers[0] != "anchor" {
|
||
t.Fatalf("the refusals by writer are %+v", got)
|
||
}
|
||
}
|
||
|
||
// countFor is how many refusals of a writer this process has heard in the last minute.
|
||
func countFor(writer string) int {
|
||
for _, w := range link.StaleRefusals.Within(time.Now().Add(-time.Minute)) {
|
||
if w.Writer == writer {
|
||
return w.Count
|
||
}
|
||
}
|
||
return 0
|
||
}
|