123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- package mhayaMapStructure
- import (
- "errors"
- "math/big"
- "net"
- "reflect"
- "testing"
- "time"
- )
- func TestComposeDecodeHookFunc(t *testing.T) {
- f1 := func(
- f reflect.Kind,
- t reflect.Kind,
- data interface{}) (interface{}, error) {
- return data.(string) + "foo", nil
- }
- f2 := func(
- f reflect.Kind,
- t reflect.Kind,
- data interface{}) (interface{}, error) {
- return data.(string) + "bar", nil
- }
- f := ComposeDecodeHookFunc(f1, f2)
- result, err := DecodeHookExec(
- f, reflect.ValueOf(""), reflect.ValueOf([]byte("")))
- if err != nil {
- t.Fatalf("bad: %s", err)
- }
- if result.(string) != "foobar" {
- t.Fatalf("bad: %#v", result)
- }
- }
- func TestComposeDecodeHookFunc_err(t *testing.T) {
- f1 := func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) {
- return nil, errors.New("foo")
- }
- f2 := func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) {
- panic("NOPE")
- }
- f := ComposeDecodeHookFunc(f1, f2)
- _, err := DecodeHookExec(
- f, reflect.ValueOf(""), reflect.ValueOf([]byte("")))
- if err.Error() != "foo" {
- t.Fatalf("bad: %s", err)
- }
- }
- func TestComposeDecodeHookFunc_kinds(t *testing.T) {
- var f2From reflect.Kind
- f1 := func(
- f reflect.Kind,
- t reflect.Kind,
- data interface{}) (interface{}, error) {
- return int(42), nil
- }
- f2 := func(
- f reflect.Kind,
- t reflect.Kind,
- data interface{}) (interface{}, error) {
- f2From = f
- return data, nil
- }
- f := ComposeDecodeHookFunc(f1, f2)
- _, err := DecodeHookExec(
- f, reflect.ValueOf(""), reflect.ValueOf([]byte("")))
- if err != nil {
- t.Fatalf("bad: %s", err)
- }
- if f2From != reflect.Int {
- t.Fatalf("bad: %#v", f2From)
- }
- }
- func TestComposeDecodeHookFunc_safe_nofuncs(t *testing.T) {
- f := ComposeDecodeHookFunc()
- type myStruct2 struct {
- MyInt int
- }
- type myStruct1 struct {
- Blah map[string]myStruct2
- }
- src := &myStruct1{Blah: map[string]myStruct2{
- "test": {
- MyInt: 1,
- },
- }}
- dst := &myStruct1{}
- dConf := &DecoderConfig{
- Result: dst,
- ErrorUnused: true,
- DecodeHook: f,
- }
- d, err := NewDecoder(dConf)
- if err != nil {
- t.Fatal(err)
- }
- err = d.Decode(src)
- if err != nil {
- t.Fatal(err)
- }
- }
- func TestStringToSliceHookFunc(t *testing.T) {
- f := StringToSliceHookFunc(",")
- strValue := reflect.ValueOf("42")
- sliceValue := reflect.ValueOf([]byte("42"))
- cases := []struct {
- f, t reflect.Value
- result interface{}
- err bool
- }{
- {sliceValue, sliceValue, []byte("42"), false},
- {strValue, strValue, "42", false},
- {
- reflect.ValueOf("foo,bar,baz"),
- sliceValue,
- []string{"foo", "bar", "baz"},
- false,
- },
- {
- reflect.ValueOf(""),
- sliceValue,
- []string{},
- false,
- },
- }
- for i, tc := range cases {
- actual, err := DecodeHookExec(f, tc.f, tc.t)
- if tc.err != (err != nil) {
- t.Fatalf("case %d: expected err %#v", i, tc.err)
- }
- if !reflect.DeepEqual(actual, tc.result) {
- t.Fatalf(
- "case %d: expected %#v, got %#v",
- i, tc.result, actual)
- }
- }
- }
- func TestStringToTimeDurationHookFunc(t *testing.T) {
- f := StringToTimeDurationHookFunc()
- timeValue := reflect.ValueOf(time.Duration(5))
- strValue := reflect.ValueOf("")
- cases := []struct {
- f, t reflect.Value
- result interface{}
- err bool
- }{
- {reflect.ValueOf("5s"), timeValue, 5 * time.Second, false},
- {reflect.ValueOf("5"), timeValue, time.Duration(0), true},
- {reflect.ValueOf("5"), strValue, "5", false},
- }
- for i, tc := range cases {
- actual, err := DecodeHookExec(f, tc.f, tc.t)
- if tc.err != (err != nil) {
- t.Fatalf("case %d: expected err %#v", i, tc.err)
- }
- if !reflect.DeepEqual(actual, tc.result) {
- t.Fatalf(
- "case %d: expected %#v, got %#v",
- i, tc.result, actual)
- }
- }
- }
- func TestStringToTimeHookFunc(t *testing.T) {
- strValue := reflect.ValueOf("5")
- timeValue := reflect.ValueOf(time.Time{})
- cases := []struct {
- f, t reflect.Value
- layout string
- result interface{}
- err bool
- }{
- {reflect.ValueOf("2006-01-02T15:04:05Z"), timeValue, time.RFC3339,
- time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC), false},
- {strValue, timeValue, time.RFC3339, time.Time{}, true},
- {strValue, strValue, time.RFC3339, "5", false},
- }
- for i, tc := range cases {
- f := StringToTimeHookFunc(tc.layout)
- actual, err := DecodeHookExec(f, tc.f, tc.t)
- if tc.err != (err != nil) {
- t.Fatalf("case %d: expected err %#v", i, tc.err)
- }
- if !reflect.DeepEqual(actual, tc.result) {
- t.Fatalf(
- "case %d: expected %#v, got %#v",
- i, tc.result, actual)
- }
- }
- }
- func TestStringToIPHookFunc(t *testing.T) {
- strValue := reflect.ValueOf("5")
- ipValue := reflect.ValueOf(net.IP{})
- cases := []struct {
- f, t reflect.Value
- result interface{}
- err bool
- }{
- {reflect.ValueOf("1.2.3.4"), ipValue,
- net.IPv4(0x01, 0x02, 0x03, 0x04), false},
- {strValue, ipValue, net.IP{}, true},
- {strValue, strValue, "5", false},
- }
- for i, tc := range cases {
- f := StringToIPHookFunc()
- actual, err := DecodeHookExec(f, tc.f, tc.t)
- if tc.err != (err != nil) {
- t.Fatalf("case %d: expected err %#v", i, tc.err)
- }
- if !reflect.DeepEqual(actual, tc.result) {
- t.Fatalf(
- "case %d: expected %#v, got %#v",
- i, tc.result, actual)
- }
- }
- }
- func TestStringToIPNetHookFunc(t *testing.T) {
- strValue := reflect.ValueOf("5")
- ipNetValue := reflect.ValueOf(net.IPNet{})
- var nilNet *net.IPNet = nil
- cases := []struct {
- f, t reflect.Value
- result interface{}
- err bool
- }{
- {reflect.ValueOf("1.2.3.4/24"), ipNetValue,
- &net.IPNet{
- IP: net.IP{0x01, 0x02, 0x03, 0x00},
- Mask: net.IPv4Mask(0xff, 0xff, 0xff, 0x00),
- }, false},
- {strValue, ipNetValue, nilNet, true},
- {strValue, strValue, "5", false},
- }
- for i, tc := range cases {
- f := StringToIPNetHookFunc()
- actual, err := DecodeHookExec(f, tc.f, tc.t)
- if tc.err != (err != nil) {
- t.Fatalf("case %d: expected err %#v", i, tc.err)
- }
- if !reflect.DeepEqual(actual, tc.result) {
- t.Fatalf(
- "case %d: expected %#v, got %#v",
- i, tc.result, actual)
- }
- }
- }
- func TestWeaklyTypedHook(t *testing.T) {
- var f DecodeHookFunc = WeaklyTypedHook
- strValue := reflect.ValueOf("")
- cases := []struct {
- f, t reflect.Value
- result interface{}
- err bool
- }{
- // TO STRING
- {
- reflect.ValueOf(false),
- strValue,
- "0",
- false,
- },
- {
- reflect.ValueOf(true),
- strValue,
- "1",
- false,
- },
- {
- reflect.ValueOf(float32(7)),
- strValue,
- "7",
- false,
- },
- {
- reflect.ValueOf(int(7)),
- strValue,
- "7",
- false,
- },
- {
- reflect.ValueOf([]uint8("foo")),
- strValue,
- "foo",
- false,
- },
- {
- reflect.ValueOf(uint(7)),
- strValue,
- "7",
- false,
- },
- }
- for i, tc := range cases {
- actual, err := DecodeHookExec(f, tc.f, tc.t)
- if tc.err != (err != nil) {
- t.Fatalf("case %d: expected err %#v", i, tc.err)
- }
- if !reflect.DeepEqual(actual, tc.result) {
- t.Fatalf(
- "case %d: expected %#v, got %#v",
- i, tc.result, actual)
- }
- }
- }
- func TestStructToMapHookFuncTabled(t *testing.T) {
- var f DecodeHookFunc = RecursiveStructToMapHookFunc()
- type b struct {
- TestKey string
- }
- type a struct {
- Sub b
- }
- testStruct := a{
- Sub: b{
- TestKey: "testval",
- },
- }
- testMap := map[string]interface{}{
- "Sub": map[string]interface{}{
- "TestKey": "testval",
- },
- }
- cases := []struct {
- name string
- receiver interface{}
- input interface{}
- expected interface{}
- err bool
- }{
- {
- "map receiver",
- func() interface{} {
- var res map[string]interface{}
- return &res
- }(),
- testStruct,
- &testMap,
- false,
- },
- {
- "interface receiver",
- func() interface{} {
- var res interface{}
- return &res
- }(),
- testStruct,
- func() interface{} {
- var exp interface{} = testMap
- return &exp
- }(),
- false,
- },
- {
- "slice receiver errors",
- func() interface{} {
- var res []string
- return &res
- }(),
- testStruct,
- new([]string),
- true,
- },
- {
- "slice to slice - no change",
- func() interface{} {
- var res []string
- return &res
- }(),
- []string{"a", "b"},
- &[]string{"a", "b"},
- false,
- },
- {
- "string to string - no change",
- func() interface{} {
- var res string
- return &res
- }(),
- "test",
- func() *string {
- s := "test"
- return &s
- }(),
- false,
- },
- }
- for _, tc := range cases {
- t.Run(tc.name, func(t *testing.T) {
- cfg := &DecoderConfig{
- DecodeHook: f,
- Result: tc.receiver,
- }
- d, err := NewDecoder(cfg)
- if err != nil {
- t.Fatalf("unexpected err %#v", err)
- }
- err = d.Decode(tc.input)
- if tc.err != (err != nil) {
- t.Fatalf("expected err %#v", err)
- }
- if !reflect.DeepEqual(tc.expected, tc.receiver) {
- t.Fatalf("expected %#v, got %#v",
- tc.expected, tc.receiver)
- }
- })
- }
- }
- func TestTextUnmarshallerHookFunc(t *testing.T) {
- cases := []struct {
- f, t reflect.Value
- result interface{}
- err bool
- }{
- {reflect.ValueOf("42"), reflect.ValueOf(big.Int{}), big.NewInt(42), false},
- {reflect.ValueOf("invalid"), reflect.ValueOf(big.Int{}), nil, true},
- {reflect.ValueOf("5"), reflect.ValueOf("5"), "5", false},
- }
- for i, tc := range cases {
- f := TextUnmarshallerHookFunc()
- actual, err := DecodeHookExec(f, tc.f, tc.t)
- if tc.err != (err != nil) {
- t.Fatalf("case %d: expected err %#v", i, tc.err)
- }
- if !reflect.DeepEqual(actual, tc.result) {
- t.Fatalf(
- "case %d: expected %#v, got %#v",
- i, tc.result, actual)
- }
- }
- }
|