126 lines
3.8 KiB
Go
126 lines
3.8 KiB
Go
package display
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.piksar.eu/piotr/groundstation/internal/osd"
|
|
)
|
|
|
|
// stubSource serves one fixed snapshot, or none.
|
|
type stubSource struct {
|
|
snapshot osd.Snapshot
|
|
ok bool
|
|
}
|
|
|
|
func (s stubSource) Latest() (osd.Snapshot, bool) { return s.snapshot, s.ok }
|
|
|
|
func armedSource(sequence uint16) stubSource {
|
|
return stubSource{snapshot: osd.Snapshot{Sequence: sequence, Armed: true, Power: true}, ok: true}
|
|
}
|
|
|
|
func TestOSDTemplateStaysTransparentWhileVideoAbsent(t *testing.T) {
|
|
canvas := &fakeCanvas{width: 800, height: 600}
|
|
|
|
NewOSDTemplate(NewVideoPresence(), armedSource(1)).Draw(canvas)
|
|
|
|
clears, flushes := canvas.drawCounts()
|
|
if clears != 1 || flushes != 1 {
|
|
t.Fatalf("clears=%d flushes=%d want 1 and 1", clears, flushes)
|
|
}
|
|
if lines := canvas.lines(); len(lines) != 0 {
|
|
t.Fatalf("OSD lines=%q want none: without video the fallback canvas owns the screen", lines)
|
|
}
|
|
}
|
|
|
|
func TestOSDTemplateDrawsMinimalTelemetryWhileVideoPresent(t *testing.T) {
|
|
canvas := &fakeCanvas{width: 800, height: 600}
|
|
presence := NewVideoPresence()
|
|
presence.SetActive(true)
|
|
|
|
NewOSDTemplate(presence, armedSource(7)).Draw(canvas)
|
|
|
|
clears, flushes := canvas.drawCounts()
|
|
if clears != 1 || flushes != 1 {
|
|
t.Fatalf("clears=%d flushes=%d want 1 and 1", clears, flushes)
|
|
}
|
|
lines := canvas.lines()
|
|
want := []string{"ARM ARMED", "PWR ON"}
|
|
if len(lines) != len(want) {
|
|
t.Fatalf("lines=%q want %q", lines, want)
|
|
}
|
|
for i := range want {
|
|
if lines[i] != want[i] {
|
|
t.Fatalf("line %d=%q want %q", i, lines[i], want[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOSDTemplateDrawsDisarmedAndPoweredOffState(t *testing.T) {
|
|
canvas := &fakeCanvas{width: 800, height: 600}
|
|
presence := NewVideoPresence()
|
|
presence.SetActive(true)
|
|
|
|
NewOSDTemplate(presence, stubSource{ok: true}).Draw(canvas)
|
|
|
|
lines := canvas.lines()
|
|
want := []string{"ARM OFF", "PWR OFF"}
|
|
if len(lines) != len(want) {
|
|
t.Fatalf("lines=%q want %q", lines, want)
|
|
}
|
|
for i := range want {
|
|
if lines[i] != want[i] {
|
|
t.Fatalf("line %d=%q want %q", i, lines[i], want[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOSDTemplateStaysTransparentWithoutASnapshotWhileVideoPresent(t *testing.T) {
|
|
canvas := &fakeCanvas{width: 800, height: 600}
|
|
presence := NewVideoPresence()
|
|
presence.SetActive(true)
|
|
|
|
NewOSDTemplate(presence, stubSource{}).Draw(canvas)
|
|
|
|
if lines := canvas.lines(); len(lines) != 0 {
|
|
t.Fatalf("OSD lines=%q want none without a published snapshot", lines)
|
|
}
|
|
}
|
|
|
|
func TestOSDTemplateGatesOnObservedVideoPresenceNotSnapshotVideo(t *testing.T) {
|
|
// The rendering gate is the video lifecycle the display observes on the
|
|
// display server, never the snapshot's Video field: the supervisor's
|
|
// field is its launcher knowledge, while the display trusts only the
|
|
// presented video output itself.
|
|
canvas := &fakeCanvas{width: 800, height: 600}
|
|
presence := NewVideoPresence()
|
|
|
|
claimingVideo := stubSource{snapshot: osd.Snapshot{Armed: true, Video: true}, ok: true}
|
|
NewOSDTemplate(presence, claimingVideo).Draw(canvas)
|
|
if lines := canvas.lines(); len(lines) != 0 {
|
|
t.Fatalf("lines=%q want none: snapshot presence must never replace the observed lifecycle", lines)
|
|
}
|
|
|
|
denyingVideo := stubSource{snapshot: osd.Snapshot{Armed: true}, ok: true}
|
|
presence.SetActive(true)
|
|
NewOSDTemplate(presence, denyingVideo).Draw(canvas)
|
|
if lines := canvas.lines(); len(lines) == 0 {
|
|
t.Fatal("the observed video lifecycle must gate rendering even when the snapshot denies video")
|
|
}
|
|
}
|
|
|
|
func TestOSDTemplateNeverDrawsTheFallbackText(t *testing.T) {
|
|
canvas := &fakeCanvas{width: 800, height: 600}
|
|
presence := NewVideoPresence()
|
|
template := NewOSDTemplate(presence, armedSource(3))
|
|
|
|
for _, active := range []bool{false, true, false} {
|
|
presence.SetActive(active)
|
|
template.Draw(canvas)
|
|
for _, line := range canvas.lines() {
|
|
if line == wantFallbackText {
|
|
t.Fatalf("the OSD is a telemetry surface, not a fallback: drew %q", line)
|
|
}
|
|
}
|
|
}
|
|
}
|