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("%w: nothing on this machine answers mesh.control.laptop.cli", ErrNotAsked) }}} 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, fmt.Errorf("%w: this machine has no link to the bus open now", ErrNotAsked) }}} if a := AskTheController(context.Background(), c.ask, Asked{Line: []string{"status"}}); !strings.Contains(a.Refused, "nothing ran") { t.Fatalf("no link reads %+v", a) } } // **Any error once the request may have been delivered is not known, never "nothing ran"** (review of ADR 0272): // only a request the link says it never asked — no link open, nobody listening — ran nothing. func TestOnlyARequestNeverAskedSaysNothingRan(t *testing.T) { for _, c := range []struct { err error nothing bool }{ {fmt.Errorf("%w: this machine has no link to the bus open now", ErrNotAsked), true}, {fmt.Errorf("%w: nothing on this machine answers mesh.control.laptop.cli", ErrNotAsked), true}, {errors.New("nats: connection closed"), false}, {errors.New("mesh.control.laptop.cli: permissions violation"), false}, {context.DeadlineExceeded, false}, } { err := c.err ctl := &controllerSays{script: []func(Asked) ([]byte, error){func(Asked) ([]byte, error) { return nil, err }}} a := AskTheController(context.Background(), ctl.ask, Asked{Line: []string{"push"}, Account: "op"}) if c.nothing && (!strings.Contains(a.Refused, "nothing ran") || a.Unknown != "") { t.Errorf("%v reads %+v; it was never asked", err, a) } if !c.nothing && (a.Refused != "" || !strings.Contains(a.Unknown, "may have run")) { t.Errorf("%v reads %+v; it may have been asked", err, a) } } }