Files
mesh-host/internal/meshcli/ask_test.go
T
jochen 564948c2f2
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
mesh-cli: follow a line to its answer, bound each account, refuse other namespaces (review of hq ADR 0272)
- A request that timed out was said as "the controller was not reached,
  nothing ran", though the line may have run. The engine now follows a line
  the controller answers as running, by its call, until it ends; when no
  answer comes in time it says the line may have run and names the call.
  "Nothing ran" is said only of a request no controller took.
- One account could hold the socket: accepting waited for a free slot, and
  a connection could stall before its deadline was set. The deadline is set
  at accept, before any lookup; each user id has two lines at once and the
  machine eight, and one over is answered busy at once.
- A container running with the operator's user id shares the number, not
  the machine: a peer whose mount or user namespace is not the engine's is
  refused, and nothing is asked.

SDK pinned at the go/cli branch's newest commit until go/v0.1.9 is tagged.
2026-10-09 12:48:20 +02:00

99 lines
3.6 KiB
Go

package meshcli
import (
"context"
"encoding/json"
"errors"
"fmt"
"strings"
"sync"
"testing"
"time"
)
// controllerSays is a controller answering each request in turn from a script, and recording what it was asked.
type controllerSays struct {
mu sync.Mutex
script []func(Asked) ([]byte, error)
asked []Asked
}
func (c *controllerSays) ask(_ context.Context, body []byte) ([]byte, error) {
c.mu.Lock()
defer c.mu.Unlock()
var a Asked
_ = json.Unmarshal(body, &a)
c.asked = append(c.asked, a)
if len(c.script) == 0 {
return nil, context.DeadlineExceeded
}
next := c.script[0]
if len(c.script) > 1 {
c.script = c.script[1:]
}
return next(a)
}
func result(v any) func(Asked) ([]byte, error) {
return func(Asked) ([]byte, error) { return json.Marshal(map[string]any{"result": v}) }
}
func fastFollow(t *testing.T) {
was := followEvery
followEvery = time.Millisecond
t.Cleanup(func() { followEvery = was })
}
// A line still running when the controller first answers is followed, by its call, to what it printed.
func TestALineStillRunningIsFollowedToItsAnswer(t *testing.T) {
fastFollow(t)
running := result(map[string]any{"running": true, "call": "call-9"})
c := &controllerSays{script: []func(Asked) ([]byte, error){running, running, running,
result(map[string]any{"stdout": []byte("pushed\n"), "exit": 0, "terminal": true})}}
a := AskTheController(context.Background(), c.ask, Asked{Line: []string{"push", "laptop"}, Account: "op", UID: 1000})
if string(a.Stdout) != "pushed\n" || !a.Terminal || a.Refused != "" || a.Unknown != "" {
t.Fatalf("followed to %+v", a)
}
for _, f := range c.asked[1:] {
if f.Follow != "call-9" || f.Account != "op" || len(f.Line) != 0 {
t.Fatalf("a follow asked %+v", f)
}
}
}
// **No answer in time is never "nothing ran"** (review of ADR 0272): the line was asked and may have run, and the
// call to look at is named when it is known.
func TestNoAnswerInTimeSaysTheLineMayHaveRun(t *testing.T) {
fastFollow(t)
c := &controllerSays{}
a := AskTheController(context.Background(), c.ask, Asked{Line: []string{"push"}, Account: "op"})
if a.Refused != "" || !strings.Contains(a.Unknown, "may have run") || a.Exit == 0 {
t.Fatalf("a request with no answer reads %+v", a)
}
c = &controllerSays{script: []func(Asked) ([]byte, error){result(map[string]any{"running": true, "call": "call-3"}),
func(Asked) ([]byte, error) { return nil, context.DeadlineExceeded }}}
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
defer cancel()
a = AskTheController(ctx, c.ask, Asked{Line: []string{"push"}, Account: "op"})
if a.Refused != "" || !strings.Contains(a.Unknown, "call-3") || !strings.Contains(a.Unknown, "may have run") {
t.Fatalf("a running line never answered reads %+v", a)
}
}
// A request the bus never carried to a controller ran nothing, and says so.
func TestARequestNobodyTookSaysNothingRan(t *testing.T) {
c := &controllerSays{script: []func(Asked) ([]byte, error){func(Asked) ([]byte, error) {
return nil, fmt.Errorf("nothing on this machine answers mesh.control.laptop.cli")
}}}
a := AskTheController(context.Background(), c.ask, Asked{Line: []string{"status"}, Account: "op"})
if !strings.Contains(a.Refused, "nothing ran") || a.Unknown != "" {
t.Fatalf("a request nobody took reads %+v", a)
}
c = &controllerSays{script: []func(Asked) ([]byte, error){func(Asked) ([]byte, error) {
return nil, errors.New("this machine has no link to the bus open now")
}}}
if a := AskTheController(context.Background(), c.ask, Asked{Line: []string{"status"}}); !strings.Contains(a.Refused, "nothing ran") {
t.Fatalf("no link reads %+v", a)
}
}