Compare commits
	
		
			5 Commits
		
	
	
		
			22ec4deb4a
			...
			c4b087d990
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | c4b087d990 | |
|  | 7940dd5237 | |
|  | ceabec997c | |
|  | 0d83cfc042 | |
|  | bf312432ee | 
							
								
								
									
										23
									
								
								gin/b/b.go
								
								
								
								
							
							
						
						
									
										23
									
								
								gin/b/b.go
								
								
								
								
							|  | @ -1,8 +1,8 @@ | |||
| package b | ||||
| 
 | ||||
| import ( | ||||
| 	"git.ningdatech.com/ningda/gin_valid/gin/binding" | ||||
| 	"git.ningdatech.com/ningda/gin_valid/go-playground/validator/v10" | ||||
| 	"git.hpds.cc/Component/gin_valid.git/gin/binding" | ||||
| 	"git.hpds.cc/Component/gin_valid.git/go-playground/validator/v10" | ||||
| 	"mime" | ||||
| 	"net/http" | ||||
| ) | ||||
|  | @ -11,7 +11,7 @@ type ValidError struct { | |||
| 	ErrString string | ||||
| } | ||||
| 
 | ||||
| func (e *ValidError) Error() string { | ||||
| func (e ValidError) Error() string { | ||||
| 	return e.ErrString | ||||
| } | ||||
| 
 | ||||
|  | @ -21,17 +21,22 @@ func ShouldBind(req *http.Request, obj interface{}) error { | |||
| 		return err | ||||
| 	} | ||||
| 	b := binding.Default(req.Method, content) | ||||
| 	err = ShouldBindWith(req, obj, b) | ||||
| 	return ShouldBindWith(req, obj, b) | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| func ShouldBindWith(req *http.Request, obj interface{}, b binding.Binding) error { | ||||
| 	err := b.Bind(req, obj) | ||||
| 	errs, ok := err.(validator.ValidationErrors) | ||||
| 	if !ok { | ||||
| 		// 非validator.ValidationErrors类型错误直接返回
 | ||||
| 		return err | ||||
| 	} | ||||
| 	return errs.Translate(binding.ValidTrans) | ||||
| } | ||||
| 
 | ||||
| func ShouldBindWith(req *http.Request, obj interface{}, b binding.Binding) error { | ||||
| 	return b.Bind(req, obj) | ||||
| 	err0 := errs.Translate(binding.ValidTrans) | ||||
| 	if err0 != nil { | ||||
| 		return ValidError{ErrString: err0.Error()} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| func ShouldBindJSON(req *http.Request, obj interface{}) error { | ||||
| 	return ShouldBindWith(req, obj, binding.JSON) | ||||
|  |  | |||
|  | @ -5,10 +5,10 @@ | |||
| package binding | ||||
| 
 | ||||
| import ( | ||||
| 	"git.ningdatech.com/ningda/gin_valid/go-playground/locales/zh" | ||||
| 	ut "git.ningdatech.com/ningda/gin_valid/go-playground/universal-translator" | ||||
| 	"git.ningdatech.com/ningda/gin_valid/go-playground/validator/v10" | ||||
| 	zhTrans "git.ningdatech.com/ningda/gin_valid/go-playground/validator/v10/translations/zh" | ||||
| 	"git.hpds.cc/Component/gin_valid.git/go-playground/locales/zh" | ||||
| 	ut "git.hpds.cc/Component/gin_valid.git/go-playground/universal-translator" | ||||
| 	"git.hpds.cc/Component/gin_valid.git/go-playground/validator/v10" | ||||
| 	zhTrans "git.hpds.cc/Component/gin_valid.git/go-playground/validator/v10/translations/zh" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
|  |  | |||
|  | @ -12,8 +12,8 @@ import ( | |||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"git.ningdatech.com/ningda/gin_valid/gin/internal/bytesconv" | ||||
| 	"git.ningdatech.com/ningda/gin_valid/gin/internal/json" | ||||
| 	"git.hpds.cc/Component/gin_valid.git/gin/internal/bytesconv" | ||||
| 	"git.hpds.cc/Component/gin_valid.git/gin/internal/json" | ||||
| ) | ||||
| 
 | ||||
| var errUnknownType = errors.New("unknown type") | ||||
|  |  | |||
|  | @ -1,67 +0,0 @@ | |||
| // 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 ( | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
| 
 | ||||
| var form = map[string][]string{ | ||||
| 	"name":      {"mike"}, | ||||
| 	"friends":   {"anna", "nicole"}, | ||||
| 	"id_number": {"12345678"}, | ||||
| 	"id_date":   {"2018-01-20"}, | ||||
| } | ||||
| 
 | ||||
| type structFull struct { | ||||
| 	Name    string   `form:"name"` | ||||
| 	Age     int      `form:"age,default=25"` | ||||
| 	Friends []string `form:"friends"` | ||||
| 	ID      *struct { | ||||
| 		Number      string    `form:"id_number"` | ||||
| 		DateOfIssue time.Time `form:"id_date" time_format:"2006-01-02" time_utc:"true"` | ||||
| 	} | ||||
| 	Nationality *string `form:"nationality"` | ||||
| } | ||||
| 
 | ||||
| func BenchmarkMapFormFull(b *testing.B) { | ||||
| 	var s structFull | ||||
| 	for i := 0; i < b.N; i++ { | ||||
| 		err := mapForm(&s, form) | ||||
| 		if err != nil { | ||||
| 			b.Fatalf("Error on a form mapping") | ||||
| 		} | ||||
| 	} | ||||
| 	b.StopTimer() | ||||
| 
 | ||||
| 	t := b | ||||
| 	assert.Equal(t, "mike", s.Name) | ||||
| 	assert.Equal(t, 25, s.Age) | ||||
| 	assert.Equal(t, []string{"anna", "nicole"}, s.Friends) | ||||
| 	assert.Equal(t, "12345678", s.ID.Number) | ||||
| 	assert.Equal(t, time.Date(2018, 1, 20, 0, 0, 0, 0, time.UTC), s.ID.DateOfIssue) | ||||
| 	assert.Nil(t, s.Nationality) | ||||
| } | ||||
| 
 | ||||
| type structName struct { | ||||
| 	Name string `form:"name"` | ||||
| } | ||||
| 
 | ||||
| func BenchmarkMapFormName(b *testing.B) { | ||||
| 	var s structName | ||||
| 	for i := 0; i < b.N; i++ { | ||||
| 		err := mapForm(&s, form) | ||||
| 		if err != nil { | ||||
| 			b.Fatalf("Error on a form mapping") | ||||
| 		} | ||||
| 	} | ||||
| 	b.StopTimer() | ||||
| 
 | ||||
| 	t := b | ||||
| 	assert.Equal(t, "mike", s.Name) | ||||
| } | ||||
|  | @ -1,281 +0,0 @@ | |||
| // 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 TestMappingTimeDuration(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) | ||||
| } | ||||
| 
 | ||||
| func TestMappingIgnoredCircularRef(t *testing.T) { | ||||
| 	type S struct { | ||||
| 		S *S `form:"-"` | ||||
| 	} | ||||
| 	var s S | ||||
| 
 | ||||
| 	err := mappingByPtr(&s, formSource{}, "form") | ||||
| 	assert.NoError(t, err) | ||||
| } | ||||
|  | @ -10,7 +10,7 @@ import ( | |||
| 	"io" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"git.ningdatech.com/ningda/gin_valid/gin/internal/json" | ||||
| 	"git.hpds.cc/Component/gin_valid.git/gin/internal/json" | ||||
| ) | ||||
| 
 | ||||
| // EnableDecoderUseNumber is used to call the UseNumber method on the JSON
 | ||||
|  |  | |||
|  | @ -1,30 +0,0 @@ | |||
| // 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 ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
| 
 | ||||
| func TestJSONBindingBindBody(t *testing.T) { | ||||
| 	var s struct { | ||||
| 		Foo string `json:"foo"` | ||||
| 	} | ||||
| 	err := jsonBinding{}.BindBody([]byte(`{"foo": "FOO"}`), &s) | ||||
| 	require.NoError(t, err) | ||||
| 	assert.Equal(t, "FOO", s.Foo) | ||||
| } | ||||
| 
 | ||||
| func TestJSONBindingBindBodyMap(t *testing.T) { | ||||
| 	s := make(map[string]string) | ||||
| 	err := jsonBinding{}.BindBody([]byte(`{"foo": "FOO","hello":"world"}`), &s) | ||||
| 	require.NoError(t, err) | ||||
| 	assert.Len(t, s, 2) | ||||
| 	assert.Equal(t, "FOO", s["foo"]) | ||||
| 	assert.Equal(t, "world", s["hello"]) | ||||
| } | ||||
|  | @ -1,34 +0,0 @@ | |||
| // 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.
 | ||||
| 
 | ||||
| // +build !nomsgpack
 | ||||
| 
 | ||||
| package binding | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 	"github.com/ugorji/go/codec" | ||||
| ) | ||||
| 
 | ||||
| func TestMsgpackBindingBindBody(t *testing.T) { | ||||
| 	type teststruct struct { | ||||
| 		Foo string `msgpack:"foo"` | ||||
| 	} | ||||
| 	var s teststruct | ||||
| 	err := msgpackBinding{}.BindBody(msgpackBody(t, teststruct{"FOO"}), &s) | ||||
| 	require.NoError(t, err) | ||||
| 	assert.Equal(t, "FOO", s.Foo) | ||||
| } | ||||
| 
 | ||||
| func msgpackBody(t *testing.T, obj interface{}) []byte { | ||||
| 	var bs bytes.Buffer | ||||
| 	h := &codec.MsgpackHandle{} | ||||
| 	err := codec.NewEncoder(&bs, h).Encode(obj) | ||||
| 	require.NoError(t, err) | ||||
| 	return bs.Bytes() | ||||
| } | ||||
|  | @ -1,138 +0,0 @@ | |||
| // 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 ( | ||||
| 	"bytes" | ||||
| 	"io/ioutil" | ||||
| 	"mime/multipart" | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
| 
 | ||||
| func TestFormMultipartBindingBindOneFile(t *testing.T) { | ||||
| 	var s struct { | ||||
| 		FileValue   multipart.FileHeader     `form:"file"` | ||||
| 		FilePtr     *multipart.FileHeader    `form:"file"` | ||||
| 		SliceValues []multipart.FileHeader   `form:"file"` | ||||
| 		SlicePtrs   []*multipart.FileHeader  `form:"file"` | ||||
| 		ArrayValues [1]multipart.FileHeader  `form:"file"` | ||||
| 		ArrayPtrs   [1]*multipart.FileHeader `form:"file"` | ||||
| 	} | ||||
| 	file := testFile{"file", "file1", []byte("hello")} | ||||
| 
 | ||||
| 	req := createRequestMultipartFiles(t, file) | ||||
| 	err := FormMultipart.Bind(req, &s) | ||||
| 	assert.NoError(t, err) | ||||
| 
 | ||||
| 	assertMultipartFileHeader(t, &s.FileValue, file) | ||||
| 	assertMultipartFileHeader(t, s.FilePtr, file) | ||||
| 	assert.Len(t, s.SliceValues, 1) | ||||
| 	assertMultipartFileHeader(t, &s.SliceValues[0], file) | ||||
| 	assert.Len(t, s.SlicePtrs, 1) | ||||
| 	assertMultipartFileHeader(t, s.SlicePtrs[0], file) | ||||
| 	assertMultipartFileHeader(t, &s.ArrayValues[0], file) | ||||
| 	assertMultipartFileHeader(t, s.ArrayPtrs[0], file) | ||||
| } | ||||
| 
 | ||||
| func TestFormMultipartBindingBindTwoFiles(t *testing.T) { | ||||
| 	var s struct { | ||||
| 		SliceValues []multipart.FileHeader   `form:"file"` | ||||
| 		SlicePtrs   []*multipart.FileHeader  `form:"file"` | ||||
| 		ArrayValues [2]multipart.FileHeader  `form:"file"` | ||||
| 		ArrayPtrs   [2]*multipart.FileHeader `form:"file"` | ||||
| 	} | ||||
| 	files := []testFile{ | ||||
| 		{"file", "file1", []byte("hello")}, | ||||
| 		{"file", "file2", []byte("world")}, | ||||
| 	} | ||||
| 
 | ||||
| 	req := createRequestMultipartFiles(t, files...) | ||||
| 	err := FormMultipart.Bind(req, &s) | ||||
| 	assert.NoError(t, err) | ||||
| 
 | ||||
| 	assert.Len(t, s.SliceValues, len(files)) | ||||
| 	assert.Len(t, s.SlicePtrs, len(files)) | ||||
| 	assert.Len(t, s.ArrayValues, len(files)) | ||||
| 	assert.Len(t, s.ArrayPtrs, len(files)) | ||||
| 
 | ||||
| 	for i, file := range files { | ||||
| 		assertMultipartFileHeader(t, &s.SliceValues[i], file) | ||||
| 		assertMultipartFileHeader(t, s.SlicePtrs[i], file) | ||||
| 		assertMultipartFileHeader(t, &s.ArrayValues[i], file) | ||||
| 		assertMultipartFileHeader(t, s.ArrayPtrs[i], file) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestFormMultipartBindingBindError(t *testing.T) { | ||||
| 	files := []testFile{ | ||||
| 		{"file", "file1", []byte("hello")}, | ||||
| 		{"file", "file2", []byte("world")}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tt := range []struct { | ||||
| 		name string | ||||
| 		s    interface{} | ||||
| 	}{ | ||||
| 		{"wrong type", &struct { | ||||
| 			Files int `form:"file"` | ||||
| 		}{}}, | ||||
| 		{"wrong array size", &struct { | ||||
| 			Files [1]*multipart.FileHeader `form:"file"` | ||||
| 		}{}}, | ||||
| 		{"wrong slice type", &struct { | ||||
| 			Files []int `form:"file"` | ||||
| 		}{}}, | ||||
| 	} { | ||||
| 		req := createRequestMultipartFiles(t, files...) | ||||
| 		err := FormMultipart.Bind(req, tt.s) | ||||
| 		assert.Error(t, err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type testFile struct { | ||||
| 	Fieldname string | ||||
| 	Filename  string | ||||
| 	Content   []byte | ||||
| } | ||||
| 
 | ||||
| func createRequestMultipartFiles(t *testing.T, files ...testFile) *http.Request { | ||||
| 	var body bytes.Buffer | ||||
| 
 | ||||
| 	mw := multipart.NewWriter(&body) | ||||
| 	for _, file := range files { | ||||
| 		fw, err := mw.CreateFormFile(file.Fieldname, file.Filename) | ||||
| 		assert.NoError(t, err) | ||||
| 
 | ||||
| 		n, err := fw.Write(file.Content) | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.Equal(t, len(file.Content), n) | ||||
| 	} | ||||
| 	err := mw.Close() | ||||
| 	assert.NoError(t, err) | ||||
| 
 | ||||
| 	req, err := http.NewRequest("POST", "/", &body) | ||||
| 	assert.NoError(t, err) | ||||
| 
 | ||||
| 	req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+mw.Boundary()) | ||||
| 	return req | ||||
| } | ||||
| 
 | ||||
| func assertMultipartFileHeader(t *testing.T, fh *multipart.FileHeader, file testFile) { | ||||
| 	assert.Equal(t, file.Filename, fh.Filename) | ||||
| 	// assert.Equal(t, int64(len(file.Content)), fh.Size) // fh.Size does not exist on go1.8
 | ||||
| 
 | ||||
| 	fl, err := fh.Open() | ||||
| 	assert.NoError(t, err) | ||||
| 
 | ||||
| 	body, err := ioutil.ReadAll(fl) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.Equal(t, string(file.Content), string(body)) | ||||
| 
 | ||||
| 	err = fl.Close() | ||||
| 	assert.NoError(t, err) | ||||
| } | ||||
|  | @ -1,228 +0,0 @@ | |||
| // Copyright 2014 Manu Martinez-Almeida.  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 ( | ||||
| 	"bytes" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"go-playground/validator/v10" | ||||
| ) | ||||
| 
 | ||||
| type testInterface interface { | ||||
| 	String() string | ||||
| } | ||||
| 
 | ||||
| type substructNoValidation struct { | ||||
| 	IString string | ||||
| 	IInt    int | ||||
| } | ||||
| 
 | ||||
| type mapNoValidationSub map[string]substructNoValidation | ||||
| 
 | ||||
| type structNoValidationValues struct { | ||||
| 	substructNoValidation | ||||
| 
 | ||||
| 	Boolean bool | ||||
| 
 | ||||
| 	Uinteger   uint | ||||
| 	Integer    int | ||||
| 	Integer8   int8 | ||||
| 	Integer16  int16 | ||||
| 	Integer32  int32 | ||||
| 	Integer64  int64 | ||||
| 	Uinteger8  uint8 | ||||
| 	Uinteger16 uint16 | ||||
| 	Uinteger32 uint32 | ||||
| 	Uinteger64 uint64 | ||||
| 
 | ||||
| 	Float32 float32 | ||||
| 	Float64 float64 | ||||
| 
 | ||||
| 	String string | ||||
| 
 | ||||
| 	Date time.Time | ||||
| 
 | ||||
| 	Struct        substructNoValidation | ||||
| 	InlinedStruct struct { | ||||
| 		String  []string | ||||
| 		Integer int | ||||
| 	} | ||||
| 
 | ||||
| 	IntSlice           []int | ||||
| 	IntPointerSlice    []*int | ||||
| 	StructPointerSlice []*substructNoValidation | ||||
| 	StructSlice        []substructNoValidation | ||||
| 	InterfaceSlice     []testInterface | ||||
| 
 | ||||
| 	UniversalInterface interface{} | ||||
| 	CustomInterface    testInterface | ||||
| 
 | ||||
| 	FloatMap  map[string]float32 | ||||
| 	StructMap mapNoValidationSub | ||||
| } | ||||
| 
 | ||||
| func createNoValidationValues() structNoValidationValues { | ||||
| 	integer := 1 | ||||
| 	s := structNoValidationValues{ | ||||
| 		Boolean:            true, | ||||
| 		Uinteger:           1 << 29, | ||||
| 		Integer:            -10000, | ||||
| 		Integer8:           120, | ||||
| 		Integer16:          -20000, | ||||
| 		Integer32:          1 << 29, | ||||
| 		Integer64:          1 << 61, | ||||
| 		Uinteger8:          250, | ||||
| 		Uinteger16:         50000, | ||||
| 		Uinteger32:         1 << 31, | ||||
| 		Uinteger64:         1 << 62, | ||||
| 		Float32:            123.456, | ||||
| 		Float64:            123.456789, | ||||
| 		String:             "text", | ||||
| 		Date:               time.Time{}, | ||||
| 		CustomInterface:    &bytes.Buffer{}, | ||||
| 		Struct:             substructNoValidation{}, | ||||
| 		IntSlice:           []int{-3, -2, 1, 0, 1, 2, 3}, | ||||
| 		IntPointerSlice:    []*int{&integer}, | ||||
| 		StructSlice:        []substructNoValidation{}, | ||||
| 		UniversalInterface: 1.2, | ||||
| 		FloatMap: map[string]float32{ | ||||
| 			"foo": 1.23, | ||||
| 			"bar": 232.323, | ||||
| 		}, | ||||
| 		StructMap: mapNoValidationSub{ | ||||
| 			"foo": substructNoValidation{}, | ||||
| 			"bar": substructNoValidation{}, | ||||
| 		}, | ||||
| 		// StructPointerSlice []noValidationSub
 | ||||
| 		// InterfaceSlice     []testInterface
 | ||||
| 	} | ||||
| 	s.InlinedStruct.Integer = 1000 | ||||
| 	s.InlinedStruct.String = []string{"first", "second"} | ||||
| 	s.IString = "substring" | ||||
| 	s.IInt = 987654 | ||||
| 	return s | ||||
| } | ||||
| 
 | ||||
| func TestValidateNoValidationValues(t *testing.T) { | ||||
| 	origin := createNoValidationValues() | ||||
| 	test := createNoValidationValues() | ||||
| 	empty := structNoValidationValues{} | ||||
| 
 | ||||
| 	assert.Nil(t, validate(test)) | ||||
| 	assert.Nil(t, validate(&test)) | ||||
| 	assert.Nil(t, validate(empty)) | ||||
| 	assert.Nil(t, validate(&empty)) | ||||
| 
 | ||||
| 	assert.Equal(t, origin, test) | ||||
| } | ||||
| 
 | ||||
| type structNoValidationPointer struct { | ||||
| 	substructNoValidation | ||||
| 
 | ||||
| 	Boolean bool | ||||
| 
 | ||||
| 	Uinteger   *uint | ||||
| 	Integer    *int | ||||
| 	Integer8   *int8 | ||||
| 	Integer16  *int16 | ||||
| 	Integer32  *int32 | ||||
| 	Integer64  *int64 | ||||
| 	Uinteger8  *uint8 | ||||
| 	Uinteger16 *uint16 | ||||
| 	Uinteger32 *uint32 | ||||
| 	Uinteger64 *uint64 | ||||
| 
 | ||||
| 	Float32 *float32 | ||||
| 	Float64 *float64 | ||||
| 
 | ||||
| 	String *string | ||||
| 
 | ||||
| 	Date *time.Time | ||||
| 
 | ||||
| 	Struct *substructNoValidation | ||||
| 
 | ||||
| 	IntSlice           *[]int | ||||
| 	IntPointerSlice    *[]*int | ||||
| 	StructPointerSlice *[]*substructNoValidation | ||||
| 	StructSlice        *[]substructNoValidation | ||||
| 	InterfaceSlice     *[]testInterface | ||||
| 
 | ||||
| 	FloatMap  *map[string]float32 | ||||
| 	StructMap *mapNoValidationSub | ||||
| } | ||||
| 
 | ||||
| func TestValidateNoValidationPointers(t *testing.T) { | ||||
| 	//origin := createNoValidation_values()
 | ||||
| 	//test := createNoValidation_values()
 | ||||
| 	empty := structNoValidationPointer{} | ||||
| 
 | ||||
| 	//assert.Nil(t, validate(test))
 | ||||
| 	//assert.Nil(t, validate(&test))
 | ||||
| 	assert.Nil(t, validate(empty)) | ||||
| 	assert.Nil(t, validate(&empty)) | ||||
| 
 | ||||
| 	//assert.Equal(t, origin, test)
 | ||||
| } | ||||
| 
 | ||||
| type Object map[string]interface{} | ||||
| 
 | ||||
| func TestValidatePrimitives(t *testing.T) { | ||||
| 	obj := Object{"foo": "bar", "bar": 1} | ||||
| 	assert.NoError(t, validate(obj)) | ||||
| 	assert.NoError(t, validate(&obj)) | ||||
| 	assert.Equal(t, Object{"foo": "bar", "bar": 1}, obj) | ||||
| 
 | ||||
| 	obj2 := []Object{{"foo": "bar", "bar": 1}, {"foo": "bar", "bar": 1}} | ||||
| 	assert.NoError(t, validate(obj2)) | ||||
| 	assert.NoError(t, validate(&obj2)) | ||||
| 
 | ||||
| 	nu := 10 | ||||
| 	assert.NoError(t, validate(nu)) | ||||
| 	assert.NoError(t, validate(&nu)) | ||||
| 	assert.Equal(t, 10, nu) | ||||
| 
 | ||||
| 	str := "value" | ||||
| 	assert.NoError(t, validate(str)) | ||||
| 	assert.NoError(t, validate(&str)) | ||||
| 	assert.Equal(t, "value", str) | ||||
| } | ||||
| 
 | ||||
| // structCustomValidation is a helper struct we use to check that
 | ||||
| // custom validation can be registered on it.
 | ||||
| // The `notone` binding directive is for custom validation and registered later.
 | ||||
| type structCustomValidation struct { | ||||
| 	Integer int `binding:"notone"` | ||||
| } | ||||
| 
 | ||||
| func notOne(f1 validator.FieldLevel) bool { | ||||
| 	if val, ok := f1.Field().Interface().(int); ok { | ||||
| 		return val != 1 | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func TestValidatorEngine(t *testing.T) { | ||||
| 	// This validates that the function `notOne` matches
 | ||||
| 	// the expected function signature by `defaultValidator`
 | ||||
| 	// and by extension the validator library.
 | ||||
| 	engine, ok := Validator.Engine().(*validator.Validate) | ||||
| 	assert.True(t, ok) | ||||
| 
 | ||||
| 	err := engine.RegisterValidation("notone", notOne) | ||||
| 	// Check that we can register custom validation without error
 | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	// Create an instance which will fail validation
 | ||||
| 	withOne := structCustomValidation{Integer: 1} | ||||
| 	errs := validate(withOne) | ||||
| 
 | ||||
| 	// Check that we got back non-nil errs
 | ||||
| 	assert.NotNil(t, errs) | ||||
| 	// Check that the error matches expectation
 | ||||
| 	assert.Error(t, errs, "", "", "notone") | ||||
| } | ||||
|  | @ -1,25 +0,0 @@ | |||
| // 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 ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
| 
 | ||||
| func TestXMLBindingBindBody(t *testing.T) { | ||||
| 	var s struct { | ||||
| 		Foo string `xml:"foo"` | ||||
| 	} | ||||
| 	xmlBody := `<?xml version="1.0" encoding="UTF-8"?> | ||||
| <root> | ||||
|    <foo>FOO</foo> | ||||
| </root>` | ||||
| 	err := xmlBinding{}.BindBody([]byte(xmlBody), &s) | ||||
| 	require.NoError(t, err) | ||||
| 	assert.Equal(t, "FOO", s.Foo) | ||||
| } | ||||
|  | @ -1,21 +0,0 @@ | |||
| // 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 ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
| 
 | ||||
| func TestYAMLBindingBindBody(t *testing.T) { | ||||
| 	var s struct { | ||||
| 		Foo string `yaml:"foo"` | ||||
| 	} | ||||
| 	err := yamlBinding{}.BindBody([]byte("foo: FOO"), &s) | ||||
| 	require.NoError(t, err) | ||||
| 	assert.Equal(t, "FOO", s.Foo) | ||||
| } | ||||
|  | @ -86,7 +86,7 @@ type TransValidError struct { | |||
| func (e TransValidError) Error() string { | ||||
| 	return e.ErrorString | ||||
| } | ||||
| func (ve ValidationErrors) Translate(ut ut.Translator) TransValidError { | ||||
| func (ve ValidationErrors) Translate(ut ut.Translator) error { | ||||
| 	var result TransValidError | ||||
| 	var fe *fieldError | ||||
| 	if len(ve) == 0 { | ||||
|  |  | |||
							
								
								
									
										2
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										2
									
								
								go.mod
								
								
								
								
							|  | @ -1,4 +1,4 @@ | |||
| module git.ningdatech.com/ningda/gin_valid | ||||
| module git.hpds.cc/Component/gin_valid.git | ||||
| 
 | ||||
| go 1.13 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue