Refactored configuration to make sections less code intensive to add
This commit is contained in:
1 parent
8b0cecb51b
commit
ff33ef082a
4 files changed
+438
-94
No files matched your search
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright © 2026 Craig Williams <craig@avsdev.uk>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package config
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Kinds that LoadFromViper knows how to read.
|
||||
var viperKinds = map[reflect.Kind]bool{
|
||||
reflect.String: true, reflect.Int: true, reflect.Bool: true,
|
||||
}
|
||||
|
||||
// Every key round-trips through TypeOf/ValueOf/SetValue and has a type that
|
||||
// LoadFromViper can read.
|
||||
func TestKeysRoundTrip(t *testing.T) {
|
||||
var conf JobSearchConfig
|
||||
if err := applyDefaults(&conf); err != nil {
|
||||
t.Fatalf("defaults: %v", err)
|
||||
}
|
||||
for key, want := range conf.Flatten() {
|
||||
kind, err := conf.TypeOf(key)
|
||||
if err != nil {
|
||||
t.Errorf("TypeOf(%q): %v", key, err)
|
||||
} else if !viperKinds[kind] {
|
||||
t.Errorf("TypeOf(%q) = %v, which LoadFromViper does not handle", key, kind)
|
||||
}
|
||||
got, err := conf.ValueOf(key)
|
||||
if err != nil || !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("ValueOf(%q) = %#v, %v; want %#v", key, got, err, want)
|
||||
}
|
||||
if err := conf.SetValue(key, got); err != nil {
|
||||
t.Errorf("SetValue(%q, %#v): %v", key, got, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Every section has the full method set, and its Flatten keys (which use the
|
||||
// section's JSCK* constant) line up with its cfg tag in the parent.
|
||||
func TestSections(t *testing.T) {
|
||||
var conf JobSearchConfig
|
||||
all := conf.Flatten()
|
||||
checkSections(t, all, "", reflect.ValueOf(&conf).Elem())
|
||||
}
|
||||
|
||||
func checkSections(t *testing.T, all map[string]any, prefix string, section reflect.Value) {
|
||||
for _, f := range fieldsOf(section.Type()) {
|
||||
if !f.section {
|
||||
continue
|
||||
}
|
||||
fv := section.FieldByIndex(f.index)
|
||||
name := fv.Type().Name()
|
||||
for _, m := range []string{"Map", "Flatten", "TypeOf", "ValueOf", "SetValue"} {
|
||||
if !fv.Addr().MethodByName(m).IsValid() {
|
||||
t.Errorf("%s is missing method %s", name, m)
|
||||
}
|
||||
}
|
||||
if flatten := fv.MethodByName("Flatten"); flatten.IsValid() {
|
||||
keys := flatten.Call(nil)[0].Interface().(map[string]any)
|
||||
for k := range keys {
|
||||
if _, ok := all[joinKey(prefix, k)]; !ok {
|
||||
t.Errorf("%s.Flatten() key %q does not match its cfg tag %q",
|
||||
name, k, joinKey(prefix, f.key))
|
||||
}
|
||||
}
|
||||
}
|
||||
checkSections(t, all, joinKey(prefix, f.key), fv)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user