Files
mesh-delivery/modules/mesh-delivery-view/internal/view/serve_test.go
T
jschoubben 1b6763de0d Serve the rows on a read-only socket and web page, and print them with mesh-delivery-cli (issue 1134)
The command holds no credential: it asks the local socket, which answers only the rows ask.
2026-10-18 19:31:50 +02:00

113 lines
3.2 KiB
Go

package view
import (
"bufio"
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
func served(t *testing.T) (string, *Model) {
t.Helper()
m := New()
fill(m, base(t)...)
fill(m, haveE(t, "a", "w", have(t, "b9", delivery.PhaseRunning, delivery.HealthOK, ""), t0))
dir, err := os.MkdirTemp(os.Getenv("TMPDIR"), "s")
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { os.RemoveAll(dir) })
path := filepath.Join(dir, "run", "cli.sock")
l, err := ListenSocket(path)
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithCancel(context.Background())
done := make(chan struct{})
go func() { ServeSocket(ctx, l, m); close(done) }()
t.Cleanup(func() { cancel(); l.Close(); <-done })
return path, m
}
func TestSocketAnswersRows(t *testing.T) { // 1134/AC6
path, m := served(t)
got, err := Ask(path)
if err != nil {
t.Fatal(err)
}
want := m.Snapshot()
b1, _ := json.Marshal(got)
b2, _ := json.Marshal(want)
if len(want.Rows) == 0 || string(b1) != string(b2) {
t.Fatalf("socket answered %s, want %s", b1, b2)
}
st, err := os.Stat(path)
if err != nil || st.Mode().Perm() != 0o666 {
t.Fatalf("socket mode = %v, %v; want 0666", st.Mode().Perm(), err)
}
dst, _ := os.Stat(filepath.Dir(path))
if dst.Mode().Perm() != 0o755 {
t.Fatalf("directory mode = %v, want 0755", dst.Mode().Perm())
}
}
func TestSocketRefusesAnyOtherAsk(t *testing.T) { // 1134/AC6
path, m := served(t)
before, _ := json.Marshal(m.Snapshot())
for _, ask := range []string{`{"ask":"start","module":"x"}`, `{"ask":"retry"}`, `{"ask":""}`, `not json`, `{}`} {
c, err := dial(path)
if err != nil {
t.Fatal(err)
}
c.Write([]byte(ask + "\n"))
line, err := bufio.NewReader(c).ReadString('\n')
c.Close()
if err != nil || !strings.Contains(line, `"error"`) || strings.Contains(line, `"rows"`) {
t.Errorf("ask %q answered %q, %v; want a refusal", ask, line, err)
}
}
after, _ := json.Marshal(m.Snapshot())
if string(before) != string(after) {
t.Fatal("a refused ask changed the rows")
}
}
func TestTableShowsEveryRow(t *testing.T) { // 1134/AC6
_, m := served(t)
var out strings.Builder
s := m.Snapshot()
Table(&out, s)
for _, r := range s.Rows {
if !strings.Contains(out.String(), r.Module) {
t.Fatalf("table lacks %s:\n%s", r.Module, out.String())
}
}
for _, w := range []string{"NODE", "MODULE", "ASSIGNED", "HAVE", "PHASE", "HEALTH", "SINCE", "WAITS", "no have yet", "left behind"} {
if !strings.Contains(out.String(), w) {
t.Errorf("table lacks %q:\n%s", w, out.String())
}
}
}
func TestWebIsTheSameRowsAndReadOnly(t *testing.T) { // 1134/AC6
_, m := served(t)
h := Web(m)
rec := httptest.NewRecorder()
h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil))
if rec.Code != 200 || !strings.Contains(rec.Body.String(), "no have yet") || !strings.Contains(rec.Header().Get("Content-Type"), "text/html") {
t.Fatalf("web = %d %q", rec.Code, rec.Body.String())
}
rec = httptest.NewRecorder()
h.ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "/", strings.NewReader("x")))
if rec.Code != http.StatusMethodNotAllowed {
t.Fatalf("POST = %d, want 405", rec.Code)
}
}