...

Source file src/github.com/gin-gonic/gin/binding/form_mapping_test.go

Documentation: github.com/gin-gonic/gin/binding

     1  // Copyright 2019 Gin Core Team. All rights reserved.
     2  // Use of this source code is governed by a MIT style
     3  // license that can be found in the LICENSE file.
     4  
     5  package binding
     6  
     7  import (
     8  	"reflect"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  func TestMappingBaseTypes(t *testing.T) {
    16  	intPtr := func(i int) *int {
    17  		return &i
    18  	}
    19  	for _, tt := range []struct {
    20  		name   string
    21  		value  any
    22  		form   string
    23  		expect any
    24  	}{
    25  		{"base type", struct{ F int }{}, "9", int(9)},
    26  		{"base type", struct{ F int8 }{}, "9", int8(9)},
    27  		{"base type", struct{ F int16 }{}, "9", int16(9)},
    28  		{"base type", struct{ F int32 }{}, "9", int32(9)},
    29  		{"base type", struct{ F int64 }{}, "9", int64(9)},
    30  		{"base type", struct{ F uint }{}, "9", uint(9)},
    31  		{"base type", struct{ F uint8 }{}, "9", uint8(9)},
    32  		{"base type", struct{ F uint16 }{}, "9", uint16(9)},
    33  		{"base type", struct{ F uint32 }{}, "9", uint32(9)},
    34  		{"base type", struct{ F uint64 }{}, "9", uint64(9)},
    35  		{"base type", struct{ F bool }{}, "True", true},
    36  		{"base type", struct{ F float32 }{}, "9.1", float32(9.1)},
    37  		{"base type", struct{ F float64 }{}, "9.1", float64(9.1)},
    38  		{"base type", struct{ F string }{}, "test", string("test")},
    39  		{"base type", struct{ F *int }{}, "9", intPtr(9)},
    40  
    41  		// zero values
    42  		{"zero value", struct{ F int }{}, "", int(0)},
    43  		{"zero value", struct{ F uint }{}, "", uint(0)},
    44  		{"zero value", struct{ F bool }{}, "", false},
    45  		{"zero value", struct{ F float32 }{}, "", float32(0)},
    46  	} {
    47  		tp := reflect.TypeOf(tt.value)
    48  		testName := tt.name + ":" + tp.Field(0).Type.String()
    49  
    50  		val := reflect.New(reflect.TypeOf(tt.value))
    51  		val.Elem().Set(reflect.ValueOf(tt.value))
    52  
    53  		field := val.Elem().Type().Field(0)
    54  
    55  		_, err := mapping(val, emptyField, formSource{field.Name: {tt.form}}, "form")
    56  		assert.NoError(t, err, testName)
    57  
    58  		actual := val.Elem().Field(0).Interface()
    59  		assert.Equal(t, tt.expect, actual, testName)
    60  	}
    61  }
    62  
    63  func TestMappingDefault(t *testing.T) {
    64  	var s struct {
    65  		Int   int    `form:",default=9"`
    66  		Slice []int  `form:",default=9"`
    67  		Array [1]int `form:",default=9"`
    68  	}
    69  	err := mappingByPtr(&s, formSource{}, "form")
    70  	assert.NoError(t, err)
    71  
    72  	assert.Equal(t, 9, s.Int)
    73  	assert.Equal(t, []int{9}, s.Slice)
    74  	assert.Equal(t, [1]int{9}, s.Array)
    75  }
    76  
    77  func TestMappingSkipField(t *testing.T) {
    78  	var s struct {
    79  		A int
    80  	}
    81  	err := mappingByPtr(&s, formSource{}, "form")
    82  	assert.NoError(t, err)
    83  
    84  	assert.Equal(t, 0, s.A)
    85  }
    86  
    87  func TestMappingIgnoreField(t *testing.T) {
    88  	var s struct {
    89  		A int `form:"A"`
    90  		B int `form:"-"`
    91  	}
    92  	err := mappingByPtr(&s, formSource{"A": {"9"}, "B": {"9"}}, "form")
    93  	assert.NoError(t, err)
    94  
    95  	assert.Equal(t, 9, s.A)
    96  	assert.Equal(t, 0, s.B)
    97  }
    98  
    99  func TestMappingUnexportedField(t *testing.T) {
   100  	var s struct {
   101  		A int `form:"a"`
   102  		b int `form:"b"`
   103  	}
   104  	err := mappingByPtr(&s, formSource{"a": {"9"}, "b": {"9"}}, "form")
   105  	assert.NoError(t, err)
   106  
   107  	assert.Equal(t, 9, s.A)
   108  	assert.Equal(t, 0, s.b)
   109  }
   110  
   111  func TestMappingPrivateField(t *testing.T) {
   112  	var s struct {
   113  		f int `form:"field"`
   114  	}
   115  	err := mappingByPtr(&s, formSource{"field": {"6"}}, "form")
   116  	assert.NoError(t, err)
   117  	assert.Equal(t, 0, s.f)
   118  }
   119  
   120  func TestMappingUnknownFieldType(t *testing.T) {
   121  	var s struct {
   122  		U uintptr
   123  	}
   124  
   125  	err := mappingByPtr(&s, formSource{"U": {"unknown"}}, "form")
   126  	assert.Error(t, err)
   127  	assert.Equal(t, errUnknownType, err)
   128  }
   129  
   130  func TestMappingURI(t *testing.T) {
   131  	var s struct {
   132  		F int `uri:"field"`
   133  	}
   134  	err := mapURI(&s, map[string][]string{"field": {"6"}})
   135  	assert.NoError(t, err)
   136  	assert.Equal(t, 6, s.F)
   137  }
   138  
   139  func TestMappingForm(t *testing.T) {
   140  	var s struct {
   141  		F int `form:"field"`
   142  	}
   143  	err := mapForm(&s, map[string][]string{"field": {"6"}})
   144  	assert.NoError(t, err)
   145  	assert.Equal(t, 6, s.F)
   146  }
   147  
   148  func TestMapFormWithTag(t *testing.T) {
   149  	var s struct {
   150  		F int `externalTag:"field"`
   151  	}
   152  	err := MapFormWithTag(&s, map[string][]string{"field": {"6"}}, "externalTag")
   153  	assert.NoError(t, err)
   154  	assert.Equal(t, 6, s.F)
   155  }
   156  
   157  func TestMappingTime(t *testing.T) {
   158  	var s struct {
   159  		Time      time.Time
   160  		LocalTime time.Time `time_format:"2006-01-02"`
   161  		ZeroValue time.Time
   162  		CSTTime   time.Time `time_format:"2006-01-02" time_location:"Asia/Shanghai"`
   163  		UTCTime   time.Time `time_format:"2006-01-02" time_utc:"1"`
   164  	}
   165  
   166  	var err error
   167  	time.Local, err = time.LoadLocation("Europe/Berlin")
   168  	assert.NoError(t, err)
   169  
   170  	err = mapForm(&s, map[string][]string{
   171  		"Time":      {"2019-01-20T16:02:58Z"},
   172  		"LocalTime": {"2019-01-20"},
   173  		"ZeroValue": {},
   174  		"CSTTime":   {"2019-01-20"},
   175  		"UTCTime":   {"2019-01-20"},
   176  	})
   177  	assert.NoError(t, err)
   178  
   179  	assert.Equal(t, "2019-01-20 16:02:58 +0000 UTC", s.Time.String())
   180  	assert.Equal(t, "2019-01-20 00:00:00 +0100 CET", s.LocalTime.String())
   181  	assert.Equal(t, "2019-01-19 23:00:00 +0000 UTC", s.LocalTime.UTC().String())
   182  	assert.Equal(t, "0001-01-01 00:00:00 +0000 UTC", s.ZeroValue.String())
   183  	assert.Equal(t, "2019-01-20 00:00:00 +0800 CST", s.CSTTime.String())
   184  	assert.Equal(t, "2019-01-19 16:00:00 +0000 UTC", s.CSTTime.UTC().String())
   185  	assert.Equal(t, "2019-01-20 00:00:00 +0000 UTC", s.UTCTime.String())
   186  
   187  	// wrong location
   188  	var wrongLoc struct {
   189  		Time time.Time `time_location:"wrong"`
   190  	}
   191  	err = mapForm(&wrongLoc, map[string][]string{"Time": {"2019-01-20T16:02:58Z"}})
   192  	assert.Error(t, err)
   193  
   194  	// wrong time value
   195  	var wrongTime struct {
   196  		Time time.Time
   197  	}
   198  	err = mapForm(&wrongTime, map[string][]string{"Time": {"wrong"}})
   199  	assert.Error(t, err)
   200  }
   201  
   202  func TestMappingTimeDuration(t *testing.T) {
   203  	var s struct {
   204  		D time.Duration
   205  	}
   206  
   207  	// ok
   208  	err := mappingByPtr(&s, formSource{"D": {"5s"}}, "form")
   209  	assert.NoError(t, err)
   210  	assert.Equal(t, 5*time.Second, s.D)
   211  
   212  	// error
   213  	err = mappingByPtr(&s, formSource{"D": {"wrong"}}, "form")
   214  	assert.Error(t, err)
   215  }
   216  
   217  func TestMappingSlice(t *testing.T) {
   218  	var s struct {
   219  		Slice []int `form:"slice,default=9"`
   220  	}
   221  
   222  	// default value
   223  	err := mappingByPtr(&s, formSource{}, "form")
   224  	assert.NoError(t, err)
   225  	assert.Equal(t, []int{9}, s.Slice)
   226  
   227  	// ok
   228  	err = mappingByPtr(&s, formSource{"slice": {"3", "4"}}, "form")
   229  	assert.NoError(t, err)
   230  	assert.Equal(t, []int{3, 4}, s.Slice)
   231  
   232  	// error
   233  	err = mappingByPtr(&s, formSource{"slice": {"wrong"}}, "form")
   234  	assert.Error(t, err)
   235  }
   236  
   237  func TestMappingArray(t *testing.T) {
   238  	var s struct {
   239  		Array [2]int `form:"array,default=9"`
   240  	}
   241  
   242  	// wrong default
   243  	err := mappingByPtr(&s, formSource{}, "form")
   244  	assert.Error(t, err)
   245  
   246  	// ok
   247  	err = mappingByPtr(&s, formSource{"array": {"3", "4"}}, "form")
   248  	assert.NoError(t, err)
   249  	assert.Equal(t, [2]int{3, 4}, s.Array)
   250  
   251  	// error - not enough vals
   252  	err = mappingByPtr(&s, formSource{"array": {"3"}}, "form")
   253  	assert.Error(t, err)
   254  
   255  	// error - wrong value
   256  	err = mappingByPtr(&s, formSource{"array": {"wrong"}}, "form")
   257  	assert.Error(t, err)
   258  }
   259  
   260  func TestMappingStructField(t *testing.T) {
   261  	var s struct {
   262  		J struct {
   263  			I int
   264  		}
   265  	}
   266  
   267  	err := mappingByPtr(&s, formSource{"J": {`{"I": 9}`}}, "form")
   268  	assert.NoError(t, err)
   269  	assert.Equal(t, 9, s.J.I)
   270  }
   271  
   272  func TestMappingMapField(t *testing.T) {
   273  	var s struct {
   274  		M map[string]int
   275  	}
   276  
   277  	err := mappingByPtr(&s, formSource{"M": {`{"one": 1}`}}, "form")
   278  	assert.NoError(t, err)
   279  	assert.Equal(t, map[string]int{"one": 1}, s.M)
   280  }
   281  
   282  func TestMappingIgnoredCircularRef(t *testing.T) {
   283  	type S struct {
   284  		S *S `form:"-"`
   285  	}
   286  	var s S
   287  
   288  	err := mappingByPtr(&s, formSource{}, "form")
   289  	assert.NoError(t, err)
   290  }
   291  

View as plain text