package config import ( "os" "path/filepath" "testing" ) func write(t *testing.T, body string) string { t.Helper() dir := t.TempDir() p := filepath.Join(dir, "config.toml") if err := os.WriteFile(p, []byte(body), 0o600); err != nil { t.Fatal(err) } return p } // disc_prefix used to be stored verbatim and never read, so a typo or an // invented value was accepted and then silently did nothing. func TestDiscPrefixRejectsUnknownValues(t *testing.T) { // Load reads the real config path too, so the values are set by file here. for _, good := range []string{"always", "never", "auto", "AUTO", " auto "} { if _, err := Load(write(t, "disc_prefix = \""+good+"\"")); err != nil { t.Errorf("disc_prefix = %q should be accepted: %v", good, err) } } for _, bad := range []string{"sometimes", "", "true"} { if _, err := Load(write(t, "disc_prefix = \""+bad+"\"")); err == nil { t.Errorf("disc_prefix = %q should be rejected", bad) } } } // An unrecognised verify_decode used to be stored verbatim and then matched none // of the modes the verifier knows, so a typo quietly turned the only end-to-end // check of the audio that gets written into a no-op. func TestVerifyDecodeRejectsUnknownValues(t *testing.T) { for _, good := range []string{"all", "sample", "none", "SAMPLE", " all "} { if _, err := Load(write(t, "verify_decode = \""+good+"\"")); err != nil { t.Errorf("verify_decode = %q should be accepted: %v", good, err) } } for _, bad := range []string{"", "sample2", "yes", "true"} { if _, err := Load(write(t, "verify_decode = \""+bad+"\"")); err == nil { t.Errorf("verify_decode = %q should be rejected", bad) } } } // libvorbis takes 1-10, and a value outside that used to reach ffmpeg, which // failed the whole album with an encoder error rather than a configuration one. func TestQualityRangeIsChecked(t *testing.T) { for _, good := range []string{"1", "9", "10"} { if _, err := Load(write(t, "quality = "+good)); err != nil { t.Errorf("quality = %s should be accepted: %v", good, err) } } for _, bad := range []string{"0", "11", "-3"} { if _, err := Load(write(t, "quality = "+bad)); err == nil { t.Errorf("quality = %s should be rejected", bad) } } } // The ignore list lives beside staging, archive and library, one folder name per // line, because it describes this library rather than this machine. func TestIgnoreListRoundTrips(t *testing.T) { root := t.TempDir() cfg := Defaults() cfg.Root = root got, err := cfg.LoadIgnore() if err != nil { t.Fatalf("a missing ignore file is not an error: %v", err) } if len(got) != 0 { t.Errorf("a missing ignore file produced %v", got) } if added, err := cfg.AddIgnore("Some Junk Folder"); err != nil || !added { t.Fatalf("AddIgnore: %v %v", added, err) } if added, err := cfg.AddIgnore("Some Junk Folder"); err != nil || added { t.Errorf("adding the same name twice should report no change: %v %v", added, err) } if added, err := cfg.AddIgnore(" "); err != nil || added { t.Errorf("a blank name should be refused: %v %v", added, err) } if _, err := cfg.AddIgnore("another one"); err != nil { t.Fatal(err) } got, err = cfg.LoadIgnore() if err != nil { t.Fatal(err) } if !got["Some Junk Folder"] || !got["another one"] || len(got) != 2 { t.Errorf("ignore set = %v", got) } if removed, err := cfg.RemoveIgnore("Some Junk Folder"); err != nil || !removed { t.Fatalf("RemoveIgnore: %v %v", removed, err) } if removed, err := cfg.RemoveIgnore("not there"); err != nil || removed { t.Errorf("removing something absent should report no change: %v %v", removed, err) } got, _ = cfg.LoadIgnore() if got["Some Junk Folder"] || !got["another one"] { t.Errorf("ignore set after removal = %v", got) } } // Hand-editing the file has to work: it is a plain list with comments. func TestIgnoreListIsHandEditable(t *testing.T) { root := t.TempDir() cfg := Defaults() cfg.Root = root body := "# my notes\n\n spaced name \n# another comment\nsecond\n" if err := os.WriteFile(cfg.IgnorePath(), []byte(body), 0o644); err != nil { t.Fatal(err) } got, err := cfg.LoadIgnore() if err != nil { t.Fatal(err) } if !got["spaced name"] || !got["second"] || len(got) != 2 { t.Errorf("ignore set = %v", got) } }