- Any failure of a request the link may have delivered now says the line may have run; "nothing ran" is said only of a request the link knows it never asked (no link open, nobody listening: link.ErrNotAsked). - A test holds that a connection saying nothing is answered within its deadline, set at accept, and gives its slot back. - The README says the socket refuses a process outside the machine's own namespaces, so flatpak, toolbox and distrobox shells are refused.
124 lines
4.8 KiB
Go
124 lines
4.8 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("%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)
|
|
}
|
|
}
|
|
}
|