97 lines
3.0 KiB
Go
97 lines
3.0 KiB
Go
//go:build integration
|
|
|
|
package link
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/nats-io/nats.go"
|
|
"github.com/novox/mesh-controller/internal/testbus"
|
|
)
|
|
|
|
func cliBus(t *testing.T, l *CallLog, atOnce int, handle CLIHandler) *nats.Conn {
|
|
t.Helper()
|
|
conn, err := nats.Connect(testbus.URL(t))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(conn.Close)
|
|
stop, err := OverNATS{Conn: conn}.serveCLI(l, atOnce, handle, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(stop)
|
|
return conn
|
|
}
|
|
|
|
func TestALongMeshCLILineIsFollowedToItsAnswer(t *testing.T) {
|
|
was := AnswerWithin
|
|
AnswerWithin = 50 * time.Millisecond
|
|
t.Cleanup(func() { AnswerWithin = was })
|
|
release := make(chan struct{})
|
|
conn := cliBus(t, NewCallLog(), 4, func(ctx context.Context, node string, asked CLIAsked) CLIAnswer {
|
|
<-release
|
|
return CLIAnswer{Stdout: []byte("done on " + node), Terminal: true}
|
|
})
|
|
_, first, failed := askCLI(t, conn, "laptop", CLIAsked{Line: []string{"push", "laptop"}, Account: "op", UID: 1000})
|
|
call, _ := first["call"].(string)
|
|
if failed != "" || first["running"] != true || call == "" {
|
|
t.Fatalf("a long line was not answered as running with its call: %v %q", first, failed)
|
|
}
|
|
_, still, _ := askCLI(t, conn, "laptop", CLIAsked{Follow: call, Account: "op", UID: 1000})
|
|
if still["running"] != true {
|
|
t.Fatalf("following a running line answered %v", still)
|
|
}
|
|
close(release)
|
|
deadline := time.Now().Add(5 * time.Second)
|
|
for {
|
|
a, raw, failed := askCLI(t, conn, "laptop", CLIAsked{Follow: call, Account: "op", UID: 1000})
|
|
if failed != "" {
|
|
t.Fatalf("following answered %q", failed)
|
|
}
|
|
if raw["running"] != true {
|
|
if string(a.Stdout) != "done on laptop" || !a.Terminal {
|
|
t.Fatalf("followed to %+v", a)
|
|
}
|
|
break
|
|
}
|
|
if time.Now().After(deadline) {
|
|
t.Fatal("the line never finished for its follower")
|
|
}
|
|
time.Sleep(20 * time.Millisecond)
|
|
}
|
|
if _, _, failed := askCLI(t, conn, "laptop", CLIAsked{Follow: call, Account: "agent", UID: 1001}); failed == "" {
|
|
t.Fatal("another account followed the operator's line")
|
|
}
|
|
if _, _, failed := askCLI(t, conn, "desktop", CLIAsked{Follow: call, Account: "op", UID: 1000}); failed == "" {
|
|
t.Fatal("another node followed the line")
|
|
}
|
|
}
|
|
|
|
func TestMeshCLILinesAtOnceAreBounded(t *testing.T) {
|
|
was := AnswerWithin
|
|
AnswerWithin = 50 * time.Millisecond
|
|
t.Cleanup(func() { AnswerWithin = was })
|
|
release := make(chan struct{})
|
|
t.Cleanup(func() { close(release) })
|
|
ran := make(chan struct{}, 4)
|
|
conn := cliBus(t, NewCallLog(), 1, func(context.Context, string, CLIAsked) CLIAnswer {
|
|
ran <- struct{}{}
|
|
<-release
|
|
return CLIAnswer{}
|
|
})
|
|
if _, first, _ := askCLI(t, conn, "laptop", CLIAsked{Line: []string{"status"}, Account: "op"}); first["running"] != true {
|
|
t.Fatalf("the first line answered %v", first)
|
|
}
|
|
a, _, _ := askCLI(t, conn, "laptop", CLIAsked{Line: []string{"status"}, Account: "op"})
|
|
if !strings.Contains(a.Refused, "busy") || a.Exit == 0 {
|
|
t.Fatalf("a line over the bound answered %+v", a)
|
|
}
|
|
if len(ran) != 1 {
|
|
t.Fatalf("%d lines ran, one was bound", len(ran))
|
|
}
|
|
}
|