|
|
|
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, setValue(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]interface{}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 := setValue(test.kind, test.target, test.value)
|
|
|
|
assert.NotEqual(t, errValueNotSettable, err)
|
|
|
|
assert.NotNil(t, err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRepr(t *testing.T) {
|
|
|
|
var (
|
|
|
|
f32 float32 = 1.1
|
|
|
|
f64 = 2.2
|
|
|
|
i8 int8 = 1
|
|
|
|
i16 int16 = 2
|
|
|
|
i32 int32 = 3
|
|
|
|
i64 int64 = 4
|
|
|
|
u8 uint8 = 5
|
|
|
|
u16 uint16 = 6
|
|
|
|
u32 uint32 = 7
|
|
|
|
u64 uint64 = 8
|
|
|
|
)
|
|
|
|
tests := []struct {
|
|
|
|
v interface{}
|
|
|
|
expect string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
nil,
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
mockStringable{},
|
|
|
|
"mocked",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
new(mockStringable),
|
|
|
|
"mocked",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
newMockPtr(),
|
|
|
|
"mockptr",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&mockOpacity{
|
|
|
|
val: 1,
|
|
|
|
},
|
|
|
|
"{1}",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
true,
|
|
|
|
"true",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
false,
|
|
|
|
"false",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
f32,
|
|
|
|
"1.1",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
f64,
|
|
|
|
"2.2",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
i8,
|
|
|
|
"1",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
i16,
|
|
|
|
"2",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
i32,
|
|
|
|
"3",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
i64,
|
|
|
|
"4",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
u8,
|
|
|
|
"5",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
u16,
|
|
|
|
"6",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
u32,
|
|
|
|
"7",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
u64,
|
|
|
|
"8",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
[]byte(`abcd`),
|
|
|
|
"abcd",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
mockOpacity{val: 1},
|
|
|
|
"{1}",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(test.expect, func(t *testing.T) {
|
|
|
|
assert.Equal(t, test.expect, Repr(test.v))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockStringable struct{}
|
|
|
|
|
|
|
|
func (m mockStringable) String() string {
|
|
|
|
return "mocked"
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockPtr struct{}
|
|
|
|
|
|
|
|
func newMockPtr() *mockPtr {
|
|
|
|
return new(mockPtr)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockPtr) String() string {
|
|
|
|
return "mockptr"
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockOpacity struct {
|
|
|
|
val int
|
|
|
|
}
|