A module that asks the operator acts with its own grants, and the hand-act log is where a person's decisions are read back. The new verb warranted records who chose, how and with which proofs from the router's record, never the caller's word, once per ask however many instances ask.
87 lines
3.1 KiB
Go
87 lines
3.1 KiB
Go
package link
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/nats-io/nats.go/jetstream"
|
|
|
|
"github.com/novox/mesh-controller/internal/broker"
|
|
)
|
|
|
|
// The hand-act log against a real server (novox/hq to-be 45 §7): an act is written with who, why and
|
|
// its cause, read back in order, and a cause recorded twice within a fortnight is found.
|
|
func TestNatsAnActByHandIsKeptWithWhyAndARepeatIsFound(t *testing.T) {
|
|
js := aBus(t)
|
|
api, err := jetstream.New(js.Conn())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_ = api.DeleteKeyValue(t.Context(), broker.HandActsBucket)
|
|
if err := js.EnsureControllerBuckets(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Setenv(CallerVar, "node-tools.g14, through the mesh-controller seat")
|
|
if _, err := RecordHandAct(t.Context(), js.Conn(), HandAct{Verb: "push", Args: []string{"anchor"}}); err == nil {
|
|
t.Fatal("an act without why was written")
|
|
}
|
|
first, err := RecordHandAct(t.Context(), js.Conn(), HandAct{Verb: "push", Args: []string{"anchor"},
|
|
Why: "it never reported the send", Cause: "sent-not-reported"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if first.By != "node-tools.g14, through the mesh-controller seat" || first.ID == "" {
|
|
t.Fatalf("written as %+v", first)
|
|
}
|
|
if _, err := RecordHandAct(t.Context(), js.Conn(), HandAct{Verb: "plans close", Args: []string{"plan-1"},
|
|
Why: "waiting on the same report"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := RecordHandAct(t.Context(), js.Conn(), HandAct{Verb: "push", Args: []string{"ace"},
|
|
Why: "again", Cause: "sent-not-reported", At: time.Now().UTC().Add(time.Second)}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
acts, err := HandActs(t.Context(), js.Conn(), time.Now().Add(-time.Hour))
|
|
if err != nil || len(acts) != 3 || acts[0].ID != first.ID || acts[1].Cause != "plans close" {
|
|
t.Fatalf("%v %+v", err, acts)
|
|
}
|
|
repeated := RepeatedCauses(acts, time.Now())
|
|
if len(repeated) != 1 || repeated["sent-not-reported"] != 2 {
|
|
t.Fatalf("repeated %v", repeated)
|
|
}
|
|
if old, _ := HandActs(t.Context(), js.Conn(), time.Now().Add(time.Hour)); len(old) != 0 {
|
|
t.Fatalf("acts before the moment asked were listed: %+v", old)
|
|
}
|
|
if !strings.HasPrefix(acts[2].ID, "act-") {
|
|
t.Fatalf("%q", acts[2].ID)
|
|
}
|
|
}
|
|
|
|
// An act on a warrant asked by each of a module's instances is recorded once (novox/hq ADR 0274).
|
|
func TestNatsAnActRecordedOnceIsWrittenOnce(t *testing.T) {
|
|
js := aBus(t)
|
|
api, err := jetstream.New(js.Conn())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_ = api.DeleteKeyValue(t.Context(), broker.HandActsBucket)
|
|
if err := js.EnsureControllerBuckets(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
act := HandAct{ID: "warrant-claude-code-instr-1", Verb: "warrant", Why: "the operator chose Approve", By: "the operator"}
|
|
if _, err := RecordHandActOnce(t.Context(), js.Conn(), HandAct{Verb: "warrant", Why: "x"}); err == nil {
|
|
t.Fatal("an act without its id was written")
|
|
}
|
|
for i, want := range []bool{true, false, false} {
|
|
written, err := RecordHandActOnce(t.Context(), js.Conn(), act)
|
|
if err != nil || written != want {
|
|
t.Fatalf("ask %d: written %v, %v", i, written, err)
|
|
}
|
|
}
|
|
acts, err := HandActs(t.Context(), js.Conn(), time.Now().Add(-time.Hour))
|
|
if err != nil || len(acts) != 1 || acts[0].ID != act.ID {
|
|
t.Fatalf("%v %+v", err, acts)
|
|
}
|
|
}
|