Files
groundstation/cmd/groundstation-display/main_test.go
T
2026-10-02 10:23:28 +02:00

126 lines
4.0 KiB
Go

package main
import (
"errors"
"testing"
"time"
"git.piksar.eu/piotr/groundstation/internal/display"
)
type recordingCanvas struct {
width, height int
lines []string
clears, flushes int
}
func (c *recordingCanvas) Size() (int, int) { return c.width, c.height }
func (c *recordingCanvas) Clear() { c.clears++ }
func (c *recordingCanvas) Text(_, _ int, message string) {
c.lines = append(c.lines, message)
}
func (c *recordingCanvas) Flush() { c.flushes++ }
func TestBuildTargetBuildsIndependentVitureLayers(t *testing.T) {
layers, err := buildTarget("x11")
if err != nil {
t.Fatal(err)
}
if len(layers) != 2 {
t.Fatalf("layers=%d want the fallback canvas and the OSD overlay", len(layers))
}
canvas, osd := layers[0], layers[1]
if canvas.Name != "fallback-canvas" || osd.Name != "osd-overlay" {
t.Fatalf("layer names %q/%q want fallback-canvas/osd-overlay", canvas.Name, osd.Name)
}
canvasOpener, ok := canvas.Opener.(display.X11Opener)
if !ok {
t.Fatalf("canvas opener %T must be the X11 target", canvas.Opener)
}
if canvasOpener.Role != display.RoleBelow {
t.Fatalf("canvas layer role %v must stay below video", canvasOpener.Role)
}
osdOpener, ok := osd.Opener.(display.X11Opener)
if !ok {
t.Fatalf("OSD opener %T must be the X11 target", osd.Opener)
}
if osdOpener.Role != display.RoleAbove {
t.Fatalf("OSD layer role %v must stay above video", osdOpener.Role)
}
// Both layers must share one presence signal so the video lifecycle
// observed by either session drives both templates.
if canvasOpener.Video == nil || osdOpener.Video == nil || canvasOpener.Video != osdOpener.Video {
t.Fatal("layers must share one video presence signal")
}
// The canvas layer keeps the target-specific fallback template with the
// exact fallback text.
canvasSurface := &recordingCanvas{width: 800, height: 600}
canvas.Template.Draw(canvasSurface)
if len(canvasSurface.lines) != 1 || canvasSurface.lines[0] != "Brak połączenia WFB" {
t.Fatalf("canvas lines=%q want the exact fallback text", canvasSurface.lines)
}
// The OSD layer is the OSD surface, never the fallback.
osdSurface := &recordingCanvas{width: 800, height: 600}
osd.Template.Draw(osdSurface)
if len(osdSurface.lines) != 0 {
t.Fatalf("OSD lines=%q want none: the overlay must not duplicate the fallback", osdSurface.lines)
}
// Video presence hides the fallback on the canvas layer only.
canvasOpener.Video.SetActive(true)
canvasSurface.lines = nil
canvas.Template.Draw(canvasSurface)
if len(canvasSurface.lines) != 0 {
t.Fatalf("canvas lines=%q must disappear while video is present", canvasSurface.lines)
}
canvasOpener.Video.SetActive(false)
}
func TestBuildTargetRejectsUnknownTarget(t *testing.T) {
if _, err := buildTarget("hdmi-mirror"); err == nil {
t.Fatal("unknown target must fail")
}
}
func TestFormatDiagnosticRendersStructuredFields(t *testing.T) {
got := formatDiagnostic(display.Diagnostic{
Target: "x11",
Layer: "fallback-canvas",
Event: display.EventOpenFailed,
Err: errors.New("connect X11: refused"),
RetryDelay: 500 * time.Millisecond,
})
want := `target=x11 layer=fallback-canvas event=open_failed error="connect X11: refused" retry_delay=500ms`
if got != want {
t.Fatalf("formatDiagnostic=%q want %q", got, want)
}
}
func TestWireDiagnosticsTagsEveryLayerWithItsName(t *testing.T) {
layers, err := buildTarget("x11")
if err != nil {
t.Fatal(err)
}
wireDiagnostics("x11", layers)
for _, layer := range layers {
if layer.Options.Target != "x11" {
t.Fatalf("layer %q target=%q want x11", layer.Name, layer.Options.Target)
}
if layer.Options.Layer != layer.Name {
t.Fatalf("layer %q diagnostic layer=%q", layer.Name, layer.Options.Layer)
}
if layer.Options.Diagnostic == nil {
t.Fatalf("layer %q must carry the reconnect diagnostic hook", layer.Name)
}
}
// The shared hook must be safe to call from any layer goroutine.
layers[0].Options.Diagnostic(display.Diagnostic{Target: "x11", Layer: layers[0].Name})
}