Files
mesh-sdk/go/handacts/handacts_test.go
T
jschoubben 8696aa9ba4 The hand-act recorder records through the seat alone, and the watched reader's reads are proved
The controller's hand-act and warranted are gone (issue 1953 L5b) and the bus refuses them, so the recorder no longer
falls back to them: an act the seat does not take is an error saying nothing was recorded. And ADR 0580 clause 1's
reader is shown reading a build by key each time and a manifest once per digest.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-01 09:53:17 +01:00

73 lines
3.0 KiB
Go

package handacts
import (
"encoding/json"
"errors"
"reflect"
"strings"
"testing"
)
// ADR 0565 clauses 10 and 11 (issue 1953 L5-S2, S4, L5b): an act reads the controller's entries unchanged, and a
// recorder records through the seat alone, the controller's verbs being gone, and says loudly when nothing was recorded.
func TestAnActIsRecordedInTheLogThatAnswers(t *testing.T) {
// The shape of mesh-controller internal/link HandAct, as its bucket keeps an entry (handacts.go at 0fbb5ef3).
raw := `{"id":"act-1","at":"2026-10-28T09:00:00Z","by":"person.jochen","verb":"hand-act record","why":"a stuck consumer",` +
`"cause":"consumer-lost","condition":"bus.EVENTS.x.consumer-lost","via":"telegram","ask":"a-1","proofs":["P1"],` +
`"requested-by":"bus.EVENTS.x.consumer-lost","outcome":"done"}`
var a Act
if err := json.Unmarshal([]byte(raw), &a); err != nil {
t.Fatal(err)
}
again, _ := json.Marshal(a)
var want, got map[string]any
_ = json.Unmarshal([]byte(raw), &want)
_ = json.Unmarshal(again, &got)
if !reflect.DeepEqual(want, got) || !a.Repair() || (Act{Cause: CauseDrill}).Repair() || (Act{Verb: VerbDrill}).Repair() {
t.Errorf("the controller's entry reads back as %s", again)
}
noResponders := errors.New("nats: no responders available for request")
for _, c := range []struct {
name string
seat error
ctrl error
away bool
log string
refused string
asked string
warrants bool
}{
{name: "the seat answers", log: LogSeat, asked: "seat:mesh-hand-acts.hand-act"},
{name: "no holder: nothing recorded, the controller never asked", seat: noResponders, refused: "nothing was recorded",
asked: "seat:mesh-hand-acts.hand-act"},
{name: "the seat refuses", seat: errors.New("why is required"), refused: "refused, nothing was recorded",
asked: "seat:mesh-hand-acts.hand-act"},
{name: "a warrant without a holder", seat: noResponders, warrants: true, refused: "nothing was recorded",
asked: "seat:mesh-hand-acts.warranted"},
{name: "a warrant recorded", warrants: true, log: LogSeat, asked: "seat:mesh-hand-acts.warranted"},
} {
var asked []string
r := Recorder{LeaseAway: func() bool { return c.away }, Ask: func(key string, body any) (json.RawMessage, error) {
asked = append(asked, key)
if strings.HasPrefix(key, "seat:mesh-hand-acts.") {
return json.RawMessage(`{}`), c.seat
}
return json.RawMessage(`{}`), c.ctrl
}}
var taken Taken
var err error
if c.warrants {
taken, err = r.RecordWarrant("mesh-config", "ask-1")
} else {
taken, err = r.Record(Request{What: "silenced", Why: "known", Cause: "silent", Verb: "conditions silence"})
}
if (c.refused != "") != (err != nil) || (err != nil && !strings.Contains(err.Error(), c.refused)) || taken.Log != c.log ||
strings.Join(asked, ",") != c.asked {
t.Errorf("%s: took %q, %v, asked %v", c.name, taken.Log, err, asked)
}
}
if _, err := (Recorder{}).Record(Request{What: "x"}); err == nil {
t.Error("an act with no why was recorded")
}
}