Files
groundstation/internal/config/config_test.go
T

117 lines
3.5 KiB
Go

package config
import (
"os"
"path/filepath"
"testing"
)
func TestDefaultConfigStartsKioskDisplay(t *testing.T) {
cfg := Default()
if !cfg.Display.Enabled {
t.Fatal("kiosk display must be enabled by default")
}
if cfg.Display.Command != "/usr/local/bin/groundstation-display" {
t.Fatalf("command=%q", cfg.Display.Command)
}
if cfg.Display.User != "orangepi" {
t.Fatalf("user=%q", cfg.Display.User)
}
if cfg.Display.Display != ":0" {
t.Fatalf("display=%q want :0", cfg.Display.Display)
}
if cfg.Display.Xauthority != "/home/orangepi/.Xauthority" {
t.Fatalf("xauthority=%q", cfg.Display.Xauthority)
}
}
func TestLoadOverridesDisplaySettings(t *testing.T) {
path := filepath.Join(t.TempDir(), "config.yml")
body := "display:\n enabled: false\n command: /bin/kiosk\n"
if err := os.WriteFile(path, []byte(body), 0644); err != nil {
t.Fatal(err)
}
cfg, err := Load(path)
if err != nil {
t.Fatal(err)
}
if cfg.Display.Enabled {
t.Fatal("display override must disable the kiosk")
}
if cfg.Display.Command != "/bin/kiosk" {
t.Fatalf("command=%q want /bin/kiosk", cfg.Display.Command)
}
if cfg.Display.Display != ":0" {
t.Fatalf("display=%q want default :0", cfg.Display.Display)
}
}
func TestDefaultConfigPublishesOSDSnapshotsFromAUX1(t *testing.T) {
cfg := Default()
if cfg.OSD.StatePath != "/run/groundstation/osd-state.bin" {
t.Fatalf("state_path=%q want the default tmpfs path", cfg.OSD.StatePath)
}
// CH5/AUX1 is the arming channel; the fail-closed convention reads it
// armed above the midpoint.
if cfg.OSD.ArmIndex != 4 {
t.Fatalf("arm_index=%d want 4 (CH5/AUX1, zero-based)", cfg.OSD.ArmIndex)
}
if cfg.OSD.ArmedThreshold != 0 {
t.Fatalf("armed_threshold=%d want 0", cfg.OSD.ArmedThreshold)
}
}
func TestLoadOverridesOSDSettings(t *testing.T) {
path := filepath.Join(t.TempDir(), "config.yml")
body := "osd:\n state_path: /tmp/osd-state.bin\n arm_index: 6\n armed_threshold: 256\n vtx_table_gen: 3\n vtx_table_hash: 9\n"
if err := os.WriteFile(path, []byte(body), 0644); err != nil {
t.Fatal(err)
}
cfg, err := Load(path)
if err != nil {
t.Fatal(err)
}
if cfg.OSD.StatePath != "/tmp/osd-state.bin" {
t.Fatalf("state_path=%q want the override", cfg.OSD.StatePath)
}
if cfg.OSD.ArmIndex != 6 || cfg.OSD.ArmedThreshold != 256 {
t.Fatalf("arm config=%+v want the overrides", cfg.OSD)
}
if cfg.OSD.VtxTableGen != 3 || cfg.OSD.VtxTableHash != 9 {
t.Fatalf("table config=%+v want the selected table", cfg.OSD)
}
}
func TestDefaultConfigSelectsNoVtxTable(t *testing.T) {
// No table exists yet: the operator selection defaults to none, so the
// OSD shows an explicit pending table instead of static configuration
// dressed up as applied VTX state.
cfg := Default()
if cfg.OSD.VtxTableGen != 0 || cfg.OSD.VtxTableHash != 0 {
t.Fatalf("table config=%+v must default to no selection", cfg.OSD)
}
}
func TestLoadRejectsArmAndVideoIndexesOutsideTheChannelRange(t *testing.T) {
for name, body := range map[string]string{
"arm index below range": "osd:\n arm_index: -1\n",
"arm index above range": "osd:\n arm_index: 16\n",
"video index below range": "video:\n aux_index: -1\n",
"video index above range": "video:\n aux_index: 16\n",
} {
path := filepath.Join(t.TempDir(), "config.yml")
if err := os.WriteFile(path, []byte(body), 0644); err != nil {
t.Fatal(err)
}
if _, err := Load(path); err == nil {
t.Fatalf("%s must be rejected: an out-of-range index would panic on the first frame", name)
}
}
}