From 757d391c29c03677616fc03b6c74328a6e265cbb Mon Sep 17 00:00:00 2001 From: Dean Karn Date: Sun, 19 Jul 2015 21:49:17 -0400 Subject: [PATCH 1/3] Update README.md updated CI to semaphore --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 36ac9da..d785383 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Package validator ================ [![Join the chat at https://gitter.im/bluesuncorp/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bluesuncorp/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build Status](https://travis-ci.org/bluesuncorp/validator.svg?branch=v5.1)](https://travis-ci.org/bluesuncorp/validator) +[![Build Status](https://semaphoreci.com/api/v1/projects/ec20115f-ef1b-4c7d-9393-cc76aba74eb4/487384/badge.svg)](https://semaphoreci.com/joeybloggs/validator) [![Coverage Status](https://coveralls.io/repos/bluesuncorp/validator/badge.svg?branch=v5)](https://coveralls.io/r/bluesuncorp/validator?branch=v5) [![GoDoc](https://godoc.org/gopkg.in/bluesuncorp/validator.v5?status.svg)](https://godoc.org/gopkg.in/bluesuncorp/validator.v5) From aa3fec1835961a9a52db2aa2912a1fabc095b733 Mon Sep 17 00:00:00 2001 From: Dean Karn Date: Sun, 19 Jul 2015 21:49:46 -0400 Subject: [PATCH 2/3] Delete .travis.yml no longer needed changed CI to semaphore --- .travis.yml | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 389db22..0000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: go - -notificaitons: - email: - recipients: bluesuncorp01@gmail.com - on_success: change - on_failure: always - -go: - - 1.3 - - 1.4 - - tip - -script: - - go get golang.org/x/tools/cmd/cover - - go get github.com/mattn/goveralls - - go test -v -covermode=count -coverprofile=cover.out - -after_success: - - goveralls -coverprofile=cover.out -service=travis-ci -repotoken I6M8FiXZzErImgwMotJ7fwFlHOX8Hqdq1 \ No newline at end of file From b870cbab2f76cd9c8130c7e50be531b690605b8e Mon Sep 17 00:00:00 2001 From: joeybloggs Date: Tue, 28 Jul 2015 09:28:12 -0400 Subject: [PATCH 3/3] Porting Back fixes from v6 --- baked_in.go | 10 +++--- doc.go | 5 +-- validator.go | 14 ++++++-- validator_test.go | 82 +++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 100 insertions(+), 11 deletions(-) diff --git a/baked_in.go b/baked_in.go index 0e394bd..82868cc 100644 --- a/baked_in.go +++ b/baked_in.go @@ -424,10 +424,12 @@ func hasValue(top interface{}, current interface{}, field interface{}, param str st := reflect.ValueOf(field) switch st.Kind() { - - case reflect.Slice, reflect.Map, reflect.Array: - return field != nil && int64(st.Len()) > 0 - + case reflect.Invalid: + return false + case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: + return !st.IsNil() + case reflect.Array: + return field != reflect.Zero(reflect.TypeOf(field)).Interface() default: return field != nil && field != reflect.Zero(reflect.TypeOf(field)).Interface() } diff --git a/doc.go b/doc.go index f45ef34..ba6f934 100644 --- a/doc.go +++ b/doc.go @@ -193,9 +193,10 @@ Here is a list of the current built in validators: within its SliceOrArrayErrs or MapErrs fields. required - This validates that the value is not the data types default value. + This validates that the value is not the data types default zero value. For numbers ensures value is not zero. For strings ensures value is - not "". For slices, arrays, and maps, ensures the length is not zero. + not "". For slices, maps, pointers, interfaces, channels and functions + ensures the value is not nil. (Usage: required) len diff --git a/validator.go b/validator.go index ccd2a55..e2c07d0 100644 --- a/validator.go +++ b/validator.go @@ -627,7 +627,11 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f f = valueField.Interface() } - cField = &cachedField{name: name, kind: valueField.Kind(), tag: tag, typ: valueField.Type()} + cField = &cachedField{name: name, kind: valueField.Kind(), tag: tag} + + if cField.kind != reflect.Invalid { + cField.typ = valueField.Type() + } switch cField.kind { case reflect.Slice, reflect.Array: @@ -648,8 +652,14 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f } switch cField.kind { + case reflect.Invalid: + return &FieldError{ + Field: cField.name, + Tag: cField.tag, + Kind: cField.kind, + } - case reflect.Struct, reflect.Interface, reflect.Invalid: + case reflect.Struct, reflect.Interface: if cField.typ != reflect.TypeOf(time.Time{}) { panic("Invalid field passed to fieldWithNameAndValue") diff --git a/validator_test.go b/validator_test.go index 8bfff9b..6fb08bb 100644 --- a/validator_test.go +++ b/validator_test.go @@ -231,6 +231,82 @@ func AssertMapFieldError(t *testing.T, s map[string]*FieldError, field string, e EqualSkip(t, 2, val.Tag, expectedTag) } +func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) { + + var m map[string]string + + errs := validate.Field(m, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + m = map[string]string{} + errs = validate.Field(m, "required") + Equal(t, errs, nil) + + var arr [5]string + errs = validate.Field(arr, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + arr[0] = "ok" + errs = validate.Field(arr, "required") + Equal(t, errs, nil) + + var s []string + errs = validate.Field(s, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + s = []string{} + errs = validate.Field(s, "required") + Equal(t, errs, nil) + + var c chan string + errs = validate.Field(c, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + c = make(chan string) + errs = validate.Field(c, "required") + Equal(t, errs, nil) + + var tst *int + errs = validate.Field(tst, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + one := 1 + tst = &one + errs = validate.Field(tst, "required") + Equal(t, errs, nil) + + var iface interface{} + + errs = validate.Field(iface, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + errs = validate.Field(iface, "omitempty,required") + Equal(t, errs, nil) + + errs = validate.Field(iface, "") + Equal(t, errs, nil) + + errs = validate.Field(iface, "len=1") + NotEqual(t, errs, nil) + + var f func(string) + + errs = validate.Field(f, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + f = func(name string) {} + + errs = validate.Field(f, "required") + Equal(t, errs, nil) +} + func TestBadKeyValidation(t *testing.T) { type Test struct { Name string `validate:"required, "` @@ -3735,14 +3811,14 @@ func TestStructSliceValidation(t *testing.T) { Min: []int{1, 2}, Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, MinMax: []int{1, 2, 3, 4, 5}, - OmitEmpty: []int{}, + OmitEmpty: nil, } err := validate.Struct(tSuccess) Equal(t, err, nil) tFail := &TestSlice{ - Required: []int{}, + Required: nil, Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, Min: []int{}, Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, @@ -3810,7 +3886,7 @@ func TestPoolObjectMaxSizeValidation(t *testing.T) { Min: []int{1, 2}, Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, MinMax: []int{1, 2, 3, 4, 5}, - OmitEmpty: []int{}, + OmitEmpty: nil, } for i := 0; i < 2; i++ {