TestSettingDefaults enumerates registry types; 'float' hit the unknown- type branch. Added float validation (default parses, within [min,max]) mirroring the int case.
113 lines
3.5 KiB
Go
113 lines
3.5 KiB
Go
package database
|
|
|
|
import (
|
|
"strconv"
|
|
"testing"
|
|
)
|
|
|
|
// TestSettingDefaults ensures every seeded setting has a compiled default with
|
|
// a valid value for its declared type. This guards against typos that would
|
|
// silently fall back at runtime.
|
|
func TestSettingDefaults(t *testing.T) {
|
|
if len(SettingDefaults) == 0 {
|
|
t.Fatal("SettingDefaults is empty")
|
|
}
|
|
for _, d := range SettingDefaults {
|
|
if d.Key == "" {
|
|
t.Errorf("default has empty key: %+v", d)
|
|
continue
|
|
}
|
|
switch d.Type {
|
|
case SettingTypeInt:
|
|
if _, err := strconv.Atoi(d.Value); err != nil {
|
|
t.Errorf("int setting %s default %q is not an int: %v", d.Key, d.Value, err)
|
|
}
|
|
if d.Min != "" {
|
|
if _, err := strconv.Atoi(d.Min); err != nil {
|
|
t.Errorf("int setting %s min %q is not an int", d.Key, d.Min)
|
|
}
|
|
}
|
|
if d.Max != "" {
|
|
if _, err := strconv.Atoi(d.Max); err != nil {
|
|
t.Errorf("int setting %s max %q is not an int", d.Key, d.Max)
|
|
}
|
|
}
|
|
case SettingTypeBool:
|
|
if _, err := strconv.ParseBool(d.Value); err != nil {
|
|
t.Errorf("bool setting %s default %q is not a bool", d.Key, d.Value)
|
|
}
|
|
case SettingTypeFloat:
|
|
f, err := strconv.ParseFloat(d.Value, 64)
|
|
if err != nil {
|
|
t.Errorf("float setting %s default %q is not a float", d.Key, d.Value)
|
|
}
|
|
if d.Min != "" {
|
|
if mn, err := strconv.ParseFloat(d.Min, 64); err == nil && f < mn {
|
|
t.Errorf("float setting %s default %q below min %q", d.Key, d.Value, d.Min)
|
|
}
|
|
}
|
|
if d.Max != "" {
|
|
if mx, err := strconv.ParseFloat(d.Max, 64); err == nil && f > mx {
|
|
t.Errorf("float setting %s default %q above max %q", d.Key, d.Value, d.Max)
|
|
}
|
|
}
|
|
case SettingTypeString:
|
|
if d.Value == "" {
|
|
t.Errorf("string setting %s has empty default", d.Key)
|
|
}
|
|
default:
|
|
t.Errorf("setting %s has unknown type %q", d.Key, d.Type)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestSettingsRegistryGetIntClamping verifies that out-of-range DB values are
|
|
// clamped to the declared min/max, and that garbage falls back to the default.
|
|
func TestSettingsRegistryGetIntClamping(t *testing.T) {
|
|
r := &SettingsRegistry{values: map[string]string{}, q: nil}
|
|
|
|
// Seed with an over-max value; expect clamping to the max (3600).
|
|
r.values["scan_poll_interval_seconds"] = "999999"
|
|
if got := r.ScanPollInterval(); got.Seconds() != 3600 {
|
|
t.Errorf("expected clamp to 3600, got %v", got)
|
|
}
|
|
|
|
// Seed with an under-min value; expect clamp to min (1).
|
|
r.values["scan_poll_interval_seconds"] = "0"
|
|
if got := r.ScanPollInterval(); got.Seconds() != 1 {
|
|
t.Errorf("expected clamp to 1, got %v", got)
|
|
}
|
|
|
|
// Seed with garbage; expect fallback to default (60).
|
|
r.values["scan_poll_interval_seconds"] = "not-a-number"
|
|
if got := r.ScanPollInterval(); got.Seconds() != 60 {
|
|
t.Errorf("expected fallback default 60, got %v", got)
|
|
}
|
|
}
|
|
|
|
// TestSettingsRegistryGetBoolFallback verifies bool parsing and fallback.
|
|
func TestSettingsRegistryGetBoolFallback(t *testing.T) {
|
|
r := &SettingsRegistry{values: map[string]string{}, q: nil}
|
|
|
|
r.values["auto_scan_enabled"] = "true"
|
|
if !r.AutoScanEnabled() {
|
|
t.Error("expected true")
|
|
}
|
|
|
|
r.values["auto_scan_enabled"] = "garbage"
|
|
// garbage falls back to default ("true")
|
|
if !r.AutoScanEnabled() {
|
|
t.Error("expected fallback to default true")
|
|
}
|
|
}
|
|
|
|
// TestLookupDefaultUnknownKey verifies unknown keys return ok=false.
|
|
func TestLookupDefaultUnknownKey(t *testing.T) {
|
|
if _, ok := LookupDefault("does_not_exist"); ok {
|
|
t.Error("expected ok=false for unknown key")
|
|
}
|
|
if _, ok := LookupDefault("session_duration_seconds"); !ok {
|
|
t.Error("expected ok=true for known key")
|
|
}
|
|
}
|