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.
298 lines
6.0 KiB
298 lines
6.0 KiB
package mapping |
|
|
|
import ( |
|
"reflect" |
|
"testing" |
|
|
|
"github.com/stretchr/testify/assert" |
|
) |
|
|
|
const testTagName = "key" |
|
|
|
type Foo struct { |
|
Str string |
|
StrWithTag string `key:"stringwithtag"` |
|
StrWithTagAndOption string `key:"stringwithtag,string"` |
|
} |
|
|
|
func TestDerefInt(t *testing.T) { |
|
i := 1 |
|
s := "hello" |
|
number := struct { |
|
f float64 |
|
}{ |
|
f: 6.4, |
|
} |
|
cases := []struct { |
|
t reflect.Type |
|
expect reflect.Kind |
|
}{ |
|
{ |
|
t: reflect.TypeOf(i), |
|
expect: reflect.Int, |
|
}, |
|
{ |
|
t: reflect.TypeOf(&i), |
|
expect: reflect.Int, |
|
}, |
|
{ |
|
t: reflect.TypeOf(s), |
|
expect: reflect.String, |
|
}, |
|
{ |
|
t: reflect.TypeOf(&s), |
|
expect: reflect.String, |
|
}, |
|
{ |
|
t: reflect.TypeOf(number.f), |
|
expect: reflect.Float64, |
|
}, |
|
{ |
|
t: reflect.TypeOf(&number.f), |
|
expect: reflect.Float64, |
|
}, |
|
} |
|
|
|
for _, each := range cases { |
|
t.Run(each.t.String(), func(t *testing.T) { |
|
assert.Equal(t, each.expect, Deref(each.t).Kind()) |
|
}) |
|
} |
|
} |
|
|
|
func TestDerefValInt(t *testing.T) { |
|
i := 1 |
|
s := "hello" |
|
number := struct { |
|
f float64 |
|
}{ |
|
f: 6.4, |
|
} |
|
cases := []struct { |
|
t reflect.Value |
|
expect reflect.Kind |
|
}{ |
|
{ |
|
t: reflect.ValueOf(i), |
|
expect: reflect.Int, |
|
}, |
|
{ |
|
t: reflect.ValueOf(&i), |
|
expect: reflect.Int, |
|
}, |
|
{ |
|
t: reflect.ValueOf(s), |
|
expect: reflect.String, |
|
}, |
|
{ |
|
t: reflect.ValueOf(&s), |
|
expect: reflect.String, |
|
}, |
|
{ |
|
t: reflect.ValueOf(number.f), |
|
expect: reflect.Float64, |
|
}, |
|
{ |
|
t: reflect.ValueOf(&number.f), |
|
expect: reflect.Float64, |
|
}, |
|
} |
|
|
|
for _, each := range cases { |
|
t.Run(each.t.String(), func(t *testing.T) { |
|
assert.Equal(t, each.expect, ensureValue(each.t).Kind()) |
|
}) |
|
} |
|
} |
|
|
|
func TestParseKeyAndOptionWithoutTag(t *testing.T) { |
|
var foo Foo |
|
rte := reflect.TypeOf(&foo).Elem() |
|
field, _ := rte.FieldByName("Str") |
|
key, options, err := parseKeyAndOptions(testTagName, field) |
|
assert.Nil(t, err) |
|
assert.Equal(t, "Str", key) |
|
assert.Nil(t, options) |
|
} |
|
|
|
func TestParseKeyAndOptionWithTagWithoutOption(t *testing.T) { |
|
var foo Foo |
|
rte := reflect.TypeOf(&foo).Elem() |
|
field, _ := rte.FieldByName("StrWithTag") |
|
key, options, err := parseKeyAndOptions(testTagName, field) |
|
assert.Nil(t, err) |
|
assert.Equal(t, "stringwithtag", key) |
|
assert.Nil(t, options) |
|
} |
|
|
|
func TestParseKeyAndOptionWithTagAndOption(t *testing.T) { |
|
var foo Foo |
|
rte := reflect.TypeOf(&foo).Elem() |
|
field, _ := rte.FieldByName("StrWithTagAndOption") |
|
key, options, err := parseKeyAndOptions(testTagName, field) |
|
assert.Nil(t, err) |
|
assert.Equal(t, "stringwithtag", key) |
|
assert.True(t, options.FromString) |
|
} |
|
|
|
func TestParseSegments(t *testing.T) { |
|
tests := []struct { |
|
input string |
|
expect []string |
|
}{ |
|
{ |
|
input: "", |
|
expect: []string{}, |
|
}, |
|
{ |
|
input: ",", |
|
expect: []string{""}, |
|
}, |
|
{ |
|
input: "foo,", |
|
expect: []string{"foo"}, |
|
}, |
|
{ |
|
input: ",foo", |
|
// the first empty string cannot be ignored, it's the key. |
|
expect: []string{"", "foo"}, |
|
}, |
|
{ |
|
input: "foo", |
|
expect: []string{"foo"}, |
|
}, |
|
{ |
|
input: "foo,bar", |
|
expect: []string{"foo", "bar"}, |
|
}, |
|
{ |
|
input: "foo,bar,baz", |
|
expect: []string{"foo", "bar", "baz"}, |
|
}, |
|
{ |
|
input: "foo,options=a|b", |
|
expect: []string{"foo", "options=a|b"}, |
|
}, |
|
{ |
|
input: "foo,bar,default=[baz,qux]", |
|
expect: []string{"foo", "bar", "default=[baz,qux]"}, |
|
}, |
|
{ |
|
input: "foo,bar,options=[baz,qux]", |
|
expect: []string{"foo", "bar", "options=[baz,qux]"}, |
|
}, |
|
{ |
|
input: `foo\,bar,options=[baz,qux]`, |
|
expect: []string{`foo,bar`, "options=[baz,qux]"}, |
|
}, |
|
{ |
|
input: `foo,bar,options=\[baz,qux]`, |
|
expect: []string{"foo", "bar", "options=[baz", "qux]"}, |
|
}, |
|
{ |
|
input: `foo,bar,options=[baz\,qux]`, |
|
expect: []string{"foo", "bar", `options=[baz\,qux]`}, |
|
}, |
|
{ |
|
input: `foo\,bar,options=[baz,qux],default=baz`, |
|
expect: []string{`foo,bar`, "options=[baz,qux]", "default=baz"}, |
|
}, |
|
{ |
|
input: `foo\,bar,options=[baz,qux, quux],default=[qux, baz]`, |
|
expect: []string{`foo,bar`, "options=[baz,qux, quux]", "default=[qux, baz]"}, |
|
}, |
|
} |
|
|
|
for _, test := range tests { |
|
test := test |
|
t.Run(test.input, func(t *testing.T) { |
|
assert.ElementsMatch(t, test.expect, parseSegments(test.input)) |
|
}) |
|
} |
|
} |
|
|
|
func TestValidatePtrWithNonPtr(t *testing.T) { |
|
var foo string |
|
rve := reflect.ValueOf(foo) |
|
assert.NotNil(t, ValidatePtr(&rve)) |
|
} |
|
|
|
func TestValidatePtrWithPtr(t *testing.T) { |
|
var foo string |
|
rve := reflect.ValueOf(&foo) |
|
assert.Nil(t, ValidatePtr(&rve)) |
|
} |
|
|
|
func TestValidatePtrWithNilPtr(t *testing.T) { |
|
var foo *string |
|
rve := reflect.ValueOf(foo) |
|
assert.NotNil(t, ValidatePtr(&rve)) |
|
} |
|
|
|
func TestValidatePtrWithZeroValue(t *testing.T) { |
|
var s string |
|
e := reflect.Zero(reflect.TypeOf(s)) |
|
assert.NotNil(t, ValidatePtr(&e)) |
|
} |
|
|
|
func TestSetValueNotSettable(t *testing.T) { |
|
var i int |
|
assert.NotNil(t, setValueFromString(reflect.Int, reflect.ValueOf(i), "1")) |
|
} |
|
|
|
func TestParseKeyAndOptionsErrors(t *testing.T) { |
|
type Bar struct { |
|
OptionsValue string `key:",options=a=b"` |
|
DefaultValue string `key:",default=a=b"` |
|
} |
|
|
|
var bar Bar |
|
_, _, err := parseKeyAndOptions("key", reflect.TypeOf(&bar).Elem().Field(0)) |
|
assert.NotNil(t, err) |
|
_, _, err = parseKeyAndOptions("key", reflect.TypeOf(&bar).Elem().Field(1)) |
|
assert.NotNil(t, err) |
|
} |
|
|
|
func TestSetValueFormatErrors(t *testing.T) { |
|
type Bar struct { |
|
IntValue int |
|
UintValue uint |
|
FloatValue float32 |
|
MapValue map[string]any |
|
} |
|
|
|
var bar Bar |
|
tests := []struct { |
|
kind reflect.Kind |
|
target reflect.Value |
|
value string |
|
}{ |
|
{ |
|
kind: reflect.Int, |
|
target: reflect.ValueOf(&bar.IntValue).Elem(), |
|
value: "a", |
|
}, |
|
{ |
|
kind: reflect.Uint, |
|
target: reflect.ValueOf(&bar.UintValue).Elem(), |
|
value: "a", |
|
}, |
|
{ |
|
kind: reflect.Float32, |
|
target: reflect.ValueOf(&bar.FloatValue).Elem(), |
|
value: "a", |
|
}, |
|
{ |
|
kind: reflect.Map, |
|
target: reflect.ValueOf(&bar.MapValue).Elem(), |
|
}, |
|
} |
|
|
|
for _, test := range tests { |
|
t.Run(test.kind.String(), func(t *testing.T) { |
|
err := setValueFromString(test.kind, test.target, test.value) |
|
assert.NotEqual(t, errValueNotSettable, err) |
|
assert.NotNil(t, err) |
|
}) |
|
} |
|
}
|
|
|