[🤖] Add Unit-Tests
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m34s

This commit is contained in:
2026-04-27 10:46:08 +02:00
parent dad0e3240d
commit 02d6894ec6
116 changed files with 18795 additions and 1 deletions
+390
View File
@@ -0,0 +1,390 @@
package confext
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"testing"
"time"
)
func TestApplyEnvOverridesPrefix(t *testing.T) {
type testdata struct {
V1 int `env:"V1"`
V2 string `env:"V2"`
}
data := testdata{V1: 1, V2: "x"}
t.Setenv("MYAPP_V1", "42")
t.Setenv("MYAPP_V2", "hello")
t.Setenv("V1", "111")
t.Setenv("V2", "noprefix")
err := ApplyEnvOverrides("MYAPP_", &data, ".")
tst.AssertNoErr(t, err)
tst.AssertEqual(t, data.V1, 42)
tst.AssertEqual(t, data.V2, "hello")
}
func TestApplyEnvOverridesUnexportedFieldsIgnored(t *testing.T) {
type testdata struct {
V1 int `env:"TEST_V1"`
v2 int `env:"TEST_V2"`
}
data := testdata{V1: 1, v2: 2}
t.Setenv("TEST_V1", "11")
t.Setenv("TEST_V2", "22")
err := ApplyEnvOverrides("", &data, ".")
tst.AssertNoErr(t, err)
tst.AssertEqual(t, data.V1, 11)
tst.AssertEqual(t, data.v2, 2)
}
func TestApplyEnvOverridesNoEnvTagIgnored(t *testing.T) {
type testdata struct {
V1 int `env:"TEST_V1"`
V2 int ``
}
data := testdata{V1: 1, V2: 2}
t.Setenv("TEST_V1", "11")
t.Setenv("V2", "22")
err := ApplyEnvOverrides("", &data, ".")
tst.AssertNoErr(t, err)
tst.AssertEqual(t, data.V1, 11)
tst.AssertEqual(t, data.V2, 2)
}
func TestApplyEnvOverridesDashTagIgnored(t *testing.T) {
type testdata struct {
V1 int `env:"TEST_V1"`
V2 string `env:"-"`
}
data := testdata{V1: 1, V2: "no"}
t.Setenv("TEST_V1", "11")
t.Setenv("-", "yes")
err := ApplyEnvOverrides("", &data, ".")
tst.AssertNoErr(t, err)
tst.AssertEqual(t, data.V1, 11)
tst.AssertEqual(t, data.V2, "no")
}
func TestApplyEnvOverridesEnvNotSetKeepsValue(t *testing.T) {
type testdata struct {
V1 int `env:"NOT_SET_INT_KEY_XYZ"`
V2 string `env:"NOT_SET_STR_KEY_XYZ"`
}
data := testdata{V1: 7, V2: "keep"}
err := ApplyEnvOverrides("", &data, ".")
tst.AssertNoErr(t, err)
tst.AssertEqual(t, data.V1, 7)
tst.AssertEqual(t, data.V2, "keep")
}
func TestApplyEnvOverridesBoolVariants(t *testing.T) {
type testdata struct {
B1 bool `env:"B1"`
B2 bool `env:"B2"`
B3 bool `env:"B3"`
B4 bool `env:"B4"`
B5 bool `env:"B5"`
B6 bool `env:"B6"`
}
data := testdata{}
t.Setenv("B1", "true")
t.Setenv("B2", "false")
t.Setenv("B3", "1")
t.Setenv("B4", "0")
t.Setenv("B5", " TRUE ")
t.Setenv("B6", "FaLsE")
err := ApplyEnvOverrides("", &data, ".")
tst.AssertNoErr(t, err)
tst.AssertEqual(t, data.B1, true)
tst.AssertEqual(t, data.B2, false)
tst.AssertEqual(t, data.B3, true)
tst.AssertEqual(t, data.B4, false)
tst.AssertEqual(t, data.B5, true)
tst.AssertEqual(t, data.B6, false)
}
func TestApplyEnvOverridesInvalidIntReturnsError(t *testing.T) {
type testdata struct {
V1 int `env:"BAD_INT"`
}
data := testdata{}
t.Setenv("BAD_INT", "not_a_number")
err := ApplyEnvOverrides("", &data, ".")
if err == nil {
t.Errorf("expected error for invalid int, got nil")
}
}
func TestApplyEnvOverridesInvalidInt8ReturnsError(t *testing.T) {
type testdata struct {
V1 int8 `env:"BAD_INT8"`
}
data := testdata{}
t.Setenv("BAD_INT8", "9999")
err := ApplyEnvOverrides("", &data, ".")
if err == nil {
t.Errorf("expected error for invalid int8, got nil")
}
}
func TestApplyEnvOverridesInvalidInt32ReturnsError(t *testing.T) {
type testdata struct {
V1 int32 `env:"BAD_INT32"`
}
data := testdata{}
t.Setenv("BAD_INT32", "not_an_int32")
err := ApplyEnvOverrides("", &data, ".")
if err == nil {
t.Errorf("expected error for invalid int32, got nil")
}
}
func TestApplyEnvOverridesInvalidInt64ReturnsError(t *testing.T) {
type testdata struct {
V1 int64 `env:"BAD_INT64"`
}
data := testdata{}
t.Setenv("BAD_INT64", "not_an_int64")
err := ApplyEnvOverrides("", &data, ".")
if err == nil {
t.Errorf("expected error for invalid int64, got nil")
}
}
func TestApplyEnvOverridesInvalidDurationReturnsError(t *testing.T) {
type testdata struct {
V1 time.Duration `env:"BAD_DUR"`
}
data := testdata{}
t.Setenv("BAD_DUR", "not_a_duration")
err := ApplyEnvOverrides("", &data, ".")
if err == nil {
t.Errorf("expected error for invalid duration, got nil")
}
}
func TestApplyEnvOverridesInvalidTimeReturnsError(t *testing.T) {
type testdata struct {
V1 time.Time `env:"BAD_TIME"`
}
data := testdata{}
t.Setenv("BAD_TIME", "not_a_time")
err := ApplyEnvOverrides("", &data, ".")
if err == nil {
t.Errorf("expected error for invalid time, got nil")
}
}
func TestApplyEnvOverridesInvalidBoolReturnsError(t *testing.T) {
type testdata struct {
V1 bool `env:"BAD_BOOL"`
}
data := testdata{}
t.Setenv("BAD_BOOL", "yesno")
err := ApplyEnvOverrides("", &data, ".")
if err == nil {
t.Errorf("expected error for invalid bool, got nil")
}
}
func TestApplyEnvOverridesUnsupportedTypeReturnsError(t *testing.T) {
type testdata struct {
V1 []int `env:"UNSUPPORTED"`
}
data := testdata{}
t.Setenv("UNSUPPORTED", "1,2,3")
err := ApplyEnvOverrides("", &data, ".")
if err == nil {
t.Errorf("expected error for unsupported type, got nil")
}
}
func TestApplyEnvOverridesFloatUnsupportedReturnsError(t *testing.T) {
type testdata struct {
V1 float64 `env:"UNSUPPORTED_FLOAT"`
}
data := testdata{}
t.Setenv("UNSUPPORTED_FLOAT", "1.5")
err := ApplyEnvOverrides("", &data, ".")
if err == nil {
t.Errorf("expected error for float64, got nil")
}
}
func TestApplyEnvOverridesPointerInvalidReturnsError(t *testing.T) {
type testdata struct {
V1 *int `env:"PTR_BAD_INT"`
}
data := testdata{}
t.Setenv("PTR_BAD_INT", "not_a_number")
err := ApplyEnvOverrides("", &data, ".")
if err == nil {
t.Errorf("expected error for invalid pointer int, got nil")
}
}
func TestApplyEnvOverridesPointerNotSetStaysNil(t *testing.T) {
type testdata struct {
V1 *int `env:"PTR_NOT_SET_KEY_ABC"`
V2 *string `env:"PTR_NOT_SET_KEY_DEF"`
}
data := testdata{}
err := ApplyEnvOverrides("", &data, ".")
tst.AssertNoErr(t, err)
if data.V1 != nil {
t.Errorf("expected V1 to remain nil, got %v", *data.V1)
}
if data.V2 != nil {
t.Errorf("expected V2 to remain nil, got %v", *data.V2)
}
}
func TestApplyEnvOverridesAliasBool(t *testing.T) {
type aliasbool bool
type testdata struct {
V1 aliasbool `env:"ALIAS_BOOL"`
}
data := testdata{}
t.Setenv("ALIAS_BOOL", "true")
err := ApplyEnvOverrides("", &data, ".")
tst.AssertNoErr(t, err)
tst.AssertEqual(t, data.V1, aliasbool(true))
}
func TestApplyEnvOverridesNestedRecursiveError(t *testing.T) {
type subdata struct {
V1 int `env:"V1"`
}
type testdata struct {
Sub subdata `env:"SUB"`
}
data := testdata{}
t.Setenv("SUB.V1", "not_a_number")
err := ApplyEnvOverrides("", &data, ".")
if err == nil {
t.Errorf("expected error from nested struct invalid value, got nil")
}
}
func TestApplyEnvOverridesTimeFieldInsideStructIsParsed(t *testing.T) {
type testdata struct {
T time.Time `env:"MYTIME"`
}
data := testdata{}
t.Setenv("MYTIME", "2023-01-02T03:04:05Z")
err := ApplyEnvOverrides("", &data, ".")
tst.AssertNoErr(t, err)
tst.AssertEqual(t, data.T.Equal(time.Date(2023, 1, 2, 3, 4, 5, 0, time.UTC)), true)
}
func TestApplyEnvOverridesPointerStringAlias(t *testing.T) {
type aliasstr string
type testdata struct {
V1 *aliasstr `env:"PTR_ALIAS_STR"`
}
data := testdata{}
t.Setenv("PTR_ALIAS_STR", "hello")
err := ApplyEnvOverrides("", &data, ".")
tst.AssertNoErr(t, err)
if data.V1 == nil {
t.Fatalf("expected V1 to be set")
}
tst.AssertEqual(t, *data.V1, aliasstr("hello"))
}
func TestApplyEnvOverridesEmptyEnvTagOnSubstruct(t *testing.T) {
type subdata struct {
V1 int `env:"INNER"`
}
type testdata struct {
Sub subdata `env:""`
}
data := testdata{}
t.Setenv("INNER", "55")
err := ApplyEnvOverrides("PRE_", &data, "_")
tst.AssertNoErr(t, err)
tst.AssertEqual(t, data.Sub.V1, 0)
t.Setenv("PRE_INNER", "77")
err = ApplyEnvOverrides("PRE_", &data, "_")
tst.AssertNoErr(t, err)
tst.AssertEqual(t, data.Sub.V1, 77)
}