This commit is contained in:
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user