The licence manager follows the nodes' holdings by an event and asks for them with holdings.asked, instead of reading the agent module's state (ADR 0596 §2). The state holdings stays the module's own. Builds: design 39 bus-and-switch §23 Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
53 lines
1.6 KiB
Go
53 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// design 39 bus-and-switch §23: the holdings are said at start, on a change and when asked again, kept in the
|
|
// module's own state each time, the report whole and never a token.
|
|
func TestHoldingsAreSaidAtStartAndOnChange(t *testing.T) {
|
|
var kept, said []string
|
|
failing := false
|
|
s := &HoldingsSayer{
|
|
Put: func(h Holdings) error { raw, _ := json.Marshal(h); kept = append(kept, string(raw)); return nil },
|
|
Emit: func(h Holdings) error {
|
|
if failing {
|
|
return errors.New("no responders")
|
|
}
|
|
raw, _ := json.Marshal(h)
|
|
said = append(said, string(raw))
|
|
return nil
|
|
},
|
|
}
|
|
fp := "sha256:0123456789abcdef"
|
|
start := Holdings{Node: "laptop"}
|
|
changed := Holdings{Node: "laptop"}
|
|
changed.Refresh.Present, changed.Refresh.Fingerprint = true, &fp
|
|
for i, step := range []struct {
|
|
h Holdings
|
|
again, out bool
|
|
}{{start, false, true}, {start, false, false}, {changed, false, true}, {changed, true, true}} {
|
|
if got, err := s.Say(step.h, step.again); err != nil || got != step.out {
|
|
t.Fatalf("step %d: said %v (%v), want %v", i, got, err, step.out)
|
|
}
|
|
}
|
|
if len(said) != 3 || len(kept) != 3 {
|
|
t.Fatalf("said %d, kept %d, want 3 each", len(said), len(kept))
|
|
}
|
|
if !strings.Contains(said[1], fp) || !strings.Contains(said[1], `"node":"laptop"`) {
|
|
t.Fatalf("the report is not said whole: %s", said[1])
|
|
}
|
|
failing = true
|
|
if got, err := s.Say(start, false); err == nil || got {
|
|
t.Fatal("a failed event counts as said")
|
|
}
|
|
failing = false
|
|
if got, _ := s.Say(start, false); !got {
|
|
t.Fatal("what failed to be said is not said at the next call")
|
|
}
|
|
}
|