fix: mapping optional dep not canonicaled (#2807)

master
Kevin Wan 2 years ago committed by GitHub
parent 32a59dbc27
commit c9b05ae07e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -97,6 +97,30 @@ d = "abcd!@#$112"
assert.Equal(t, "abcd!@#$112", val.D) assert.Equal(t, "abcd!@#$112", val.D)
} }
func TestConfigOptional(t *testing.T) {
text := `a = "foo"
b = 1
c = "FOO"
d = "abcd"
`
tmpfile, err := createTempFile(".toml", text)
assert.Nil(t, err)
defer os.Remove(tmpfile)
var val struct {
A string `json:"a"`
B int `json:"b,optional"`
C string `json:"c,optional=B"`
D string `json:"d,optional=b"`
}
if assert.NoError(t, Load(tmpfile, &val)) {
assert.Equal(t, "foo", val.A)
assert.Equal(t, 1, val.B)
assert.Equal(t, "FOO", val.C)
assert.Equal(t, "abcd", val.D)
}
}
func TestConfigJsonCanonical(t *testing.T) { func TestConfigJsonCanonical(t *testing.T) {
text := []byte(`{"a": "foo", "B": "bar"}`) text := []byte(`{"a": "foo", "B": "bar"}`)

@ -930,3 +930,13 @@ func TestUnmarshalJsonArray(t *testing.T) {
assert.Equal(t, "kevin", v[0].Name) assert.Equal(t, "kevin", v[0].Name)
assert.Equal(t, 18, v[0].Age) assert.Equal(t, 18, v[0].Age)
} }
func TestUnmarshalJsonBytesError(t *testing.T) {
var v []struct {
Name string `json:"name"`
Age int `json:"age"`
}
assert.Error(t, UnmarshalJsonBytes([]byte((``)), &v))
assert.Error(t, UnmarshalJsonReader(strings.NewReader(``), &v))
}

@ -372,6 +372,26 @@ func (u *Unmarshaler) parseOptionsWithContext(field reflect.StructField, m Value
return key, nil, nil return key, nil, nil
} }
if u.opts.canonicalKey != nil {
key = u.opts.canonicalKey(key)
if len(options.OptionalDep) > 0 {
// need to create a new fieldOption, because the original one is shared through cache.
options = &fieldOptions{
fieldOptionsWithContext: fieldOptionsWithContext{
Inherit: options.Inherit,
FromString: options.FromString,
Optional: options.Optional,
Options: options.Options,
Default: options.Default,
EnvVar: options.EnvVar,
Range: options.Range,
},
OptionalDep: u.opts.canonicalKey(options.OptionalDep),
}
}
}
optsWithContext, err := options.toOptionsWithContext(key, m, fullName) optsWithContext, err := options.toOptionsWithContext(key, m, fullName)
if err != nil { if err != nil {
return "", nil, err return "", nil, err

@ -77,6 +77,26 @@ func TestUnmarshalWithoutTagNameWithCanonicalKey(t *testing.T) {
} }
} }
func TestUnmarshalWithoutTagNameWithCanonicalKeyOptionalDep(t *testing.T) {
type inner struct {
FirstName string `key:",optional"`
LastName string `key:",optional=FirstName"`
}
m := map[string]interface{}{
"firstname": "go",
"lastname": "zero",
}
var in inner
unmarshaler := NewUnmarshaler(defaultKeyName, WithCanonicalKeyFunc(func(s string) string {
return strings.ToLower(s)
}))
if assert.NoError(t, unmarshaler.Unmarshal(m, &in)) {
assert.Equal(t, "go", in.FirstName)
assert.Equal(t, "zero", in.LastName)
}
}
func TestUnmarshalBool(t *testing.T) { func TestUnmarshalBool(t *testing.T) {
type inner struct { type inner struct {
True bool `key:"yes"` True bool `key:"yes"`
@ -1099,6 +1119,66 @@ func TestUnmarshalStructOptionalDependsNotEnoughValue(t *testing.T) {
assert.Error(t, UnmarshalKey(m, &in)) assert.Error(t, UnmarshalKey(m, &in))
} }
func TestUnmarshalStructOptionalDependsMoreValues(t *testing.T) {
type address struct {
Optional string `key:",optional"`
OptionalDepends string `key:",optional=a=b"`
}
type inner struct {
Name string `key:"name"`
Address address `key:"address"`
}
m := map[string]interface{}{
"name": "kevin",
"address": map[string]interface{}{},
}
var in inner
assert.Error(t, UnmarshalKey(m, &in))
}
func TestUnmarshalStructMissing(t *testing.T) {
type address struct {
Optional string `key:",optional"`
OptionalDepends string `key:",optional=a=b"`
}
type inner struct {
Name string `key:"name"`
Address address `key:"address"`
}
m := map[string]interface{}{
"name": "kevin",
}
var in inner
assert.Error(t, UnmarshalKey(m, &in))
}
func TestUnmarshalNestedStructMissing(t *testing.T) {
type mostInner struct {
Name string `key:"name"`
}
type address struct {
Optional string `key:",optional"`
OptionalDepends string `key:",optional=a=b"`
MostInner mostInner
}
type inner struct {
Name string `key:"name"`
Address address `key:"address"`
}
m := map[string]interface{}{
"name": "kevin",
"address": map[string]interface{}{},
}
var in inner
assert.Error(t, UnmarshalKey(m, &in))
}
func TestUnmarshalAnonymousStructOptionalDepends(t *testing.T) { func TestUnmarshalAnonymousStructOptionalDepends(t *testing.T) {
type AnonAddress struct { type AnonAddress struct {
City string `key:"city"` City string `key:"city"`
@ -1422,6 +1502,18 @@ func TestUnmarshalOptionsOptionalWrongValue(t *testing.T) {
assert.Error(t, UnmarshalKey(m, &in)) assert.Error(t, UnmarshalKey(m, &in))
} }
func TestUnmarshalOptionsMissingValues(t *testing.T) {
type inner struct {
Value string `key:"value,options"`
}
m := map[string]interface{}{
"value": "first",
}
var in inner
assert.Error(t, UnmarshalKey(m, &in))
}
func TestUnmarshalStringOptionsWithStringOptionsNotString(t *testing.T) { func TestUnmarshalStringOptionsWithStringOptionsNotString(t *testing.T) {
type inner struct { type inner struct {
Value string `key:"value,options=first|second"` Value string `key:"value,options=first|second"`

Loading…
Cancel
Save