rehearse refused only a verb's process. Since mesh-cli (ADR 0272 §4) the serving controller runs an ordinary mesh-cli line without a verb, naming its caller: such a line, from an agent's account, read as the terminal and could start a question the operator did not ask. rehearse now asks startedAtTheTerminal. And main's mesh-cli test helper asked is cliAsked, beside the asker's asked.
77 lines
3.2 KiB
Go
77 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"github.com/novox/mesh-controller/internal/link"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/asks"
|
|
)
|
|
|
|
// A rehearsal (the live acceptance of novox/hq ADR 0259): its approval is a warrant like any other — claimed once,
|
|
// its act checked against what the option bound, recorded as the operator's decision with who, how and the
|
|
// proofs — and it performs nothing. The reconciling of conditions leaves it open.
|
|
func TestARehearsalsApprovalIsRecordedAndPerformsNothing(t *testing.T) {
|
|
r := newAskerRig(t)
|
|
q, options := rehearsalAsk("crehearsal", r.now, askerRehearsalFor)
|
|
if err := q.Check(r.now); err != nil {
|
|
t.Fatalf("the rehearsal's ask is refused: %v", err)
|
|
}
|
|
r.store["crehearsal"] = asked{ID: "crehearsal", Condition: q.About, Ask: q, Actions: rehearsalActions(), Options: options,
|
|
State: askOpen, Opened: r.now, Rehearsal: true}
|
|
if err := r.a.reconcile(context.Background()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := r.store["crehearsal"]; got.State != askOpen {
|
|
t.Fatalf("the reconciling of conditions ended the rehearsal: %+v", got)
|
|
}
|
|
approve, _ := q.Option("approve")
|
|
w := asks.Warrant{Ask: "crehearsal", Asker: "mesh-controller", Outcome: asks.OutcomeChosen, Option: approve.ID,
|
|
Label: approve.Label, Level: approve.Level, Channel: "telegram", Proofs: []string{"P1"}, At: r.now,
|
|
AskDigest: q.Digest(), By: &asks.Person{Who: asks.Operator, Kind: "telegram", Identity: "42", Verified: "user id verified"}}
|
|
answerWith(t, r, w)
|
|
answerWith(t, r, w) // heard again
|
|
if len(r.called)+len(r.silenced) != 0 {
|
|
t.Errorf("a rehearsal performed something: %v %v", r.called, r.silenced)
|
|
}
|
|
if len(r.acts) != 1 {
|
|
t.Fatalf("hand-acts %+v", r.acts)
|
|
}
|
|
act := r.acts[0]
|
|
if act.Verb != handActWarrant || act.By != "the operator, as telegram identity 42" || act.Ask != "crehearsal" ||
|
|
strings.Join(act.Args, " ") != "rehearsal rehearsal=approve" || act.Outcome != "done" || strings.Join(act.Proofs, ",") != "P1" {
|
|
t.Errorf("the rehearsal's record: %+v", act)
|
|
}
|
|
if !personsDecision(act) {
|
|
t.Error("a rehearsal's answer counts as a repair")
|
|
}
|
|
}
|
|
|
|
// Only the terminal starts a rehearsal: a verb's process is refused before anything is asked.
|
|
func TestARehearsalIsTheTerminalsAlone(t *testing.T) {
|
|
t.Setenv(verbVar, "mesh-controller.command")
|
|
if err := rehearseCommand(context.Background(), nil); err == nil || !strings.Contains(err.Error(), "terminal") {
|
|
t.Fatalf("a verb started a rehearsal: %v", err)
|
|
}
|
|
// Nor a mesh-cli line from anybody but the control-node's operator (hq ADR 0272 §4): run without a verb,
|
|
// naming its caller, and without the terminal's mark — and nor anything the serving controller started.
|
|
for name, env := range map[string]map[string]string{
|
|
"an ordinary mesh-cli line": {verbVar: "", link.CallerVar: "laptop/agent"},
|
|
"a process the serving controller ran": {verbVar: "", servedVar: "1"},
|
|
} {
|
|
t.Run(name, func(t *testing.T) {
|
|
for k, v := range env {
|
|
t.Setenv(k, v)
|
|
}
|
|
if err := rehearseCommand(context.Background(), nil); err == nil || !strings.Contains(err.Error(), "terminal") {
|
|
t.Fatalf("%s started a rehearsal: %v", name, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// askerRehearsalFor is how long the test's rehearsal waits.
|
|
const askerRehearsalFor = 15 * time.Minute
|