package envs import ( `errors` `os` `testing` `time` `github.com/davecgh/go-spew/spew` `r00t2.io/sysutils/errs` ) type ( testCustom string testStruct struct { Hello string `envpop:"USER"` HelloPtr *string `envpop:"USER"` HelloForce string `envpop:"USER,force"` HelloPtrForce *string `envpop:"USER,force"` HelloNo string `envsub:"-" envpop:"-"` HelloNoPtr *string `envsub:"-" envpop:"-"` BadType int NilField *string `envpop:"NONEXISTENTBADVAR,allow_empty"` PtrInt *int Custom testCustom MapStr map[string]string SliceStr []string SliceSlice [][]string SliceMap []map[string]string SliceStruct []testStruct } ) func TestInterpolateString(t *testing.T) { var err error var s string = "My username is ${USER}; hello!" var sp *string = &s if err = InterpolateString(&s); err != nil { t.Fatalf("Failed interpolation: %v", err) } t.Logf("String test passed:\n%v", s) if err = InterpolateString(sp); err != nil { t.Fatalf("Failed interpolation: %v", err) } t.Logf("String pointer test passed:\n%v", *sp) } func TestInterpolateStruct(t *testing.T) { var err error for _, i := range []interface{}{ "i am ${USER}, it is ${CURDATETIME}", new(string), /* testStruct{ Hello: "i am ${USER}, it is ${CURDATETIME}", HelloPtr: new(string), HelloForce: "i am ${USER}, it is ${CURDATETIME}", HelloPtrForce: new(string), HelloNo: "i am ${USER}, it is ${CURDATETIME}", HelloNoPtr: new(string), BadType: 4, NilField: nil, PtrInt: new(int), Custom: testCustom("i am ${USER}, it is ${CURDATETIME}"), SliceStr: []string{"i am ${USER}, it is ${CURDATETIME}"}, SliceSlice: [][]string{[]string{"i am ${USER}, it is ${CURDATETIME}"}}, SliceMap: []map[string]string{map[string]string{"i am ${USER} key": "i am ${USER} value, it is ${CURDATETIME}"}}, SliceStruct: []testStruct{ { Hello: "i am nested ${USER}, it is ${CURDATETIME}", HelloPtr: nil, HelloForce: "i am nested ${USER}, it is ${CURDATETIME}", HelloPtrForce: nil, HelloNo: "i am nested ${USER}, it is ${CURDATETIME}", HelloNoPtr: nil, BadType: 0, NilField: nil, PtrInt: nil, Custom: testCustom("i am nested ${USER}, it is ${CURDATETIME}"), SliceStr: []string{"i am nested ${USER}, it is ${CURDATETIME}"}, SliceSlice: [][]string{[]string{"i am nested ${USER}, it is ${CURDATETIME}"}}, SliceMap: []map[string]string{map[string]string{"i am nested ${USER} key": "i am ${USER} value, it is ${CURDATETIME}"}}, SliceStruct: nil, }, }, }, */ &testStruct{ Hello: "i am ${USER}, it is ${CURDATETIME}", HelloPtr: new(string), HelloForce: "i am ${USER}, it is ${CURDATETIME}", HelloPtrForce: new(string), HelloNo: "i am ${USER}, it is ${CURDATETIME}", HelloNoPtr: new(string), BadType: 4, NilField: nil, PtrInt: new(int), Custom: testCustom("i am ${USER}, it is ${CURDATETIME}"), MapStr: map[string]string{"i am ${USER} key": "i am ${USER} value, it is ${CURDATETIME}"}, SliceStr: []string{"i am ${USER}, it is ${CURDATETIME}"}, SliceSlice: [][]string{[]string{"i am ${USER}, it is ${CURDATETIME}"}}, SliceMap: []map[string]string{map[string]string{"i am ${USER} key": "i am ${USER} value, it is ${CURDATETIME}"}}, SliceStruct: []testStruct{ { Hello: "i am nested ${USER}, it is ${CURDATETIME}", HelloPtr: nil, HelloForce: "i am nested ${USER}, it is ${CURDATETIME}", HelloPtrForce: nil, HelloNo: "i am nested ${USER}, it is ${CURDATETIME}", HelloNoPtr: nil, BadType: 0, NilField: nil, PtrInt: nil, Custom: testCustom("i am nested ${USER}, it is ${CURDATETIME}"), SliceStr: []string{"i am nested ${USER}, it is ${CURDATETIME}"}, SliceSlice: [][]string{[]string{"i am nested ${USER}, it is ${CURDATETIME}"}}, SliceMap: []map[string]string{map[string]string{"i am nested ${USER} key": "i am ${USER} value, it is ${CURDATETIME}"}}, SliceStruct: nil, }, }, }, } { if err = os.Setenv("CURDATETIME", time.Now().String()); err != nil { t.Fatalf("Received error setting CURDATETIME: %v", err) } switch x := i.(type) { case *string: *x = "i am ${USER}, it is ${CURDATETIME}" case testStruct: *x.HelloPtr = x.Hello *x.HelloPtrForce = x.HelloForce *x.HelloNoPtr = x.HelloNo *x.PtrInt = x.BadType case *testStruct: *x.HelloPtr = x.Hello *x.HelloPtrForce = x.HelloForce *x.HelloNoPtr = x.HelloNo *x.PtrInt = x.BadType } t.Logf("Before (%T):\n%v", i, spew.Sdump(i)) if err = Interpolate(i); err != nil { t.Fatalf("Failed interpolation: %v", err) } t.Logf("After (%T):\n%v\n", i, spew.Sdump(i)) } } func TestPopulateStruct(t *testing.T) { var err error var greet string = "My username is ${USER}; hello!" var num int = 4 var sp *testStruct = &testStruct{ Hello: greet, HelloPtr: &greet, HelloForce: greet, HelloPtrForce: &greet, HelloNo: greet, HelloNoPtr: &greet, BadType: 4, PtrInt: &num, } if err = PopulateStruct(sp); err != nil { if errors.Is(err, errs.ErrNilPtr) { err = nil t.Logf("Detected nil.") } else if errors.Is(err, errs.ErrBadType) { err = nil t.Log("Detected bad type.") } else { t.Fatalf("Failed interpolation: %v", err) } } t.Logf("Evaluated:\n%v", spew.Sdump(sp)) }