Default the update repo to the Gitea host
Settles the first open question in claude.md: the update endpoint is gitea.apointless.space/bsncubed/ipswap. It was left empty — which disables the checker — only because the host was unconfirmed. Load unmarshals over the defaults, so an absent update_repo takes the new default while an explicitly empty one stays empty. That distinction is the off switch, and forks depend on it, so it is now pinned by a test. Adds the config package's first tests while here: the defaulting rules above, the repair path for a nonsensical mask style or poll interval, and the guarantee that a corrupt config.json still yields usable defaults rather than stopping the app from starting. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadMissingFileReturnsDefaults(t *testing.T) {
|
||||
s, err := Load(filepath.Join(t.TempDir(), "config.json"))
|
||||
if err != nil {
|
||||
t.Fatalf("a missing config must not be an error: %v", err)
|
||||
}
|
||||
if s != Default() {
|
||||
t.Errorf("expected defaults, got %+v", s)
|
||||
}
|
||||
if s.UpdateRepo != DefaultUpdateRepo {
|
||||
t.Errorf("update repo default = %q, want %q", s.UpdateRepo, DefaultUpdateRepo)
|
||||
}
|
||||
}
|
||||
|
||||
// An absent field takes the default, but an explicitly empty one must stay
|
||||
// empty — that is how the update check is turned off.
|
||||
func TestExplicitEmptyUpdateRepoDisablesTheCheck(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "config.json")
|
||||
if err := os.WriteFile(path, []byte(`{"update_repo": ""}`), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
s, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if s.UpdateRepo != "" {
|
||||
t.Errorf("an explicit empty update_repo must be preserved, got %q", s.UpdateRepo)
|
||||
}
|
||||
// The rest of the file was absent, so it should still be defaulted.
|
||||
if s.ActivePollSeconds != Default().ActivePollSeconds {
|
||||
t.Errorf("unset fields should keep their defaults, got %+v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadRepairsNonsense(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "config.json")
|
||||
if err := os.WriteFile(path, []byte(`{"mask_style":"wat","active_poll_seconds":0}`), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
s, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if s.MaskStyle != MaskPrefix {
|
||||
t.Errorf("an unknown mask style should fall back to prefix, got %q", s.MaskStyle)
|
||||
}
|
||||
if s.ActivePollSeconds != 30 {
|
||||
t.Errorf("a zero poll interval should be repaired, got %d", s.ActivePollSeconds)
|
||||
}
|
||||
}
|
||||
|
||||
// A corrupt config must not stop the app from starting.
|
||||
func TestLoadCorruptFileReturnsDefaultsAndError(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "config.json")
|
||||
if err := os.WriteFile(path, []byte(`{not json`), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
s, err := Load(path)
|
||||
if err == nil {
|
||||
t.Error("expected an error for a corrupt config")
|
||||
}
|
||||
if s != Default() {
|
||||
t.Errorf("a corrupt config should still yield usable defaults, got %+v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSaveRoundTrip(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "nested", "config.json")
|
||||
|
||||
want := Default()
|
||||
want.MaskStyle = MaskDotted
|
||||
want.StartWithWindows = true
|
||||
want.UpdateRepo = "https://example.com/o/r"
|
||||
if err := want.Save(path); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got != want {
|
||||
t.Errorf("round trip changed the settings:\n got %+v\nwant %+v", got, want)
|
||||
}
|
||||
if !got.DottedMasks() {
|
||||
t.Error("DottedMasks should be true for MaskDotted")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user