Files
petere 34efbaf26d feat: support custom --config path in CLI and GUI
Add config.LoadFrom/SaveTo for arbitrary paths and thread a --config
flag through both entry points:
- CLI: --config loads a file first; explicit flags override file values
- GUI: --config selects the settings file used for load and save
- tests for LoadFrom/SaveTo and default fallback
2026-09-19 08:35:07 +01:00

125 lines
3.4 KiB
Go

package config
import (
"os"
"path/filepath"
"testing"
)
// TestLoadDefaultsWhenMissing verifies Load returns defaults when the file
// does not exist.
func TestLoadDefaultsWhenMissing(t *testing.T) {
// Point at a non-existent directory so we never touch the real config.
old := pathVar
pathVar = filepath.Join(t.TempDir(), "nope", "config.json")
defer func() { pathVar = old }()
c, err := Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
if c.Port != 9756 {
t.Errorf("default port = %d, want 9756", c.Port)
}
}
// TestSaveLoadRoundTrip writes a config and reads it back.
func TestSaveLoadRoundTrip(t *testing.T) {
old := pathVar
pathVar = filepath.Join(t.TempDir(), "config.json")
defer func() { pathVar = old }()
announce := false
want := Config{
Name: "Studio",
Port: 9898,
Quality: 95,
FPS: 60,
Source: "pattern",
Audio: false,
StreamIndex: 1,
Announce: &announce,
}
if err := Save(want); err != nil {
t.Fatalf("Save: %v", err)
}
got, err := Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
if got.Name != want.Name || got.Port != want.Port || got.Quality != want.Quality ||
got.FPS != want.FPS || got.Source != want.Source || got.Audio != want.Audio ||
got.StreamIndex != want.StreamIndex || got.Announce == nil || want.Announce == nil ||
*got.Announce != *want.Announce {
t.Errorf("round trip mismatch:\n got %+v\nwant %+v", got, want)
}
}
// TestLoadFillsZeroValues ensures a partial file gets defaults filled.
func TestLoadFillsZeroValues(t *testing.T) {
old := pathVar
pathVar = filepath.Join(t.TempDir(), "config.json")
defer func() { pathVar = old }()
if err := os.WriteFile(pathVar, []byte(`{"name":"Partial"}`), 0o600); err != nil {
t.Fatalf("write: %v", err)
}
c, err := Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
if c.Name != "Partial" {
t.Errorf("name = %q, want Partial", c.Name)
}
if c.Port != 9756 {
t.Errorf("port = %d, want filled default 9756", c.Port)
}
if c.Quality != 80 {
t.Errorf("quality = %d, want filled default 80", c.Quality)
}
// Absent "announce" key must default to true (not false).
if c.Announce == nil || !*c.Announce {
t.Errorf("announce = %v, want default true", c.Announce)
}
}
// TestToFlingerAnnounceDefault checks the announce default survives conversion.
func TestToFlingerAnnounceDefault(t *testing.T) {
c := Config{}
if !c.ToFlinger().Announce {
t.Error("ToFlinger announce default should be true")
}
}
// TestLoadFromMissing returns defaults for a non-existent custom path.
func TestLoadFromMissing(t *testing.T) {
c, err := LoadFrom(filepath.Join(t.TempDir(), "missing", "config.json"))
if err != nil {
t.Fatalf("LoadFrom: %v", err)
}
if c.Port != 9756 {
t.Errorf("default port = %d, want 9756", c.Port)
}
}
// TestSaveToLoadFromRoundTrip uses an explicit path independent of pathVar.
func TestSaveToLoadFromRoundTrip(t *testing.T) {
p := filepath.Join(t.TempDir(), "custom", "daemon.json")
announce := false
want := Config{Name: "Daemon", Port: 9901, Quality: 90, FPS: 30, Source: "screen", Audio: true, Announce: &announce}
if err := SaveTo(p, want); err != nil {
t.Fatalf("SaveTo: %v", err)
}
got, err := LoadFrom(p)
if err != nil {
t.Fatalf("LoadFrom: %v", err)
}
if got.Name != want.Name || got.Port != want.Port || *got.Announce != false {
t.Errorf("round trip mismatch: got %+v want %+v", got, want)
}
}