Files
mesh-sdk/go/handacts/handacts_test.go
T

75 lines
3.2 KiB
Go

package handacts
import (
"encoding/json"
"errors"
"reflect"
"strings"
"testing"
)
// ADR 0565 clauses 10 and 11 (issue 1953 L5-S2, S4): an act reads the controller's entries unchanged, and a recorder
// records through the seat, through the controller's verb only while the seat has no holder and the lease is the
// controller's, saying which log took it, and refuses to record nowhere.
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 yet", seat: noResponders, log: LogController, asked: "seat:mesh-hand-acts.hand-act,seat:mesh-controller.hand-act"},
{name: "no holder, the lease handed away", seat: noResponders, away: true, refused: "handed its lease away",
asked: "seat:mesh-hand-acts.hand-act"},
{name: "the seat refuses", seat: errors.New("why is required"), refused: "refused", asked: "seat:mesh-hand-acts.hand-act"},
{name: "neither answers", seat: noResponders, ctrl: noResponders, refused: "refused too",
asked: "seat:mesh-hand-acts.hand-act,seat:mesh-controller.hand-act"},
{name: "a warrant without a holder", seat: noResponders, warrants: true, log: LogController,
asked: "seat:mesh-hand-acts.warranted,seat:mesh-controller.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")
}
}