Unit tests added for internal/config
This commit is contained in:
1 parent
09644d0691
commit
69620e5f7d
4 files changed
+631
No files matched your search
@@ -0,0 +1,163 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// useConfigFile points Viper at a new YAML config file holding contents.
|
||||
func useConfigFile(t *testing.T, contents string) string {
|
||||
t.Helper()
|
||||
resetViper(t)
|
||||
path := filepath.Join(t.TempDir(), "config.yaml")
|
||||
if err := os.WriteFile(path, []byte(contents), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
viper.SetConfigFile(path)
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// readConfigFile reads path with a fresh Viper.
|
||||
func readConfigFile(t *testing.T, path string) *viper.Viper {
|
||||
t.Helper()
|
||||
v := viper.New()
|
||||
v.SetConfigFile(path)
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func TestStoreValue(t *testing.T) {
|
||||
tests := []struct {
|
||||
key, value string
|
||||
want any
|
||||
kind reflect.Kind
|
||||
}{
|
||||
{"logging.level", "debug", "debug", reflect.String},
|
||||
{"sources.sleeper.enabled", "true", true, reflect.Bool},
|
||||
{"sources.fts_mock.api_root", "http://mock", "http://mock", reflect.String},
|
||||
{"sources.fts_mock.interval", "30s", "30s", reflect.String},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.key, func(t *testing.T) {
|
||||
path := useConfigFile(t, "logging:\n level: warn\n")
|
||||
conf := defaultConfig(t)
|
||||
|
||||
got, kind, err := StoreValue(&conf, tt.key, tt.value)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got != tt.want || kind != tt.kind {
|
||||
t.Errorf("got %#v <%s>; want %#v <%s>", got, kind, tt.want, tt.kind)
|
||||
}
|
||||
if v := readConfigFile(t, path).Get(tt.key); v != tt.want {
|
||||
t.Errorf("file has %s = %#v; want %#v", tt.key, v, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreValueKeepsOtherKeys(t *testing.T) {
|
||||
path := useConfigFile(t, "logging:\n level: warn\n file: /tmp/js.log\n")
|
||||
conf := defaultConfig(t)
|
||||
if _, _, err := StoreValue(&conf, "logging.level", "error"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
v := readConfigFile(t, path)
|
||||
if got := v.GetString("logging.file"); got != "/tmp/js.log" {
|
||||
t.Errorf("logging.file = %q; want it kept", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreValueErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
name, key, value, wantErr string
|
||||
}{
|
||||
{"unknown key", "nope", "x", ""},
|
||||
{"section key", "sources", "x", ""},
|
||||
{"bad bool", "sources.sleeper.enabled", "maybe", "expected <bool>"},
|
||||
{"invalid log level", "logging.level", "shouty", "invalid log level"},
|
||||
{"bad duration", "sources.fts_mock.interval", "eventually", "duration"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
path := useConfigFile(t, "logging:\n level: warn\n")
|
||||
before, _ := os.ReadFile(path)
|
||||
conf := defaultConfig(t)
|
||||
|
||||
_, _, err := StoreValue(&conf, tt.key, tt.value)
|
||||
if err == nil {
|
||||
t.Fatal("expected an error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), tt.wantErr) {
|
||||
t.Errorf("err = %v; want it to mention %q", err, tt.wantErr)
|
||||
}
|
||||
if after, _ := os.ReadFile(path); string(after) != string(before) {
|
||||
t.Errorf("config file changed:\n%s", after)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreValueNoConfigFile(t *testing.T) {
|
||||
resetViper(t)
|
||||
conf := defaultConfig(t)
|
||||
if _, _, err := StoreValue(&conf, "logging.level", "debug"); err == nil {
|
||||
t.Fatal("expected an error with no config file to write")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPurgeValue(t *testing.T) {
|
||||
path := useConfigFile(t, "logging:\n level: debug\n file: /tmp/js.log\n")
|
||||
conf := defaultConfig(t)
|
||||
|
||||
if err := PurgeValue(&conf, "logging.file"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
v := readConfigFile(t, path)
|
||||
if v.IsSet("logging.file") {
|
||||
t.Errorf("logging.file still set: %v", v.Get("logging.file"))
|
||||
}
|
||||
if got := v.GetString("logging.level"); got != "debug" {
|
||||
t.Errorf("logging.level = %q; want it kept", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPurgeValueErrors(t *testing.T) {
|
||||
path := useConfigFile(t, "logging:\n level: debug\n")
|
||||
before, _ := os.ReadFile(path)
|
||||
conf := defaultConfig(t)
|
||||
|
||||
if err := PurgeValue(&conf, "nope"); err == nil {
|
||||
t.Error("expected an error for an unknown key")
|
||||
}
|
||||
if after, _ := os.ReadFile(path); string(after) != string(before) {
|
||||
t.Errorf("config file changed:\n%s", after)
|
||||
}
|
||||
|
||||
resetViper(t)
|
||||
if err := PurgeValue(&conf, "logging.level"); err == nil {
|
||||
t.Error("expected an error with no config file to write")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreValueUpdatesConf(t *testing.T) {
|
||||
useConfigFile(t, "logging:\n level: warn\n")
|
||||
conf := defaultConfig(t)
|
||||
if _, _, err := StoreValue(&conf, "sources.fts_mock.interval", "30s"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if conf.Sources.FTSMock.Interval != 30*time.Second {
|
||||
t.Errorf("FTSMock.Interval = %v; want 30s", conf.Sources.FTSMock.Interval)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user