Skip to content

Commit

Permalink
switch how to hook different lookup to simple function instead of int…
Browse files Browse the repository at this point in the history
…erface, also fix bug found when using the mock in test (recurse was using the os version)
  • Loading branch information
ldemailly committed Nov 7, 2023
1 parent a4e5e62 commit cf32bf5
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 36 deletions.
19 changes: 4 additions & 15 deletions env.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ func setPointer(fieldValue reflect.Value) reflect.Value {
}

func checkEnv(envLookup EnvLookup, envName, fieldName string, fieldValue reflect.Value) (*string, error) {
val, found := envLookup.LookupEnv(envName)
val, found := envLookup(envName)
if !found {
// log.LogVf("%q not set for %s", envName, fieldName)
return nil, nil //nolint:nilnil
Expand All @@ -267,22 +267,11 @@ func checkEnv(envLookup EnvLookup, envName, fieldName string, fieldValue reflect
return &val, nil
}

// EnvLookup defines the interface for looking up environment variables.
type EnvLookup interface {
LookupEnv(key string) (string, bool)
}

// DefaultEnvLookup implements the EnvLookup interface using the os package.
type DefaultEnvLookup struct{}

// LookupEnv for DefaultEnvLookup uses the os.LookupEnv function.
func (DefaultEnvLookup) LookupEnv(key string) (string, bool) {
return os.LookupEnv(key)
}
type EnvLookup func(key string) (string, bool)

// Reverse of StructToEnvVars, assumes the same encoding. Using the current os environment variables as source.
func SetFromEnv(prefix string, s interface{}) []error {
return SetFrom(DefaultEnvLookup{}, prefix, s)
return SetFrom(os.LookupEnv, prefix, s)

Check warning on line 274 in env.go

View check run for this annotation

Codecov / codecov/patch

env.go#L274

Added line #L274 was not covered by tests
}

// Reverse of StructToEnvVars, assumes the same encoding. Using passed it lookup object that can lookup values by keys.
Expand Down Expand Up @@ -321,7 +310,7 @@ func setFromEnv(allErrors []error, envLookup EnvLookup, prefix string, s interfa
if kind == reflect.Struct {
// Recurse with prefix
if fieldValue.CanAddr() { // Check if we can get the address
SetFromEnv(envName+"_", fieldValue.Addr().Interface())
allErrors = setFromEnv(allErrors, envLookup, envName+"_", fieldValue.Addr().Interface())
} else {
err := fmt.Errorf("cannot take the address of %s to recurse", fieldType.Name)
allErrors = append(allErrors, err)
Expand Down
43 changes: 22 additions & 21 deletions env_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package struct2env

import (
"os"
"reflect"
"strings"
"testing"
Expand Down Expand Up @@ -200,31 +199,33 @@ export TST_FOO TST_BAR TST_A_SPECIAL_BLAH TST_A_BOOL TST_HTTP_SERVER TST_INT_POI

func TestSetFromEnv(t *testing.T) {
foo := FooConfig{}
envs := []struct {
k string
v string
}{
{"TST2_FOO", "another\nfoo"},
{"TST2_BAR", "bar"},
{"TST2_RECURSE_HERE_INNER_B", "in1"},
{"TST2_A_SPECIAL_BLAH", "31"},
{"TST2_A_BOOL", "1"},
{"TST2_FLOAT_POINTER", "5.75"},
{"TST2_INT_POINTER", "73"},
{"TST2_SOME_BINARY", "QUJDAERFRg=="},
}
for _, e := range envs {
os.Setenv(e.k, e.v)
}
errors := SetFromEnv("TST2_", &foo)
envs := map[string]string{
"TST2_FOO": "another\nfoo",
"TST2_BAR": "bar",
"TST2_RECURSE_HERE_INNER_B": "in1",
"TST2_A_SPECIAL_BLAH": "31",
"TST2_A_BOOL": "1",
"TST2_FLOAT_POINTER": "5.75",
"TST2_INT_POINTER": "73",
"TST2_SOME_BINARY": "QUJDAERFRg==",
}
lookup := func(key string) (string, bool) {
value, found := envs[key]
return value, found
}
errors := SetFrom(lookup, "TST2_", &foo)
if len(errors) != 0 {
t.Errorf("Unexpectedly got errors :%v", errors)
}
if foo.Foo != "another\nfoo" || foo.Bar != "bar" || foo.RecurseHere.InnerB != "in1" || foo.Blah != 31 || foo.ABool != true ||
foo.FloatPointer == nil || *foo.FloatPointer != 5.75 ||
foo.IntPointer == nil || *foo.IntPointer != 73 {
if foo.Foo != "another\nfoo" || foo.Bar != "bar" || foo.RecurseHere.InnerB != "in1" || foo.Blah != 31 || foo.ABool != true {
t.Errorf("Mismatch in object values, got: %+v", foo)
}
if foo.IntPointer == nil || *foo.IntPointer != 73 {
t.Errorf("IntPointer not set correctly: %v %v", foo.IntPointer, *foo.IntPointer)
}
if foo.FloatPointer == nil || *foo.FloatPointer != 5.75 {
t.Errorf("FloatPointer not set correctly: %v %v", foo.FloatPointer, *foo.FloatPointer)
}
if string(foo.SomeBinary) != "ABC\x00DEF" {
t.Errorf("Base64 decoding not working for []byte field: %q", string(foo.SomeBinary))
}
Expand Down

0 comments on commit cf32bf5

Please sign in to comment.