binding: move tests of mapping to separate test file (#1842)
* move tests of mapping to separate test file make 100% coverage of form_mapping.go from form_mapping_test.go file * fix tests for go 1.6 go 1.6 doesn't support `t.Run(...)` subtests
This commit is contained in:
		@ -114,71 +114,6 @@ type FooStructForBoolType struct {
 | 
			
		||||
	BoolFoo bool `form:"bool_foo"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForIntType struct {
 | 
			
		||||
	IntFoo int `form:"int_foo"`
 | 
			
		||||
	IntBar int `form:"int_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForInt8Type struct {
 | 
			
		||||
	Int8Foo int8 `form:"int8_foo"`
 | 
			
		||||
	Int8Bar int8 `form:"int8_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForInt16Type struct {
 | 
			
		||||
	Int16Foo int16 `form:"int16_foo"`
 | 
			
		||||
	Int16Bar int16 `form:"int16_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForInt32Type struct {
 | 
			
		||||
	Int32Foo int32 `form:"int32_foo"`
 | 
			
		||||
	Int32Bar int32 `form:"int32_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForInt64Type struct {
 | 
			
		||||
	Int64Foo int64 `form:"int64_foo"`
 | 
			
		||||
	Int64Bar int64 `form:"int64_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForUintType struct {
 | 
			
		||||
	UintFoo uint `form:"uint_foo"`
 | 
			
		||||
	UintBar uint `form:"uint_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForUint8Type struct {
 | 
			
		||||
	Uint8Foo uint8 `form:"uint8_foo"`
 | 
			
		||||
	Uint8Bar uint8 `form:"uint8_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForUint16Type struct {
 | 
			
		||||
	Uint16Foo uint16 `form:"uint16_foo"`
 | 
			
		||||
	Uint16Bar uint16 `form:"uint16_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForUint32Type struct {
 | 
			
		||||
	Uint32Foo uint32 `form:"uint32_foo"`
 | 
			
		||||
	Uint32Bar uint32 `form:"uint32_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForUint64Type struct {
 | 
			
		||||
	Uint64Foo uint64 `form:"uint64_foo"`
 | 
			
		||||
	Uint64Bar uint64 `form:"uint64_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForBoolType struct {
 | 
			
		||||
	BoolFoo bool `form:"bool_foo"`
 | 
			
		||||
	BoolBar bool `form:"bool_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForFloat32Type struct {
 | 
			
		||||
	Float32Foo float32 `form:"float32_foo"`
 | 
			
		||||
	Float32Bar float32 `form:"float32_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooBarStructForFloat64Type struct {
 | 
			
		||||
	Float64Foo float64 `form:"float64_foo"`
 | 
			
		||||
	Float64Bar float64 `form:"float64_bar" binding:"required"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FooStructForStringPtrType struct {
 | 
			
		||||
	PtrFoo *string `form:"ptr_foo"`
 | 
			
		||||
	PtrBar *string `form:"ptr_bar" binding:"required"`
 | 
			
		||||
@ -335,110 +270,6 @@ func TestBindingFormForType(t *testing.T) {
 | 
			
		||||
		"/?slice_map_foo=1&slice_map_foo=2", "/?bar2=1&bar2=2",
 | 
			
		||||
		"", "", "SliceMap")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"int_foo=&int_bar=-12", "bar2=-123", "Int")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?int_foo=&int_bar=-12", "/?bar2=-123",
 | 
			
		||||
		"", "", "Int")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"int8_foo=&int8_bar=-12", "bar2=-123", "Int8")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?int8_foo=&int8_bar=-12", "/?bar2=-123",
 | 
			
		||||
		"", "", "Int8")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"int16_foo=&int16_bar=-12", "bar2=-123", "Int16")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?int16_foo=&int16_bar=-12", "/?bar2=-123",
 | 
			
		||||
		"", "", "Int16")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"int32_foo=&int32_bar=-12", "bar2=-123", "Int32")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?int32_foo=&int32_bar=-12", "/?bar2=-123",
 | 
			
		||||
		"", "", "Int32")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"int64_foo=&int64_bar=-12", "bar2=-123", "Int64")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?int64_foo=&int64_bar=-12", "/?bar2=-123",
 | 
			
		||||
		"", "", "Int64")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"uint_foo=&uint_bar=12", "bar2=123", "Uint")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?uint_foo=&uint_bar=12", "/?bar2=123",
 | 
			
		||||
		"", "", "Uint")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"uint8_foo=&uint8_bar=12", "bar2=123", "Uint8")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?uint8_foo=&uint8_bar=12", "/?bar2=123",
 | 
			
		||||
		"", "", "Uint8")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"uint16_foo=&uint16_bar=12", "bar2=123", "Uint16")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?uint16_foo=&uint16_bar=12", "/?bar2=123",
 | 
			
		||||
		"", "", "Uint16")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"uint32_foo=&uint32_bar=12", "bar2=123", "Uint32")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?uint32_foo=&uint32_bar=12", "/?bar2=123",
 | 
			
		||||
		"", "", "Uint32")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"uint64_foo=&uint64_bar=12", "bar2=123", "Uint64")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?uint64_foo=&uint64_bar=12", "/?bar2=123",
 | 
			
		||||
		"", "", "Uint64")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"bool_foo=&bool_bar=true", "bar2=true", "Bool")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?bool_foo=&bool_bar=true", "/?bar2=true",
 | 
			
		||||
		"", "", "Bool")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"float32_foo=&float32_bar=-12.34", "bar2=12.3", "Float32")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?float32_foo=&float32_bar=-12.34", "/?bar2=12.3",
 | 
			
		||||
		"", "", "Float32")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"float64_foo=&float64_bar=-12.34", "bar2=12.3", "Float64")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "GET",
 | 
			
		||||
		"/?float64_foo=&float64_bar=-12.34", "/?bar2=12.3",
 | 
			
		||||
		"", "", "Float64")
 | 
			
		||||
 | 
			
		||||
	testFormBindingForType(t, "POST",
 | 
			
		||||
		"/", "/",
 | 
			
		||||
		"ptr_bar=test", "bar2=test", "Ptr")
 | 
			
		||||
@ -1076,149 +907,6 @@ func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody s
 | 
			
		||||
		req.Header.Add("Content-Type", MIMEPOSTForm)
 | 
			
		||||
	}
 | 
			
		||||
	switch typ {
 | 
			
		||||
	case "Int":
 | 
			
		||||
		obj := FooBarStructForIntType{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, int(0), obj.IntFoo)
 | 
			
		||||
		assert.Equal(t, int(-12), obj.IntBar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForIntType{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Int8":
 | 
			
		||||
		obj := FooBarStructForInt8Type{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, int8(0), obj.Int8Foo)
 | 
			
		||||
		assert.Equal(t, int8(-12), obj.Int8Bar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForInt8Type{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Int16":
 | 
			
		||||
		obj := FooBarStructForInt16Type{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, int16(0), obj.Int16Foo)
 | 
			
		||||
		assert.Equal(t, int16(-12), obj.Int16Bar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForInt16Type{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Int32":
 | 
			
		||||
		obj := FooBarStructForInt32Type{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, int32(0), obj.Int32Foo)
 | 
			
		||||
		assert.Equal(t, int32(-12), obj.Int32Bar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForInt32Type{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Int64":
 | 
			
		||||
		obj := FooBarStructForInt64Type{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, int64(0), obj.Int64Foo)
 | 
			
		||||
		assert.Equal(t, int64(-12), obj.Int64Bar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForInt64Type{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Uint":
 | 
			
		||||
		obj := FooBarStructForUintType{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, uint(0x0), obj.UintFoo)
 | 
			
		||||
		assert.Equal(t, uint(0xc), obj.UintBar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForUintType{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Uint8":
 | 
			
		||||
		obj := FooBarStructForUint8Type{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, uint8(0x0), obj.Uint8Foo)
 | 
			
		||||
		assert.Equal(t, uint8(0xc), obj.Uint8Bar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForUint8Type{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Uint16":
 | 
			
		||||
		obj := FooBarStructForUint16Type{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, uint16(0x0), obj.Uint16Foo)
 | 
			
		||||
		assert.Equal(t, uint16(0xc), obj.Uint16Bar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForUint16Type{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Uint32":
 | 
			
		||||
		obj := FooBarStructForUint32Type{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, uint32(0x0), obj.Uint32Foo)
 | 
			
		||||
		assert.Equal(t, uint32(0xc), obj.Uint32Bar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForUint32Type{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Uint64":
 | 
			
		||||
		obj := FooBarStructForUint64Type{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, uint64(0x0), obj.Uint64Foo)
 | 
			
		||||
		assert.Equal(t, uint64(0xc), obj.Uint64Bar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForUint64Type{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Float32":
 | 
			
		||||
		obj := FooBarStructForFloat32Type{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, float32(0.0), obj.Float32Foo)
 | 
			
		||||
		assert.Equal(t, float32(-12.34), obj.Float32Bar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForFloat32Type{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Float64":
 | 
			
		||||
		obj := FooBarStructForFloat64Type{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, float64(0.0), obj.Float64Foo)
 | 
			
		||||
		assert.Equal(t, float64(-12.34), obj.Float64Bar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForFloat64Type{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Bool":
 | 
			
		||||
		obj := FooBarStructForBoolType{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.False(t, obj.BoolFoo)
 | 
			
		||||
		assert.True(t, obj.BoolBar)
 | 
			
		||||
 | 
			
		||||
		obj = FooBarStructForBoolType{}
 | 
			
		||||
		req = requestWithBody(method, badPath, badBody)
 | 
			
		||||
		err = JSON.Bind(req, &obj)
 | 
			
		||||
		assert.Error(t, err)
 | 
			
		||||
	case "Slice":
 | 
			
		||||
		obj := FooStructForSliceType{}
 | 
			
		||||
		err := b.Bind(req, &obj)
 | 
			
		||||
@ -1454,97 +1142,3 @@ func requestWithBody(method, path, body string) (req *http.Request) {
 | 
			
		||||
	req, _ = http.NewRequest(method, path, bytes.NewBufferString(body))
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestCanSet(t *testing.T) {
 | 
			
		||||
	type CanSetStruct struct {
 | 
			
		||||
		lowerStart string `form:"lower"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var c CanSetStruct
 | 
			
		||||
	assert.Nil(t, mapForm(&c, nil))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func formPostRequest(path, body string) *http.Request {
 | 
			
		||||
	req := requestWithBody("POST", path, body)
 | 
			
		||||
	req.Header.Add("Content-Type", MIMEPOSTForm)
 | 
			
		||||
	return req
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestBindingSliceDefault(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Friends []string `form:"friends,default=mike"`
 | 
			
		||||
	}
 | 
			
		||||
	req := formPostRequest("", "")
 | 
			
		||||
	err := Form.Bind(req, &s)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	assert.Len(t, s.Friends, 1)
 | 
			
		||||
	assert.Equal(t, "mike", s.Friends[0])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestBindingStructField(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Opts struct {
 | 
			
		||||
			Port int
 | 
			
		||||
		} `form:"opts"`
 | 
			
		||||
	}
 | 
			
		||||
	req := formPostRequest("", `opts={"Port": 8000}`)
 | 
			
		||||
	err := Form.Bind(req, &s)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, 8000, s.Opts.Port)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestBindingUnknownTypeChan(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Stop chan bool `form:"stop"`
 | 
			
		||||
	}
 | 
			
		||||
	req := formPostRequest("", "stop=true")
 | 
			
		||||
	err := Form.Bind(req, &s)
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
	assert.Equal(t, errUnknownType, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestBindingTimeDuration(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Timeout time.Duration `form:"timeout"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ok
 | 
			
		||||
	req := formPostRequest("", "timeout=5s")
 | 
			
		||||
	err := Form.Bind(req, &s)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, 5*time.Second, s.Timeout)
 | 
			
		||||
 | 
			
		||||
	// error
 | 
			
		||||
	req = formPostRequest("", "timeout=wrong")
 | 
			
		||||
	err = Form.Bind(req, &s)
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestBindingArray(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Nums [2]int `form:"nums,default=4"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// default
 | 
			
		||||
	req := formPostRequest("", "")
 | 
			
		||||
	err := Form.Bind(req, &s)
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
	assert.Equal(t, [2]int{0, 0}, s.Nums)
 | 
			
		||||
 | 
			
		||||
	// ok
 | 
			
		||||
	req = formPostRequest("", "nums=3&nums=8")
 | 
			
		||||
	err = Form.Bind(req, &s)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, [2]int{3, 8}, s.Nums)
 | 
			
		||||
 | 
			
		||||
	// not enough vals
 | 
			
		||||
	req = formPostRequest("", "nums=3")
 | 
			
		||||
	err = Form.Bind(req, &s)
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
	// error
 | 
			
		||||
	req = formPostRequest("", "nums=3&nums=wrong")
 | 
			
		||||
	err = Form.Bind(req, &s)
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										271
									
								
								binding/form_mapping_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								binding/form_mapping_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,271 @@
 | 
			
		||||
// Copyright 2019 Gin Core Team. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package binding
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestMappingBaseTypes(t *testing.T) {
 | 
			
		||||
	intPtr := func(i int) *int {
 | 
			
		||||
		return &i
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range []struct {
 | 
			
		||||
		name   string
 | 
			
		||||
		value  interface{}
 | 
			
		||||
		form   string
 | 
			
		||||
		expect interface{}
 | 
			
		||||
	}{
 | 
			
		||||
		{"base type", struct{ F int }{}, "9", int(9)},
 | 
			
		||||
		{"base type", struct{ F int8 }{}, "9", int8(9)},
 | 
			
		||||
		{"base type", struct{ F int16 }{}, "9", int16(9)},
 | 
			
		||||
		{"base type", struct{ F int32 }{}, "9", int32(9)},
 | 
			
		||||
		{"base type", struct{ F int64 }{}, "9", int64(9)},
 | 
			
		||||
		{"base type", struct{ F uint }{}, "9", uint(9)},
 | 
			
		||||
		{"base type", struct{ F uint8 }{}, "9", uint8(9)},
 | 
			
		||||
		{"base type", struct{ F uint16 }{}, "9", uint16(9)},
 | 
			
		||||
		{"base type", struct{ F uint32 }{}, "9", uint32(9)},
 | 
			
		||||
		{"base type", struct{ F uint64 }{}, "9", uint64(9)},
 | 
			
		||||
		{"base type", struct{ F bool }{}, "True", true},
 | 
			
		||||
		{"base type", struct{ F float32 }{}, "9.1", float32(9.1)},
 | 
			
		||||
		{"base type", struct{ F float64 }{}, "9.1", float64(9.1)},
 | 
			
		||||
		{"base type", struct{ F string }{}, "test", string("test")},
 | 
			
		||||
		{"base type", struct{ F *int }{}, "9", intPtr(9)},
 | 
			
		||||
 | 
			
		||||
		// zero values
 | 
			
		||||
		{"zero value", struct{ F int }{}, "", int(0)},
 | 
			
		||||
		{"zero value", struct{ F uint }{}, "", uint(0)},
 | 
			
		||||
		{"zero value", struct{ F bool }{}, "", false},
 | 
			
		||||
		{"zero value", struct{ F float32 }{}, "", float32(0)},
 | 
			
		||||
	} {
 | 
			
		||||
		tp := reflect.TypeOf(tt.value)
 | 
			
		||||
		testName := tt.name + ":" + tp.Field(0).Type.String()
 | 
			
		||||
 | 
			
		||||
		val := reflect.New(reflect.TypeOf(tt.value))
 | 
			
		||||
		val.Elem().Set(reflect.ValueOf(tt.value))
 | 
			
		||||
 | 
			
		||||
		field := val.Elem().Type().Field(0)
 | 
			
		||||
 | 
			
		||||
		_, err := mapping(val, emptyField, formSource{field.Name: {tt.form}}, "form")
 | 
			
		||||
		assert.NoError(t, err, testName)
 | 
			
		||||
 | 
			
		||||
		actual := val.Elem().Field(0).Interface()
 | 
			
		||||
		assert.Equal(t, tt.expect, actual, testName)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingDefault(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Int   int    `form:",default=9"`
 | 
			
		||||
		Slice []int  `form:",default=9"`
 | 
			
		||||
		Array [1]int `form:",default=9"`
 | 
			
		||||
	}
 | 
			
		||||
	err := mappingByPtr(&s, formSource{}, "form")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, 9, s.Int)
 | 
			
		||||
	assert.Equal(t, []int{9}, s.Slice)
 | 
			
		||||
	assert.Equal(t, [1]int{9}, s.Array)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingSkipField(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		A int
 | 
			
		||||
	}
 | 
			
		||||
	err := mappingByPtr(&s, formSource{}, "form")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, 0, s.A)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingIgnoreField(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		A int `form:"A"`
 | 
			
		||||
		B int `form:"-"`
 | 
			
		||||
	}
 | 
			
		||||
	err := mappingByPtr(&s, formSource{"A": {"9"}, "B": {"9"}}, "form")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, 9, s.A)
 | 
			
		||||
	assert.Equal(t, 0, s.B)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingUnexportedField(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		A int `form:"a"`
 | 
			
		||||
		b int `form:"b"`
 | 
			
		||||
	}
 | 
			
		||||
	err := mappingByPtr(&s, formSource{"a": {"9"}, "b": {"9"}}, "form")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, 9, s.A)
 | 
			
		||||
	assert.Equal(t, 0, s.b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingPrivateField(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		f int `form:"field"`
 | 
			
		||||
	}
 | 
			
		||||
	err := mappingByPtr(&s, formSource{"field": {"6"}}, "form")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, int(0), s.f)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingUnknownFieldType(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		U uintptr
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mappingByPtr(&s, formSource{"U": {"unknown"}}, "form")
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
	assert.Equal(t, errUnknownType, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingURI(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		F int `uri:"field"`
 | 
			
		||||
	}
 | 
			
		||||
	err := mapUri(&s, map[string][]string{"field": {"6"}})
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, int(6), s.F)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingForm(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		F int `form:"field"`
 | 
			
		||||
	}
 | 
			
		||||
	err := mapForm(&s, map[string][]string{"field": {"6"}})
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, int(6), s.F)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingTime(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Time      time.Time
 | 
			
		||||
		LocalTime time.Time `time_format:"2006-01-02"`
 | 
			
		||||
		ZeroValue time.Time
 | 
			
		||||
		CSTTime   time.Time `time_format:"2006-01-02" time_location:"Asia/Shanghai"`
 | 
			
		||||
		UTCTime   time.Time `time_format:"2006-01-02" time_utc:"1"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	time.Local, err = time.LoadLocation("Europe/Berlin")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	err = mapForm(&s, map[string][]string{
 | 
			
		||||
		"Time":      {"2019-01-20T16:02:58Z"},
 | 
			
		||||
		"LocalTime": {"2019-01-20"},
 | 
			
		||||
		"ZeroValue": {},
 | 
			
		||||
		"CSTTime":   {"2019-01-20"},
 | 
			
		||||
		"UTCTime":   {"2019-01-20"},
 | 
			
		||||
	})
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, "2019-01-20 16:02:58 +0000 UTC", s.Time.String())
 | 
			
		||||
	assert.Equal(t, "2019-01-20 00:00:00 +0100 CET", s.LocalTime.String())
 | 
			
		||||
	assert.Equal(t, "2019-01-19 23:00:00 +0000 UTC", s.LocalTime.UTC().String())
 | 
			
		||||
	assert.Equal(t, "0001-01-01 00:00:00 +0000 UTC", s.ZeroValue.String())
 | 
			
		||||
	assert.Equal(t, "2019-01-20 00:00:00 +0800 CST", s.CSTTime.String())
 | 
			
		||||
	assert.Equal(t, "2019-01-19 16:00:00 +0000 UTC", s.CSTTime.UTC().String())
 | 
			
		||||
	assert.Equal(t, "2019-01-20 00:00:00 +0000 UTC", s.UTCTime.String())
 | 
			
		||||
 | 
			
		||||
	// wrong location
 | 
			
		||||
	var wrongLoc struct {
 | 
			
		||||
		Time time.Time `time_location:"wrong"`
 | 
			
		||||
	}
 | 
			
		||||
	err = mapForm(&wrongLoc, map[string][]string{"Time": {"2019-01-20T16:02:58Z"}})
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
	// wrong time value
 | 
			
		||||
	var wrongTime struct {
 | 
			
		||||
		Time time.Time
 | 
			
		||||
	}
 | 
			
		||||
	err = mapForm(&wrongTime, map[string][]string{"Time": {"wrong"}})
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMapiingTimeDuration(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		D time.Duration
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ok
 | 
			
		||||
	err := mappingByPtr(&s, formSource{"D": {"5s"}}, "form")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, 5*time.Second, s.D)
 | 
			
		||||
 | 
			
		||||
	// error
 | 
			
		||||
	err = mappingByPtr(&s, formSource{"D": {"wrong"}}, "form")
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingSlice(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Slice []int `form:"slice,default=9"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// default value
 | 
			
		||||
	err := mappingByPtr(&s, formSource{}, "form")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, []int{9}, s.Slice)
 | 
			
		||||
 | 
			
		||||
	// ok
 | 
			
		||||
	err = mappingByPtr(&s, formSource{"slice": {"3", "4"}}, "form")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, []int{3, 4}, s.Slice)
 | 
			
		||||
 | 
			
		||||
	// error
 | 
			
		||||
	err = mappingByPtr(&s, formSource{"slice": {"wrong"}}, "form")
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingArray(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		Array [2]int `form:"array,default=9"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// wrong default
 | 
			
		||||
	err := mappingByPtr(&s, formSource{}, "form")
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
	// ok
 | 
			
		||||
	err = mappingByPtr(&s, formSource{"array": {"3", "4"}}, "form")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, [2]int{3, 4}, s.Array)
 | 
			
		||||
 | 
			
		||||
	// error - not enough vals
 | 
			
		||||
	err = mappingByPtr(&s, formSource{"array": {"3"}}, "form")
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
 | 
			
		||||
	// error - wrong value
 | 
			
		||||
	err = mappingByPtr(&s, formSource{"array": {"wrong"}}, "form")
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingStructField(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		J struct {
 | 
			
		||||
			I int
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mappingByPtr(&s, formSource{"J": {`{"I": 9}`}}, "form")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, 9, s.J.I)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMappingMapField(t *testing.T) {
 | 
			
		||||
	var s struct {
 | 
			
		||||
		M map[string]int
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mappingByPtr(&s, formSource{"M": {`{"one": 1}`}}, "form")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, map[string]int{"one": 1}, s.M)
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user