Skip to content

Commit 4de0b0e

Browse files
committed
test(config): add tests for non-primitive and named types
Add comprehensive test coverage for reviewer feedback: 1. Non-primitive field handling - validates descriptive errors when attempting to set slice/map fields 2. Named type support - verifies SetString/SetInt/SetBool work correctly with named types (e.g., type LogLevel string) Tests use mock struct with named int/bool types since actual config only has named string (LogLevel).
1 parent d5e2332 commit 4de0b0e

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

pkg/config/setter_test.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,3 +302,109 @@ func TestFindFieldByTagWithMeta_NonStructValue(t *testing.T) {
302302
})
303303
}
304304
}
305+
306+
func TestSetConfigValue_NonPrimitiveFields(t *testing.T) {
307+
// Test that attempting to set non-primitive types returns descriptive errors
308+
tests := []struct {
309+
name string
310+
path string
311+
value string
312+
expectedError string
313+
}{
314+
{
315+
name: "slice field",
316+
path: "experimental",
317+
value: "value",
318+
expectedError: "unsupported type slice",
319+
},
320+
{
321+
name: "slice of structs",
322+
path: "storage",
323+
value: "value",
324+
expectedError: "unsupported type slice",
325+
},
326+
{
327+
name: "map field",
328+
path: "telemetry.headers",
329+
value: "value",
330+
expectedError: "unsupported type map",
331+
},
332+
}
333+
334+
for _, tt := range tests {
335+
t.Run(tt.name, func(t *testing.T) {
336+
data := &Data{}
337+
err := SetConfigValue(data, tt.path, tt.value)
338+
require.Error(t, err)
339+
assert.Contains(t, err.Error(), tt.expectedError)
340+
})
341+
}
342+
}
343+
344+
// Test types for named type validation
345+
type testNamedString string
346+
type testNamedInt int
347+
type testNamedBool bool
348+
349+
type testNamedStruct struct {
350+
StringField testNamedString `toml:"string-field" yaml:"string-field" json:"string-field"`
351+
IntField testNamedInt `toml:"int-field" yaml:"int-field" json:"int-field"`
352+
BoolField testNamedBool `toml:"bool-field" yaml:"bool-field" json:"bool-field"`
353+
}
354+
355+
func TestSetConfigValue_NamedTypes(t *testing.T) {
356+
// Test that SetString/SetInt/SetBool work correctly with named types
357+
// This validates that reflection-based setters work on named types, not just primitives
358+
tests := []struct {
359+
name string
360+
path string
361+
value string
362+
validate func(*testing.T, *testNamedStruct)
363+
}{
364+
{
365+
name: "named string type",
366+
path: "string-field",
367+
value: "test-value",
368+
validate: func(t *testing.T, d *testNamedStruct) {
369+
assert.Equal(t, testNamedString("test-value"), d.StringField)
370+
assert.IsType(t, testNamedString(""), d.StringField)
371+
},
372+
},
373+
{
374+
name: "named int type",
375+
path: "int-field",
376+
value: "42",
377+
validate: func(t *testing.T, d *testNamedStruct) {
378+
assert.Equal(t, testNamedInt(42), d.IntField)
379+
assert.IsType(t, testNamedInt(0), d.IntField)
380+
},
381+
},
382+
{
383+
name: "named bool type",
384+
path: "bool-field",
385+
value: "true",
386+
validate: func(t *testing.T, d *testNamedStruct) {
387+
assert.Equal(t, testNamedBool(true), d.BoolField)
388+
assert.IsType(t, testNamedBool(false), d.BoolField)
389+
},
390+
},
391+
}
392+
393+
for _, tt := range tests {
394+
t.Run(tt.name, func(t *testing.T) {
395+
data := &testNamedStruct{}
396+
err := setFieldByPath(reflect.ValueOf(data).Elem(), []string{tt.path}, tt.value)
397+
require.NoError(t, err)
398+
tt.validate(t, data)
399+
})
400+
}
401+
}
402+
403+
func TestSetConfigValue_NamedTypes_RealConfig(t *testing.T) {
404+
// Test named types in actual config (LogLevel)
405+
data := &Data{}
406+
err := SetConfigValue(data, "logs.level", "debug")
407+
require.NoError(t, err)
408+
assert.Equal(t, LogLevel("debug"), data.Logs.Level)
409+
assert.IsType(t, LogLevel(""), data.Logs.Level)
410+
}

0 commit comments

Comments
 (0)