Shortened configuration struct names from JobSearchConfig to JSC since they are distinguished by being in the config package anyway

This commit is contained in:
bwilliams committed 2026-10-13 16:16:34 +01:00
1 parent 5ec4b65b91
commit be4770cbab
11 files changed
+71 -67

No files matched your search

+8 -8
View File
@@ -5,31 +5,31 @@ import "reflect"
// JSCKDatabase is the database section's configuration key.
const JSCKDatabase string = "database"
// JobSearchConfigDatabase configures the SQLite database. File is the path to
// JSCDatabase configures the SQLite database. File is the path to
// the database file.
type JobSearchConfigDatabase struct {
type JSCDatabase struct {
File string `cfg:"file"`
}
// ---------- Section methods (see Section) ----------
// Keys returns the keys directly in the section.
func (c *JobSearchConfigDatabase) Keys() []string { return keysOf(c) }
func (c *JSCDatabase) Keys() []string { return keysOf(c) }
func (c JobSearchConfigDatabase) Map() map[string]any { return mapOf(c) }
func (c JSCDatabase) Map() map[string]any { return mapOf(c) }
func (c JobSearchConfigDatabase) Flatten() map[string]any {
func (c JSCDatabase) Flatten() map[string]any {
return flattenOf(JSCKDatabase, c)
}
func (c JobSearchConfigDatabase) TypeOf(key string) (reflect.Kind, error) {
func (c JSCDatabase) TypeOf(key string) (reflect.Kind, error) {
return typeOf(c, key)
}
func (c JobSearchConfigDatabase) ValueOf(key string) (any, error) {
func (c JSCDatabase) ValueOf(key string) (any, error) {
return valueOf(c, key)
}
func (c *JobSearchConfigDatabase) SetValue(key string, value any) error {
func (c *JSCDatabase) SetValue(key string, value any) error {
return setValue(c, key, value)
}
+10 -10
View File
@@ -9,40 +9,40 @@ import (
// JSCKLogging is the logging section's configuration key.
const JSCKLogging string = "logging"
// JobSearchConfigLogging configures logging. Level is one of debug, info,
// JSCLogging configures logging. Level is one of debug, info,
// warn or error. File, if set, is where commands that log to a file write.
type JobSearchConfigLogging struct {
type JSCLogging struct {
Level string `cfg:"level" default:"warn"`
File string `cfg:"file"`
}
// ---------- Section methods (see Section) ----------
func (c JobSearchConfigLogging) Map() map[string]any { return mapOf(c) }
func (c JSCLogging) Map() map[string]any { return mapOf(c) }
func (c JobSearchConfigLogging) Flatten() map[string]any {
func (c JSCLogging) Flatten() map[string]any {
return flattenOf(JSCKLogging, c)
}
func (c JobSearchConfigLogging) TypeOf(key string) (reflect.Kind, error) {
func (c JSCLogging) TypeOf(key string) (reflect.Kind, error) {
return typeOf(c, key)
}
func (c JobSearchConfigLogging) ValueOf(key string) (any, error) {
func (c JSCLogging) ValueOf(key string) (any, error) {
return valueOf(c, key)
}
func (c *JobSearchConfigLogging) SetValue(key string, value any) error {
func (c *JSCLogging) SetValue(key string, value any) error {
return setValue(c, key, value)
}
// Keys returns the keys directly in the section.
func (c *JobSearchConfigLogging) Keys() []string { return keysOf(c) }
func (c *JSCLogging) Keys() []string { return keysOf(c) }
// ---------- Section specific methods ----------
// validate checks values before they are stored (see validator).
func (c *JobSearchConfigLogging) validate(key string, value any) error {
func (c *JSCLogging) validate(key string, value any) error {
switch key {
case "level":
switch value.(string) {
@@ -74,6 +74,6 @@ func ConfigLevelToLogLevel(level string) slog.Level {
// LogLevel returns the configured level as an slog level. An unknown level
// gives 99, above every real level, so nothing is logged.
func (c *JobSearchConfigLogging) LogLevel() slog.Level {
func (c *JSCLogging) LogLevel() slog.Level {
return ConfigLevelToLogLevel(c.Level)
}
+14 -10
View File
@@ -62,7 +62,7 @@ func TestDefaults(t *testing.T) {
}
func TestLoggingSection(t *testing.T) {
c := JobSearchConfigLogging{Level: "info", File: "/tmp/x.log"}
c := JSCLogging{Level: "info", File: "/tmp/x.log"}
if got, want := c.Keys(), []string{"level", "file"}; !reflect.DeepEqual(got, want) {
t.Errorf("Keys = %v; want %v", got, want)
@@ -100,7 +100,7 @@ func TestLoggingSection(t *testing.T) {
}
func TestLoggingLevelValidation(t *testing.T) {
var c JobSearchConfigLogging
var c JSCLogging
for _, lvl := range []string{"debug", "info", "warn", "error"} {
if err := c.SetValue("level", lvl); err != nil || c.Level != lvl {
t.Errorf("SetValue(level, %q) = %v, Level = %q", lvl, err, c.Level)
@@ -142,7 +142,7 @@ func TestConfigLevelToLogLevel(t *testing.T) {
if got := ConfigLevelToLogLevel(in); got != want {
t.Errorf("ConfigLevelToLogLevel(%q) = %v; want %v", in, got, want)
}
c := JobSearchConfigLogging{Level: in}
c := JSCLogging{Level: in}
if got := c.LogLevel(); got != want {
t.Errorf("LogLevel() with %q = %v; want %v", in, got, want)
}
@@ -187,9 +187,9 @@ func TestConcreteSourceSections(t *testing.T) {
apiRoot bool
blockShutdown bool
}{
{JSCKSourceFindATender, &JobSearchConfigSourceFindATender{}, true, false},
{JSCKSourceFTSMock, &JobSearchConfigSourceFTSMock{}, true, false},
{JSCKSourceSleeper, &JobSearchConfigSourceSleeper{}, false, true},
{JSCKSourceFindATender, &JSCSourceFindATender{}, true, false},
{JSCKSourceFTSMock, &JSCSourceFTSMock{}, true, false},
{JSCKSourceSleeper, &JSCSourceSleeper{}, false, true},
}
for _, tt := range tests {
t.Run(tt.prefix, func(t *testing.T) {
@@ -252,7 +252,7 @@ func TestConcreteSourceSections(t *testing.T) {
}
func TestSourcesSection(t *testing.T) {
var c JobSearchConfigSources
var c JSCSources
if err := c.SetValue("fts_mock.api_root", "http://mock"); err != nil {
t.Fatalf("SetValue: %v", err)
}
@@ -457,7 +457,7 @@ func TestLoadFromViperInvalidValues(t *testing.T) {
}
func TestDatabaseSection(t *testing.T) {
c := JobSearchConfigDatabase{File: "./jobsearch.db"}
c := JSCDatabase{File: "./jobsearch.db"}
if got, want := c.Keys(), []string{"file"}; !reflect.DeepEqual(got, want) {
t.Errorf("Keys = %v; want %v", got, want)
@@ -501,6 +501,8 @@ func TestViperValue(t *testing.T) {
viper.Set("s", "text")
viper.Set("i", "42") // strings are converted
viper.Set("b", "true")
viper.Set("env_list", "a, b") // e.g. from an environment variable
viper.Set("file_list", []any{"a", "b"}) // e.g. from a YAML list
for _, tt := range []struct {
key string
@@ -510,13 +512,15 @@ func TestViperValue(t *testing.T) {
{"s", reflect.String, "text"},
{"i", reflect.Int, 42},
{"b", reflect.Bool, true},
{"env_list", reflect.Slice, "a, b"}, // split by SetValue
{"file_list", reflect.Slice, []string{"a", "b"}},
} {
got, ok := viperValue(tt.key, tt.kind)
if !ok || got != tt.want {
if !ok || !reflect.DeepEqual(got, tt.want) {
t.Errorf("viperValue(%q, %v) = %#v, %v; want %#v", tt.key, tt.kind, got, ok, tt.want)
}
}
for _, kind := range []reflect.Kind{reflect.Float64, reflect.Int8, reflect.Slice} {
for _, kind := range []reflect.Kind{reflect.Float64, reflect.Int8, reflect.Map} {
if got, ok := viperValue("i", kind); ok {
t.Errorf("viperValue(i, %v) = %#v, true; want unhandled", kind, got)
}
+7 -7
View File
@@ -5,29 +5,29 @@ import "reflect"
// JSCKSourceFindATender is the Find a Tender source's configuration key.
const JSCKSourceFindATender string = "find_a_tender"
// JobSearchConfigSourceFindATender configures fetching from the Find a Tender
// JSCSourceFindATender configures fetching from the Find a Tender
// OCDS API at APIRoot.
type JobSearchConfigSourceFindATender struct {
type JSCSourceFindATender struct {
JobSearchConfigSource
APIRoot string `cfg:"api_root" default:"https://www.find-tender.service.gov.uk/api/1.0"`
}
// ---------- Section methods (see Section) ----------
func (c JobSearchConfigSourceFindATender) Map() map[string]any { return mapOf(c) }
func (c JSCSourceFindATender) Map() map[string]any { return mapOf(c) }
func (c JobSearchConfigSourceFindATender) Flatten() map[string]any {
func (c JSCSourceFindATender) Flatten() map[string]any {
return flattenOf(JSCKSourceFindATender, c)
}
func (c JobSearchConfigSourceFindATender) TypeOf(key string) (reflect.Kind, error) {
func (c JSCSourceFindATender) TypeOf(key string) (reflect.Kind, error) {
return typeOf(c, key)
}
func (c JobSearchConfigSourceFindATender) ValueOf(key string) (any, error) {
func (c JSCSourceFindATender) ValueOf(key string) (any, error) {
return valueOf(c, key)
}
func (c *JobSearchConfigSourceFindATender) SetValue(key string, value any) error {
func (c *JSCSourceFindATender) SetValue(key string, value any) error {
return setValue(c, key, value)
}
+7 -7
View File
@@ -5,29 +5,29 @@ import "reflect"
// JSCKSourceFTSMock is the Find a Tender mock source's configuration key.
const JSCKSourceFTSMock string = "fts_mock"
// JobSearchConfigSourceFTSMock configures fetching from a Find a Tender mock
// JSCSourceFTSMock configures fetching from a Find a Tender mock
// server (cmd/mock-fts) at APIRoot.
type JobSearchConfigSourceFTSMock struct {
type JSCSourceFTSMock struct {
JobSearchConfigSource
APIRoot string `cfg:"api_root"`
}
// ---------- Section methods (see Section) ----------
func (c JobSearchConfigSourceFTSMock) Map() map[string]any { return mapOf(c) }
func (c JSCSourceFTSMock) Map() map[string]any { return mapOf(c) }
func (c JobSearchConfigSourceFTSMock) Flatten() map[string]any {
func (c JSCSourceFTSMock) Flatten() map[string]any {
return flattenOf(JSCKSourceFTSMock, c)
}
func (c JobSearchConfigSourceFTSMock) TypeOf(key string) (reflect.Kind, error) {
func (c JSCSourceFTSMock) TypeOf(key string) (reflect.Kind, error) {
return typeOf(c, key)
}
func (c JobSearchConfigSourceFTSMock) ValueOf(key string) (any, error) {
func (c JSCSourceFTSMock) ValueOf(key string) (any, error) {
return valueOf(c, key)
}
func (c *JobSearchConfigSourceFTSMock) SetValue(key string, value any) error {
func (c *JSCSourceFTSMock) SetValue(key string, value any) error {
return setValue(c, key, value)
}
+7 -7
View File
@@ -5,30 +5,30 @@ import "reflect"
// JSCKSourceSleeper is the sleeper source's configuration key.
const JSCKSourceSleeper string = "sleeper"
// JobSearchConfigSourceSleeper configures the sleeper, a test source that
// JSCSourceSleeper configures the sleeper, a test source that
// simulates work by sleeping. With BlockShutdown its work ignores
// cancellation, to test shutdown waiting on a non-cooperative task.
type JobSearchConfigSourceSleeper struct {
type JSCSourceSleeper struct {
JobSearchConfigSource
BlockShutdown bool `cfg:"block_shutdown"`
}
// ---------- Section methods (see Section) ----------
func (c JobSearchConfigSourceSleeper) Map() map[string]any { return mapOf(c) }
func (c JSCSourceSleeper) Map() map[string]any { return mapOf(c) }
func (c JobSearchConfigSourceSleeper) Flatten() map[string]any {
func (c JSCSourceSleeper) Flatten() map[string]any {
return flattenOf(JSCKSourceSleeper, c)
}
func (c JobSearchConfigSourceSleeper) TypeOf(key string) (reflect.Kind, error) {
func (c JSCSourceSleeper) TypeOf(key string) (reflect.Kind, error) {
return typeOf(c, key)
}
func (c JobSearchConfigSourceSleeper) ValueOf(key string) (any, error) {
func (c JSCSourceSleeper) ValueOf(key string) (any, error) {
return valueOf(c, key)
}
func (c *JobSearchConfigSourceSleeper) SetValue(key string, value any) error {
func (c *JSCSourceSleeper) SetValue(key string, value any) error {
return setValue(c, key, value)
}
+12 -12
View File
@@ -8,35 +8,35 @@ import (
// JSCKSources is the sources section's configuration key.
const JSCKSources string = "sources"
// JobSearchConfigSources configures each source of opportunities, one field
// JSCSources configures each source of opportunities, one field
// per source. Each field's cfg tag must match the section's JSCK* constant.
type JobSearchConfigSources struct {
FindATender JobSearchConfigSourceFindATender `cfg:"find_a_tender"`
FTSMock JobSearchConfigSourceFTSMock `cfg:"fts_mock"`
Sleeper JobSearchConfigSourceSleeper `cfg:"sleeper"`
type JSCSources struct {
FindATender JSCSourceFindATender `cfg:"find_a_tender"`
FTSMock JSCSourceFTSMock `cfg:"fts_mock"`
Sleeper JSCSourceSleeper `cfg:"sleeper"`
}
// ---------- Section methods (see Section) ----------
func (c JobSearchConfigSources) Map() map[string]any { return mapOf(c) }
func (c JSCSources) Map() map[string]any { return mapOf(c) }
func (c JobSearchConfigSources) Flatten() map[string]any {
func (c JSCSources) Flatten() map[string]any {
return flattenOf(JSCKSources, c)
}
func (c JobSearchConfigSources) TypeOf(key string) (reflect.Kind, error) {
func (c JSCSources) TypeOf(key string) (reflect.Kind, error) {
return typeOf(c, key)
}
func (c JobSearchConfigSources) ValueOf(key string) (any, error) {
func (c JSCSources) ValueOf(key string) (any, error) {
return valueOf(c, key)
}
func (c *JobSearchConfigSources) SetValue(key string, value any) error {
func (c *JSCSources) SetValue(key string, value any) error {
return setValue(c, key, value)
}
// ---------- Generic Source definition ----------
// ========== Generic source ==========
// JobSearchConfigSource holds the settings every source has, and is embedded
// in each source's section. Interval is how often an enabled source fetches.
@@ -45,7 +45,7 @@ type JobSearchConfigSource struct {
Interval time.Duration `cfg:"interval" default:"10m"`
}
// ---------- Section methods for Source (see Section) ----------
// ---------- Section methods (see Section) ----------
func (c JobSearchConfigSource) Map() map[string]any { return mapOf(c) }
+3 -3
View File
@@ -24,9 +24,9 @@ const EtcConfigPath string = "/etc/job-search"
// JobSearchConfig is the application's whole configuration, one field per
// section. Each field's cfg tag must match the section's JSCK* constant.
type JobSearchConfig struct {
Logging JobSearchConfigLogging `cfg:"logging"`
Database JobSearchConfigDatabase `cfg:"database"`
Sources JobSearchConfigSources `cfg:"sources"`
Database JSCDatabase `cfg:"database"`
Logging JSCLogging `cfg:"logging"`
Sources JSCSources `cfg:"sources"`
}
// LoadDefaultConfig sets Viper's defaults from the configuration's default
+1 -1
View File
@@ -106,7 +106,7 @@ func TestInitKeepsCommandLineLevel(t *testing.T) {
initDir(t, []string{}, "logging:\n level: info\n")
logs := captureLogs(t, slog.LevelDebug)
conf := JobSearchConfig{Logging: JobSearchConfigLogging{Level: level}}
conf := JobSearchConfig{Logging: JSCLogging{Level: level}}
if err := Init("", &conf); err != nil {
t.Fatal(err)
}