config updated to improve setting values, writing changes and test coverage
This commit is contained in:
1 parent
8f0e72821f
commit
169c6c6b64
8 files changed
+453
-59
No files matched your search
@@ -0,0 +1,129 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"go.yaml.in/yaml/v3"
|
||||
)
|
||||
|
||||
// captureStdout returns what fn prints to os.Stdout.
|
||||
func captureStdout(t *testing.T, fn func()) string {
|
||||
t.Helper()
|
||||
path := filepath.Join(t.TempDir(), "stdout")
|
||||
f, err := os.Create(filepath.Clean(path))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
old := os.Stdout
|
||||
os.Stdout = f
|
||||
fn()
|
||||
os.Stdout = old
|
||||
if err := f.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b, err := os.ReadFile(filepath.Clean(path))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func TestPrintTerminal(t *testing.T) {
|
||||
conf := defaultConfig(t)
|
||||
got := captureStdout(t, conf.PrintTerminal)
|
||||
if want := conf.String() + "\n"; got != want {
|
||||
t.Errorf("PrintTerminal printed %q; want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// String lists every key once, sorted, so the output is the same each run.
|
||||
func TestStringSorted(t *testing.T) {
|
||||
conf := defaultConfig(t)
|
||||
var keys []string
|
||||
for _, line := range strings.Split(strings.TrimSpace(conf.String()), "\n") {
|
||||
key, _, _ := strings.Cut(line, " = ")
|
||||
keys = append(keys, key)
|
||||
}
|
||||
if !slices.IsSorted(keys) || len(keys) != len(conf.Flatten()) {
|
||||
t.Errorf("String keys = %v; want each key once, sorted", keys)
|
||||
}
|
||||
if first := conf.String(); conf.String() != first {
|
||||
t.Error("String output differs between calls")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintJson(t *testing.T) {
|
||||
conf := defaultConfig(t)
|
||||
out := captureStdout(t, conf.PrintJson)
|
||||
var m map[string]any
|
||||
if err := json.Unmarshal([]byte(out), &m); err != nil {
|
||||
t.Fatalf("PrintJson output is not JSON: %v\n%s", err, out)
|
||||
}
|
||||
if got := m["logging"].(map[string]any)["level"]; got != "warn" {
|
||||
t.Errorf("logging.level = %v; want warn", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintYaml(t *testing.T) {
|
||||
conf := defaultConfig(t)
|
||||
out := captureStdout(t, conf.PrintYaml)
|
||||
var m map[string]any
|
||||
if err := yaml.Unmarshal([]byte(out), &m); err != nil {
|
||||
t.Fatalf("PrintYaml output is not YAML: %v\n%s", err, out)
|
||||
}
|
||||
if got := m["logging"].(map[string]any)["level"]; got != "warn" {
|
||||
t.Errorf("logging.level = %v; want warn", got)
|
||||
}
|
||||
}
|
||||
|
||||
// PrintLog logs one line per key, at the level asked for (info for any
|
||||
// level other than debug, warn and error).
|
||||
func TestPrintLog(t *testing.T) {
|
||||
conf := defaultConfig(t)
|
||||
for _, tt := range []struct {
|
||||
at slog.Level
|
||||
want string
|
||||
}{
|
||||
{slog.LevelDebug, "level=DEBUG"},
|
||||
{slog.LevelInfo, "level=INFO"},
|
||||
{slog.LevelWarn, "level=WARN"},
|
||||
{slog.LevelError, "level=ERROR"},
|
||||
{slog.LevelError + 4, "level=INFO"},
|
||||
} {
|
||||
logs := captureLogs(t, slog.LevelDebug)
|
||||
conf.PrintLog(tt.at)
|
||||
|
||||
lines := strings.Split(strings.TrimSpace(logs.String()), "\n")
|
||||
if len(lines) != len(conf.Flatten()) {
|
||||
t.Errorf("PrintLog(%v) logged %d lines; want %d", tt.at, len(lines), len(conf.Flatten()))
|
||||
}
|
||||
for _, l := range lines {
|
||||
if !strings.Contains(l, tt.want) {
|
||||
t.Errorf("PrintLog(%v) line %q; want %s", tt.at, l, tt.want)
|
||||
}
|
||||
}
|
||||
if !strings.Contains(logs.String(), "logging.level = warn") {
|
||||
t.Errorf("PrintLog(%v) missing logging.level:\n%s", tt.at, logs)
|
||||
}
|
||||
// Each line is msg="\t<key> = <value>".
|
||||
flat := conf.Flatten()
|
||||
var keys []string
|
||||
for _, l := range lines {
|
||||
_, msg, _ := strings.Cut(l, `msg="\t`)
|
||||
key, _, _ := strings.Cut(msg, " = ")
|
||||
if _, ok := flat[key]; !ok {
|
||||
t.Errorf("PrintLog(%v) line %q: no key", tt.at, l)
|
||||
}
|
||||
keys = append(keys, key)
|
||||
}
|
||||
if !slices.IsSorted(keys) {
|
||||
t.Errorf("PrintLog(%v) keys not sorted: %v", tt.at, keys)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user