2023-05-06 21:00:42 +00:00
|
|
|
package env
|
2021-05-09 15:51:38 +00:00
|
|
|
|
|
|
|
import (
|
2023-05-06 21:00:42 +00:00
|
|
|
"encoding/json"
|
2021-05-09 15:51:38 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
2023-10-23 18:07:28 +00:00
|
|
|
func stringPtr(v string) *string {
|
|
|
|
return &v
|
2022-08-15 15:37:49 +00:00
|
|
|
}
|
|
|
|
|
2023-10-23 18:07:28 +00:00
|
|
|
func intPtr(v int) *int {
|
|
|
|
return &v
|
|
|
|
}
|
|
|
|
|
2024-08-20 22:08:54 +00:00
|
|
|
func uintPtr(v uint) *uint {
|
2023-10-23 18:07:28 +00:00
|
|
|
return &v
|
|
|
|
}
|
|
|
|
|
|
|
|
func boolPtr(v bool) *bool {
|
|
|
|
return &v
|
|
|
|
}
|
|
|
|
|
|
|
|
func float64Ptr(v float64) *float64 {
|
|
|
|
return &v
|
|
|
|
}
|
|
|
|
|
|
|
|
func durationPtr(v time.Duration) *time.Duration {
|
|
|
|
return &v
|
2021-05-09 15:51:38 +00:00
|
|
|
}
|
|
|
|
|
2023-05-06 21:00:42 +00:00
|
|
|
type myDuration time.Duration
|
|
|
|
|
|
|
|
func (d *myDuration) UnmarshalJSON(b []byte) error {
|
|
|
|
var in string
|
|
|
|
if err := json.Unmarshal(b, &in); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
du, err := time.ParseDuration(in)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
*d = myDuration(du)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-10-07 21:32:15 +00:00
|
|
|
// UnmarshalEnv implements env.Unmarshaler.
|
|
|
|
func (d *myDuration) UnmarshalEnv(_ string, v string) error {
|
|
|
|
return d.UnmarshalJSON([]byte(`"` + v + `"`))
|
2023-05-06 21:00:42 +00:00
|
|
|
}
|
|
|
|
|
2023-10-23 18:07:28 +00:00
|
|
|
type subStruct struct {
|
|
|
|
MyParam int `json:"myParam"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type mapEntry struct {
|
|
|
|
MyValue string `json:"myValue"`
|
|
|
|
MyStruct subStruct `json:"myStruct"`
|
|
|
|
}
|
|
|
|
|
2023-06-30 14:47:10 +00:00
|
|
|
type mySubStruct struct {
|
2023-10-07 21:32:15 +00:00
|
|
|
URL string `json:"url"`
|
|
|
|
Username string `json:"username"`
|
|
|
|
Password string `json:"password"`
|
2023-10-23 18:07:28 +00:00
|
|
|
MyInt2 int `json:"myInt2"`
|
2023-06-30 14:47:10 +00:00
|
|
|
}
|
|
|
|
|
2021-05-09 15:51:38 +00:00
|
|
|
type testStruct struct {
|
2023-10-23 18:07:28 +00:00
|
|
|
MyString string `json:"myString"`
|
|
|
|
MyStringOpt *string `json:"myStringOpt"`
|
|
|
|
MyInt int `json:"myInt"`
|
|
|
|
MyIntOpt *int `json:"myIntOpt"`
|
2024-08-20 22:08:54 +00:00
|
|
|
MyUint uint `json:"myUint"`
|
|
|
|
MyUintOpt *uint `json:"myUintOpt"`
|
2023-10-23 18:07:28 +00:00
|
|
|
MyFloat float64 `json:"myFloat"`
|
|
|
|
MyFloatOpt *float64 `json:"myFloatOpt"`
|
|
|
|
MyBool bool `json:"myBool"`
|
|
|
|
MyBoolOpt *bool `json:"myBoolOpt"`
|
|
|
|
MyDuration myDuration `json:"myDuration"`
|
|
|
|
MyDurationOpt *myDuration `json:"myDurationOpt"`
|
|
|
|
MyDurationOptUnset *myDuration `json:"myDurationOptUnset"`
|
|
|
|
MyMap map[string]*mapEntry `json:"myMap"`
|
2024-01-28 20:48:21 +00:00
|
|
|
MySliceFloat []float64 `json:"mySliceFloat"`
|
2023-10-23 18:07:28 +00:00
|
|
|
MySliceString []string `json:"mySliceString"`
|
|
|
|
MySliceStringEmpty []string `json:"mySliceStringEmpty"`
|
|
|
|
MySliceStringOpt *[]string `json:"mySliceStringOpt"`
|
|
|
|
MySliceStringOptUnset *[]string `json:"mySliceStringOptUnset"`
|
|
|
|
MySliceSubStruct []mySubStruct `json:"mySliceSubStruct"`
|
|
|
|
MySliceSubStructEmpty []mySubStruct `json:"mySliceSubStructEmpty"`
|
|
|
|
MySliceSubStructOpt *[]mySubStruct `json:"mySliceSubStructOpt"`
|
|
|
|
MySliceSubStructOptUnset *[]mySubStruct `json:"mySliceSubStructOptUnset"`
|
|
|
|
Unset *bool `json:"unset"`
|
2021-05-09 15:51:38 +00:00
|
|
|
}
|
|
|
|
|
2023-05-06 21:00:42 +00:00
|
|
|
func TestLoad(t *testing.T) {
|
2023-10-23 18:07:28 +00:00
|
|
|
env := map[string]string{
|
|
|
|
"MYPREFIX_MYSTRING": "testcontent",
|
|
|
|
"MYPREFIX_MYSTRINGOPT": "testcontent2",
|
|
|
|
"MYPREFIX_MYINT": "123",
|
|
|
|
"MYPREFIX_MYINTOPT": "456",
|
|
|
|
"MYPREFIX_MYUINT": "8910",
|
|
|
|
"MYPREFIX_MYUINTOPT": "112313",
|
|
|
|
"MYPREFIX_MYFLOAT": "15.2",
|
|
|
|
"MYPREFIX_MYFLOATOPT": "16.2",
|
|
|
|
"MYPREFIX_MYBOOL": "yes",
|
|
|
|
"MYPREFIX_MYBOOLOPT": "false",
|
|
|
|
"MYPREFIX_MYDURATION": "22s",
|
|
|
|
"MYPREFIX_MYDURATIONOPT": "30s",
|
|
|
|
"MYPREFIX_MYMAP_MYKEY": "",
|
|
|
|
"MYPREFIX_MYMAP_MYKEY2_MYVALUE": "asd",
|
|
|
|
"MYPREFIX_MYMAP_MYKEY2_MYSTRUCT_MYPARAM": "456",
|
2024-01-28 20:48:21 +00:00
|
|
|
"MYPREFIX_MYSLICEFLOAT": "0.5,0.5",
|
2023-10-23 18:07:28 +00:00
|
|
|
"MYPREFIX_MYSLICESTRING": "val1,val2",
|
|
|
|
"MYPREFIX_MYSLICESTRINGEMPTY": "",
|
|
|
|
"MYPREFIX_MYSLICESTRINGOPT": "aa",
|
|
|
|
"MYPREFIX_MYSLICESUBSTRUCT_0_URL": "url1",
|
|
|
|
"MYPREFIX_MYSLICESUBSTRUCT_0_USERNAME": "user1",
|
|
|
|
"MYPREFIX_MYSLICESUBSTRUCT_0_PASSWORD": "pass1",
|
|
|
|
"MYPREFIX_MYSLICESUBSTRUCT_1_URL": "url2",
|
|
|
|
"MYPREFIX_MYSLICESUBSTRUCT_1_PASSWORD": "pass2",
|
|
|
|
"MYPREFIX_MYSLICESUBSTRUCTEMPTY": "",
|
|
|
|
"MYPREFIX_MYSLICESUBSTRUCTOPT_1_PASSWORD": "pwd",
|
|
|
|
}
|
2023-06-30 14:47:10 +00:00
|
|
|
|
2023-10-23 18:07:28 +00:00
|
|
|
for key, val := range env {
|
2023-11-20 16:34:56 +00:00
|
|
|
t.Setenv(key, val)
|
2023-10-23 18:07:28 +00:00
|
|
|
}
|
2023-07-16 22:12:05 +00:00
|
|
|
|
2021-05-09 15:51:38 +00:00
|
|
|
var s testStruct
|
2023-05-06 21:00:42 +00:00
|
|
|
err := Load("MYPREFIX", &s)
|
2021-05-09 15:51:38 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-10-23 18:07:28 +00:00
|
|
|
require.Equal(t, testStruct{
|
|
|
|
MyString: "testcontent",
|
|
|
|
MyStringOpt: stringPtr("testcontent2"),
|
|
|
|
MyInt: 123,
|
|
|
|
MyIntOpt: intPtr(456),
|
|
|
|
MyUint: 8910,
|
2024-08-20 22:08:54 +00:00
|
|
|
MyUintOpt: uintPtr(112313),
|
2023-10-23 18:07:28 +00:00
|
|
|
MyFloat: 15.2,
|
|
|
|
MyFloatOpt: float64Ptr(16.2),
|
|
|
|
MyBool: true,
|
|
|
|
MyBoolOpt: boolPtr(false),
|
|
|
|
MyDuration: 22000000000,
|
|
|
|
MyDurationOpt: (*myDuration)(durationPtr(30000000000)),
|
|
|
|
MyMap: map[string]*mapEntry{
|
|
|
|
"mykey": {
|
|
|
|
MyValue: "",
|
|
|
|
MyStruct: subStruct{
|
|
|
|
MyParam: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"mykey2": {
|
|
|
|
MyValue: "asd",
|
|
|
|
MyStruct: subStruct{
|
|
|
|
MyParam: 456,
|
|
|
|
},
|
|
|
|
},
|
2023-06-30 14:47:10 +00:00
|
|
|
},
|
2024-01-28 20:48:21 +00:00
|
|
|
MySliceFloat: []float64{0.5, 0.5},
|
2023-10-23 18:07:28 +00:00
|
|
|
MySliceString: []string{
|
|
|
|
"val1",
|
|
|
|
"val2",
|
2023-06-30 14:47:10 +00:00
|
|
|
},
|
2023-10-23 18:07:28 +00:00
|
|
|
MySliceStringEmpty: []string{},
|
|
|
|
MySliceStringOpt: &[]string{"aa"},
|
|
|
|
MySliceSubStruct: []mySubStruct{
|
|
|
|
{
|
|
|
|
URL: "url1",
|
|
|
|
Username: "user1",
|
|
|
|
Password: "pass1",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
URL: "url2",
|
|
|
|
Username: "",
|
|
|
|
Password: "pass2",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
MySliceSubStructEmpty: []mySubStruct{},
|
|
|
|
}, s)
|
|
|
|
}
|
2023-07-16 22:12:05 +00:00
|
|
|
|
2023-10-23 18:07:28 +00:00
|
|
|
func FuzzLoad(f *testing.F) {
|
|
|
|
f.Add("MYPREFIX_MYINT", "a")
|
|
|
|
f.Add("MYPREFIX_MYUINT", "a")
|
|
|
|
f.Add("MYPREFIX_MYFLOAT", "a")
|
|
|
|
f.Add("MYPREFIX_MYBOOL", "a")
|
|
|
|
f.Add("MYPREFIX_MYSLICESUBSTRUCT_0_MYINT2", "a")
|
|
|
|
f.Add("MYPREFIX_MYDURATION", "a")
|
|
|
|
f.Add("MYPREFIX_MYDURATION_A", "a")
|
|
|
|
|
2024-03-19 11:53:26 +00:00
|
|
|
f.Fuzz(func(_ *testing.T, key string, val string) {
|
2023-10-23 18:07:28 +00:00
|
|
|
env := map[string]string{
|
|
|
|
key: val,
|
|
|
|
}
|
|
|
|
|
|
|
|
var s testStruct
|
|
|
|
loadWithEnv(env, "MYPREFIX", &s) //nolint:errcheck
|
|
|
|
})
|
2021-05-09 15:51:38 +00:00
|
|
|
}
|