feat: validate value in options for mapping (#2616)
This commit is contained in:
@@ -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)
|
||||
|
||||
var v Value
|
||||
assert.NoError(t, UnmarshalKey(emptyMap, &v))
|
||||
assert.Equal(t, envVal, v.Name)
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalStruct(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user