golanggohlsrtmpwebrtcmedia-serverobs-studiortcprtmp-proxyrtmp-serverrtprtsprtsp-proxyrtsp-relayrtsp-serversrtstreamingwebrtc-proxy
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
5.8 KiB
205 lines
5.8 KiB
package env |
|
|
|
import ( |
|
"encoding/json" |
|
"testing" |
|
"time" |
|
|
|
"github.com/stretchr/testify/require" |
|
) |
|
|
|
func stringPtr(v string) *string { |
|
return &v |
|
} |
|
|
|
func intPtr(v int) *int { |
|
return &v |
|
} |
|
|
|
func uint64Ptr(v uint64) *uint64 { |
|
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 |
|
} |
|
|
|
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 |
|
} |
|
|
|
// UnmarshalEnv implements env.Unmarshaler. |
|
func (d *myDuration) UnmarshalEnv(_ string, v string) error { |
|
return d.UnmarshalJSON([]byte(`"` + v + `"`)) |
|
} |
|
|
|
type subStruct struct { |
|
MyParam int `json:"myParam"` |
|
} |
|
|
|
type mapEntry struct { |
|
MyValue string `json:"myValue"` |
|
MyStruct subStruct `json:"myStruct"` |
|
} |
|
|
|
type mySubStruct struct { |
|
URL string `json:"url"` |
|
Username string `json:"username"` |
|
Password string `json:"password"` |
|
MyInt2 int `json:"myInt2"` |
|
} |
|
|
|
type testStruct struct { |
|
MyString string `json:"myString"` |
|
MyStringOpt *string `json:"myStringOpt"` |
|
MyInt int `json:"myInt"` |
|
MyIntOpt *int `json:"myIntOpt"` |
|
MyUint uint64 `json:"myUint"` |
|
MyUintOpt *uint64 `json:"myUintOpt"` |
|
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"` |
|
MySliceFloat []float64 `json:"mySliceFloat"` |
|
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"` |
|
} |
|
|
|
func TestLoad(t *testing.T) { |
|
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", |
|
"MYPREFIX_MYSLICEFLOAT": "0.5,0.5", |
|
"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", |
|
} |
|
|
|
for key, val := range env { |
|
t.Setenv(key, val) |
|
} |
|
|
|
var s testStruct |
|
err := Load("MYPREFIX", &s) |
|
require.NoError(t, err) |
|
|
|
require.Equal(t, testStruct{ |
|
MyString: "testcontent", |
|
MyStringOpt: stringPtr("testcontent2"), |
|
MyInt: 123, |
|
MyIntOpt: intPtr(456), |
|
MyUint: 8910, |
|
MyUintOpt: uint64Ptr(112313), |
|
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, |
|
}, |
|
}, |
|
}, |
|
MySliceFloat: []float64{0.5, 0.5}, |
|
MySliceString: []string{ |
|
"val1", |
|
"val2", |
|
}, |
|
MySliceStringEmpty: []string{}, |
|
MySliceStringOpt: &[]string{"aa"}, |
|
MySliceSubStruct: []mySubStruct{ |
|
{ |
|
URL: "url1", |
|
Username: "user1", |
|
Password: "pass1", |
|
}, |
|
{ |
|
URL: "url2", |
|
Username: "", |
|
Password: "pass2", |
|
}, |
|
}, |
|
MySliceSubStructEmpty: []mySubStruct{}, |
|
}, s) |
|
} |
|
|
|
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") |
|
|
|
f.Fuzz(func(_ *testing.T, key string, val string) { |
|
env := map[string]string{ |
|
key: val, |
|
} |
|
|
|
var s testStruct |
|
loadWithEnv(env, "MYPREFIX", &s) //nolint:errcheck |
|
}) |
|
}
|
|
|