feat: validate value in options for mapping (#2616)

master
Kevin Wan 2 years ago committed by GitHub
parent 79de932646
commit 06fafd2153
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -341,6 +341,10 @@ func (u *Unmarshaler) processFieldTextUnmarshaler(field reflect.StructField, val
func (u *Unmarshaler) processFieldWithEnvValue(field reflect.StructField, value reflect.Value,
envVal string, opts *fieldOptionsWithContext, fullName string) error {
if err := validateValueInOptions(envVal, opts.options()); err != nil {
return err
}
fieldKind := field.Type.Kind()
switch fieldKind {
case reflect.Bool:

@ -3254,91 +3254,85 @@ func TestUnmarshal_EnvDurationBadValue(t *testing.T) {
assert.NotNil(t, UnmarshalKey(emptyMap, &v))
}
func BenchmarkUnmarshalString(b *testing.B) {
type inner struct {
Value string `key:"value"`
}
m := map[string]interface{}{
"value": "first",
func TestUnmarshal_EnvWithOptions(t *testing.T) {
type Value struct {
Name string `key:"name,env=TEST_NAME_ENV_OPTIONS_MATCH,options=[abc,123,xyz]"`
}
for i := 0; i < b.N; i++ {
var in inner
if err := UnmarshalKey(m, &in); err != nil {
b.Fatal(err)
}
}
}
const (
envName = "TEST_NAME_ENV_OPTIONS_MATCH"
envVal = "123"
)
os.Setenv(envName, envVal)
defer os.Unsetenv(envName)
func BenchmarkUnmarshalStruct(b *testing.B) {
b.ReportAllocs()
var v Value
assert.NoError(t, UnmarshalKey(emptyMap, &v))
assert.Equal(t, envVal, v.Name)
}
m := map[string]interface{}{
"Ids": []map[string]interface{}{
{
"First": 1,
"Second": 2,
},
},
func TestUnmarshal_EnvWithOptionsWrongValueBool(t *testing.T) {
type Value struct {
Enable bool `key:"enable,env=TEST_NAME_ENV_OPTIONS_BOOL,options=[true]"`
}
for i := 0; i < b.N; i++ {
var v struct {
Ids []struct {
First int
Second int
}
}
if err := UnmarshalKey(m, &v); err != nil {
b.Fatal(err)
}
}
const (
envName = "TEST_NAME_ENV_OPTIONS_BOOL"
envVal = "false"
)
os.Setenv(envName, envVal)
defer os.Unsetenv(envName)
var v Value
assert.Error(t, UnmarshalKey(emptyMap, &v))
}
func BenchmarkMapToStruct(b *testing.B) {
data := map[string]interface{}{
"valid": "1",
"age": "5",
"name": "liao",
}
type anonymous struct {
Valid bool
Age int
Name string
func TestUnmarshal_EnvWithOptionsWrongValueDuration(t *testing.T) {
type Value struct {
Duration time.Duration `key:"duration,env=TEST_NAME_ENV_OPTIONS_DURATION,options=[1s,2s,3s]"`
}
for i := 0; i < b.N; i++ {
var an anonymous
if valid, ok := data["valid"]; ok {
an.Valid = valid == "1"
}
if age, ok := data["age"]; ok {
ages, _ := age.(string)
an.Age, _ = strconv.Atoi(ages)
}
if name, ok := data["name"]; ok {
names, _ := name.(string)
an.Name = names
}
}
const (
envName = "TEST_NAME_ENV_OPTIONS_DURATION"
envVal = "4s"
)
os.Setenv(envName, envVal)
defer os.Unsetenv(envName)
var v Value
assert.Error(t, UnmarshalKey(emptyMap, &v))
}
func BenchmarkUnmarshal(b *testing.B) {
data := map[string]interface{}{
"valid": "1",
"age": "5",
"name": "liao",
}
type anonymous struct {
Valid bool `key:"valid,string"`
Age int `key:"age,string"`
Name string `key:"name"`
func TestUnmarshal_EnvWithOptionsWrongValueNumber(t *testing.T) {
type Value struct {
Age int `key:"age,env=TEST_NAME_ENV_OPTIONS_AGE,options=[18,19,20]"`
}
for i := 0; i < b.N; i++ {
var an anonymous
UnmarshalKey(data, &an)
const (
envName = "TEST_NAME_ENV_OPTIONS_AGE"
envVal = "30"
)
os.Setenv(envName, envVal)
defer os.Unsetenv(envName)
var v Value
assert.Error(t, UnmarshalKey(emptyMap, &v))
}
func TestUnmarshal_EnvWithOptionsWrongValueString(t *testing.T) {
type Value struct {
Name string `key:"name,env=TEST_NAME_ENV_OPTIONS_STRING,options=[abc,123,xyz]"`
}
const (
envName = "TEST_NAME_ENV_OPTIONS_STRING"
envVal = "this is a name"
)
os.Setenv(envName, envVal)
defer os.Unsetenv(envName)
var v Value
assert.Error(t, UnmarshalKey(emptyMap, &v))
}
func TestUnmarshalJsonReaderMultiArray(t *testing.T) {
@ -3581,3 +3575,90 @@ func BenchmarkDefaultValue(b *testing.B) {
}
}
}
func BenchmarkUnmarshalString(b *testing.B) {
type inner struct {
Value string `key:"value"`
}
m := map[string]interface{}{
"value": "first",
}
for i := 0; i < b.N; i++ {
var in inner
if err := UnmarshalKey(m, &in); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkUnmarshalStruct(b *testing.B) {
b.ReportAllocs()
m := map[string]interface{}{
"Ids": []map[string]interface{}{
{
"First": 1,
"Second": 2,
},
},
}
for i := 0; i < b.N; i++ {
var v struct {
Ids []struct {
First int
Second int
}
}
if err := UnmarshalKey(m, &v); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkMapToStruct(b *testing.B) {
data := map[string]interface{}{
"valid": "1",
"age": "5",
"name": "liao",
}
type anonymous struct {
Valid bool
Age int
Name string
}
for i := 0; i < b.N; i++ {
var an anonymous
if valid, ok := data["valid"]; ok {
an.Valid = valid == "1"
}
if age, ok := data["age"]; ok {
ages, _ := age.(string)
an.Age, _ = strconv.Atoi(ages)
}
if name, ok := data["name"]; ok {
names, _ := name.(string)
an.Name = names
}
}
}
func BenchmarkUnmarshal(b *testing.B) {
data := map[string]interface{}{
"valid": "1",
"age": "5",
"name": "liao",
}
type anonymous struct {
Valid bool `key:"valid,string"`
Age int `key:"age,string"`
Name string `key:"name"`
}
for i := 0; i < b.N; i++ {
var an anonymous
UnmarshalKey(data, &an)
}
}

Loading…
Cancel
Save