diff --git a/README.md b/README.md
index 7583259..4f52d21 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,12 @@
Package validator
================
-
+
[![Join the chat at https://gitter.im/bluesuncorp/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-![Project status](https://img.shields.io/badge/version-8.18.1-green.svg)
+![Project status](https://img.shields.io/badge/alpha-9.0.0-red.svg)
[![Build Status](https://semaphoreci.com/api/v1/projects/ec20115f-ef1b-4c7d-9393-cc76aba74eb4/530054/badge.svg)](https://semaphoreci.com/joeybloggs/validator)
-[![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=v8&service=github)](https://coveralls.io/github/go-playground/validator?branch=v8)
+[![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=v9&service=github)](https://coveralls.io/github/go-playground/validator?branch=v9)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator)
-[![GoDoc](https://godoc.org/gopkg.in/go-playground/validator.v8?status.svg)](https://godoc.org/gopkg.in/go-playground/validator.v8)
+[![GoDoc](https://godoc.org/gopkg.in/go-playground/validator.v9?status.svg)](https://godoc.org/gopkg.in/go-playground/validator.v8)
![License](https://img.shields.io/dub/l/vibe-d.svg)
Package validator implements value validations for structs and individual fields based on tags.
@@ -25,15 +25,15 @@ Installation
Use go get.
- go get gopkg.in/go-playground/validator.v8
+ go get gopkg.in/go-playground/validator.v9
or to update
- go get -u gopkg.in/go-playground/validator.v8
+ go get -u gopkg.in/go-playground/validator.v9
Then import the validator package into your own code.
- import "gopkg.in/go-playground/validator.v8"
+ import "gopkg.in/go-playground/validator.v9"
Error Return Value
-------
@@ -57,7 +57,7 @@ validationErrors := err.(validator.ValidationErrors)
Usage and documentation
------
-Please see http://godoc.org/gopkg.in/go-playground/validator.v8 for detailed usage docs.
+Please see http://godoc.org/gopkg.in/go-playground/validator.v9 for detailed usage docs.
##### Examples:
@@ -68,7 +68,7 @@ package main
import (
"fmt"
- "gopkg.in/go-playground/validator.v8"
+ "gopkg.in/go-playground/validator.v9"
)
// User contains user information
@@ -211,7 +211,7 @@ import (
"fmt"
"reflect"
- "gopkg.in/go-playground/validator.v8"
+ "gopkg.in/go-playground/validator.v9"
)
// User contains user information
@@ -346,21 +346,13 @@ Complimentary Software
Here is a list of software that compliments using this library either pre or post validation.
-* [Gorilla Schema](https://github.com/gorilla/schema) - Package gorilla/schema fills a struct with form values.
+* [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.
* [Conform](https://github.com/leebenson/conform) - Trims, sanitizes & scrubs data based on struct tags.
How to Contribute
------
-There will always be a development branch for each version i.e. `v1-development`. In order to contribute,
-please make your pull requests against those branches.
-
-If the changes being proposed or requested are breaking changes, please create an issue, for discussion
-or create a pull request against the highest development branch for example this package has a
-v1 and v1-development branch however, there will also be a v2-development branch even though v2 doesn't exist yet.
-
-I strongly encourage everyone whom creates a custom validation function to contribute them and
-help make this package even better.
+Make a pull request...
License
------
diff --git a/baked_in.go b/baked_in.go
index 44aaa08..f5dee2a 100644
--- a/baked_in.go
+++ b/baked_in.go
@@ -10,156 +10,171 @@ import (
"unicode/utf8"
)
-// BakedInAliasValidators is a default mapping of a single validationstag that
-// defines a common or complex set of validation(s) to simplify
-// adding validation to structs. i.e. set key "_ageok" and the tags
-// are "gt=0,lte=130" or key "_preferredname" and tags "omitempty,gt=0,lte=60"
-var bakedInAliasValidators = map[string]string{
- "iscolor": "hexcolor|rgb|rgba|hsl|hsla",
-}
-
-// BakedInValidators is the default map of ValidationFunc
-// you can add, remove or even replace items to suite your needs,
-// or even disregard and use your own map if so desired.
-var bakedInValidators = map[string]Func{
- "required": HasValue,
- "len": HasLengthOf,
- "min": HasMinOf,
- "max": HasMaxOf,
- "eq": IsEq,
- "ne": IsNe,
- "lt": IsLt,
- "lte": IsLte,
- "gt": IsGt,
- "gte": IsGte,
- "eqfield": IsEqField,
- "eqcsfield": IsEqCrossStructField,
- "necsfield": IsNeCrossStructField,
- "gtcsfield": IsGtCrossStructField,
- "gtecsfield": IsGteCrossStructField,
- "ltcsfield": IsLtCrossStructField,
- "ltecsfield": IsLteCrossStructField,
- "nefield": IsNeField,
- "gtefield": IsGteField,
- "gtfield": IsGtField,
- "ltefield": IsLteField,
- "ltfield": IsLtField,
- "alpha": IsAlpha,
- "alphanum": IsAlphanum,
- "numeric": IsNumeric,
- "number": IsNumber,
- "hexadecimal": IsHexadecimal,
- "hexcolor": IsHEXColor,
- "rgb": IsRGB,
- "rgba": IsRGBA,
- "hsl": IsHSL,
- "hsla": IsHSLA,
- "email": IsEmail,
- "url": IsURL,
- "uri": IsURI,
- "base64": IsBase64,
- "contains": Contains,
- "containsany": ContainsAny,
- "containsrune": ContainsRune,
- "excludes": Excludes,
- "excludesall": ExcludesAll,
- "excludesrune": ExcludesRune,
- "isbn": IsISBN,
- "isbn10": IsISBN10,
- "isbn13": IsISBN13,
- "uuid": IsUUID,
- "uuid3": IsUUID3,
- "uuid4": IsUUID4,
- "uuid5": IsUUID5,
- "ascii": IsASCII,
- "printascii": IsPrintableASCII,
- "multibyte": HasMultiByteCharacter,
- "datauri": IsDataURI,
- "latitude": IsLatitude,
- "longitude": IsLongitude,
- "ssn": IsSSN,
- "ipv4": IsIPv4,
- "ipv6": IsIPv6,
- "ip": IsIP,
- "cidrv4": IsCIDRv4,
- "cidrv6": IsCIDRv6,
- "cidr": IsCIDR,
- "tcp4_addr": IsTCP4AddrResolvable,
- "tcp6_addr": IsTCP6AddrResolvable,
- "tcp_addr": IsTCPAddrResolvable,
- "udp4_addr": IsUDP4AddrResolvable,
- "udp6_addr": IsUDP6AddrResolvable,
- "udp_addr": IsUDPAddrResolvable,
- "ip4_addr": IsIP4AddrResolvable,
- "ip6_addr": IsIP6AddrResolvable,
- "ip_addr": IsIPAddrResolvable,
- "unix_addr": IsUnixAddrResolvable,
- "mac": IsMAC,
-}
+// Func accepts all values needed for file and cross field validation
+// fl = FieldLevel validation helper
+// field = field value for validation
+// fieldType = fields
+// param = parameter used in validation i.e. gt=0 param would be 0
+type Func func(fl FieldLevel) bool
+
+var (
+ restrictedTags = map[string]struct{}{
+ diveTag: {},
+ structOnlyTag: {},
+ omitempty: {},
+ skipValidationTag: {},
+ utf8HexComma: {},
+ utf8Pipe: {},
+ noStructLevelTag: {},
+ }
+
+ // BakedInAliasValidators is a default mapping of a single validation tag that
+ // defines a common or complex set of validation(s) to simplify
+ // adding validation to structs.
+ bakedInAliases = map[string]string{
+ "iscolor": "hexcolor|rgb|rgba|hsl|hsla",
+ }
+
+ // BakedInValidators is the default map of ValidationFunc
+ // you can add, remove or even replace items to suite your needs,
+ // or even disregard and use your own map if so desired.
+ bakedInValidators = map[string]Func{
+ "required": hasValue,
+ "len": hasLengthOf,
+ "min": hasMinOf,
+ "max": hasMaxOf,
+ "eq": isEq,
+ "ne": isNe,
+ "lt": isLt,
+ "lte": isLte,
+ "gt": isGt,
+ "gte": isGte,
+ "eqfield": isEqField,
+ "eqcsfield": isEqCrossStructField,
+ "necsfield": isNeCrossStructField,
+ "gtcsfield": isGtCrossStructField,
+ "gtecsfield": isGteCrossStructField,
+ "ltcsfield": isLtCrossStructField,
+ "ltecsfield": isLteCrossStructField,
+ "nefield": isNeField,
+ "gtefield": isGteField,
+ "gtfield": isGtField,
+ "ltefield": isLteField,
+ "ltfield": isLtField,
+ "alpha": isAlpha,
+ "alphanum": isAlphanum,
+ "numeric": isNumeric,
+ "number": isNumber,
+ "hexadecimal": isHexadecimal,
+ "hexcolor": isHEXColor,
+ "rgb": isRGB,
+ "rgba": isRGBA,
+ "hsl": isHSL,
+ "hsla": isHSLA,
+ "email": isEmail,
+ "url": isURL,
+ "uri": isURI,
+ "base64": isBase64,
+ "contains": contains,
+ "containsany": containsAny,
+ "containsrune": containsRune,
+ "excludes": excludes,
+ "excludesall": excludesAll,
+ "excludesrune": excludesRune,
+ "isbn": isISBN,
+ "isbn10": isISBN10,
+ "isbn13": isISBN13,
+ "uuid": isUUID,
+ "uuid3": isUUID3,
+ "uuid4": isUUID4,
+ "uuid5": isUUID5,
+ "ascii": isASCII,
+ "printascii": isPrintableASCII,
+ "multibyte": hasMultiByteCharacter,
+ "datauri": isDataURI,
+ "latitude": isLatitude,
+ "longitude": isLongitude,
+ "ssn": isSSN,
+ "ipv4": isIPv4,
+ "ipv6": isIPv6,
+ "ip": isIP,
+ "cidrv4": isCIDRv4,
+ "cidrv6": isCIDRv6,
+ "cidr": isCIDR,
+ "tcp4_addr": isTCP4AddrResolvable,
+ "tcp6_addr": isTCP6AddrResolvable,
+ "tcp_addr": isTCPAddrResolvable,
+ "udp4_addr": isUDP4AddrResolvable,
+ "udp6_addr": isUDP6AddrResolvable,
+ "udp_addr": isUDPAddrResolvable,
+ "ip4_addr": isIP4AddrResolvable,
+ "ip6_addr": isIP6AddrResolvable,
+ "ip_addr": isIPAddrResolvable,
+ "unix_addr": isUnixAddrResolvable,
+ "mac": isMAC,
+ }
+)
// IsMAC is the validation function for validating if the field's value is a valid MAC address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsMAC(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- _, err := net.ParseMAC(field.String())
+func isMAC(fl FieldLevel) bool {
+
+ _, err := net.ParseMAC(fl.Field().String())
+
return err == nil
}
// IsCIDRv4 is the validation function for validating if the field's value is a valid v4 CIDR address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsCIDRv4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isCIDRv4(fl FieldLevel) bool {
- ip, _, err := net.ParseCIDR(field.String())
+ ip, _, err := net.ParseCIDR(fl.Field().String())
return err == nil && ip.To4() != nil
}
// IsCIDRv6 is the validation function for validating if the field's value is a valid v6 CIDR address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsCIDRv6(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isCIDRv6(fl FieldLevel) bool {
- ip, _, err := net.ParseCIDR(field.String())
+ ip, _, err := net.ParseCIDR(fl.Field().String())
return err == nil && ip.To4() == nil
}
// IsCIDR is the validation function for validating if the field's value is a valid v4 or v6 CIDR address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsCIDR(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isCIDR(fl FieldLevel) bool {
- _, _, err := net.ParseCIDR(field.String())
+ _, _, err := net.ParseCIDR(fl.Field().String())
return err == nil
}
// IsIPv4 is the validation function for validating if a value is a valid v4 IP address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsIPv4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isIPv4(fl FieldLevel) bool {
- ip := net.ParseIP(field.String())
+ ip := net.ParseIP(fl.Field().String())
return ip != nil && ip.To4() != nil
}
// IsIPv6 is the validation function for validating if the field's value is a valid v6 IP address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsIPv6(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- ip := net.ParseIP(field.String())
+func isIPv6(fl FieldLevel) bool {
+
+ ip := net.ParseIP(fl.Field().String())
return ip != nil && ip.To4() == nil
}
// IsIP is the validation function for validating if the field's value is a valid v4 or v6 IP address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsIP(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isIP(fl FieldLevel) bool {
- ip := net.ParseIP(field.String())
+ ip := net.ParseIP(fl.Field().String())
return ip != nil
}
// IsSSN is the validation function for validating if the field's value is a valid SSN.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsSSN(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isSSN(fl FieldLevel) bool {
+
+ field := fl.Field()
if field.Len() != 11 {
return false
@@ -169,22 +184,19 @@ func IsSSN(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Va
}
// IsLongitude is the validation function for validating if the field's value is a valid longitude coordinate.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsLongitude(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return longitudeRegex.MatchString(field.String())
+func isLongitude(fl FieldLevel) bool {
+ return longitudeRegex.MatchString(fl.Field().String())
}
// IsLatitude is the validation function for validating if the field's value is a valid latitude coordinate.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsLatitude(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return latitudeRegex.MatchString(field.String())
+func isLatitude(fl FieldLevel) bool {
+ return latitudeRegex.MatchString(fl.Field().String())
}
// IsDataURI is the validation function for validating if the field's value is a valid data URI.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsDataURI(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isDataURI(fl FieldLevel) bool {
- uri := strings.SplitN(field.String(), ",", 2)
+ uri := strings.SplitN(fl.Field().String(), ",", 2)
if len(uri) != 2 {
return false
@@ -194,14 +206,13 @@ func IsDataURI(v *Validate, topStruct reflect.Value, currentStructOrField reflec
return false
}
- fld := reflect.ValueOf(uri[1])
-
- return IsBase64(v, topStruct, currentStructOrField, fld, fld.Type(), fld.Kind(), param)
+ return base64Regex.MatchString(uri[1])
}
// HasMultiByteCharacter is the validation function for validating if the field's value has a multi byte character.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func HasMultiByteCharacter(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func hasMultiByteCharacter(fl FieldLevel) bool {
+
+ field := fl.Field()
if field.Len() == 0 {
return true
@@ -211,52 +222,44 @@ func HasMultiByteCharacter(v *Validate, topStruct reflect.Value, currentStructOr
}
// IsPrintableASCII is the validation function for validating if the field's value is a valid printable ASCII character.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsPrintableASCII(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return printableASCIIRegex.MatchString(field.String())
+func isPrintableASCII(fl FieldLevel) bool {
+ return printableASCIIRegex.MatchString(fl.Field().String())
}
// IsASCII is the validation function for validating if the field's value is a valid ASCII character.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsASCII(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return aSCIIRegex.MatchString(field.String())
+func isASCII(fl FieldLevel) bool {
+ return aSCIIRegex.MatchString(fl.Field().String())
}
// IsUUID5 is the validation function for validating if the field's value is a valid v5 UUID.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsUUID5(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return uUID5Regex.MatchString(field.String())
+func isUUID5(fl FieldLevel) bool {
+ return uUID5Regex.MatchString(fl.Field().String())
}
// IsUUID4 is the validation function for validating if the field's value is a valid v4 UUID.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsUUID4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return uUID4Regex.MatchString(field.String())
+func isUUID4(fl FieldLevel) bool {
+ return uUID4Regex.MatchString(fl.Field().String())
}
// IsUUID3 is the validation function for validating if the field's value is a valid v3 UUID.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsUUID3(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return uUID3Regex.MatchString(field.String())
+func isUUID3(fl FieldLevel) bool {
+ return uUID3Regex.MatchString(fl.Field().String())
}
// IsUUID is the validation function for validating if the field's value is a valid UUID of any version.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsUUID(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return uUIDRegex.MatchString(field.String())
+func isUUID(fl FieldLevel) bool {
+ return uUIDRegex.MatchString(fl.Field().String())
}
// IsISBN is the validation function for validating if the field's value is a valid v10 or v13 ISBN.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsISBN(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return IsISBN10(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) || IsISBN13(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
+func isISBN(fl FieldLevel) bool {
+ return isISBN10(fl) || isISBN13(fl)
}
// IsISBN13 is the validation function for validating if the field's value is a valid v13 ISBN.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsISBN13(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isISBN13(fl FieldLevel) bool {
- s := strings.Replace(strings.Replace(field.String(), "-", "", 4), " ", "", 4)
+ s := strings.Replace(strings.Replace(fl.Field().String(), "-", "", 4), " ", "", 4)
if !iSBN13Regex.MatchString(s) {
return false
@@ -275,10 +278,9 @@ func IsISBN13(v *Validate, topStruct reflect.Value, currentStructOrField reflect
}
// IsISBN10 is the validation function for validating if the field's value is a valid v10 ISBN.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsISBN10(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isISBN10(fl FieldLevel) bool {
- s := strings.Replace(strings.Replace(field.String(), "-", "", 3), " ", "", 3)
+ s := strings.Replace(strings.Replace(fl.Field().String(), "-", "", 3), " ", "", 3)
if !iSBN10Regex.MatchString(s) {
return false
@@ -301,54 +303,51 @@ func IsISBN10(v *Validate, topStruct reflect.Value, currentStructOrField reflect
}
// ExcludesRune is the validation function for validating that the field's value does not contain the rune specified within the param.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func ExcludesRune(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return !ContainsRune(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
+func excludesRune(fl FieldLevel) bool {
+ return !containsRune(fl)
}
// ExcludesAll is the validation function for validating that the field's value does not contain any of the characters specified within the param.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func ExcludesAll(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return !ContainsAny(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
+func excludesAll(fl FieldLevel) bool {
+ return !containsAny(fl)
}
// Excludes is the validation function for validating that the field's value does not contain the text specified within the param.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func Excludes(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return !Contains(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
+func excludes(fl FieldLevel) bool {
+ return !contains(fl)
}
// ContainsRune is the validation function for validating that the field's value contains the rune specified within the param.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func ContainsRune(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- r, _ := utf8.DecodeRuneInString(param)
+func containsRune(fl FieldLevel) bool {
- return strings.ContainsRune(field.String(), r)
+ r, _ := utf8.DecodeRuneInString(fl.Param())
+
+ return strings.ContainsRune(fl.Field().String(), r)
}
// ContainsAny is the validation function for validating that the field's value contains any of the characters specified within the param.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func ContainsAny(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return strings.ContainsAny(field.String(), param)
+func containsAny(fl FieldLevel) bool {
+ return strings.ContainsAny(fl.Field().String(), fl.Param())
}
// Contains is the validation function for validating that the field's value contains the text specified within the param.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func Contains(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return strings.Contains(field.String(), param)
+func contains(fl FieldLevel) bool {
+ return strings.Contains(fl.Field().String(), fl.Param())
}
// IsNeField is the validation function for validating if the current field's value is not equal to the field specified by the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsNeField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isNeField(fl FieldLevel) bool {
- currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
+ field := fl.Field()
+ kind := field.Kind()
- if !ok || currentKind != fieldKind {
+ currentField, currentKind, ok := fl.GetStructFieldOK()
+
+ if !ok || currentKind != kind {
return true
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() != currentField.Int()
@@ -364,6 +363,8 @@ func IsNeField(v *Validate, topStruct reflect.Value, currentStructOrField reflec
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return true
@@ -384,21 +385,22 @@ func IsNeField(v *Validate, topStruct reflect.Value, currentStructOrField reflec
}
// IsNe is the validation function for validating that the field's value does not equal the provided param value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsNe(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return !IsEq(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
+func isNe(fl FieldLevel) bool {
+ return !isEq(fl)
}
// IsLteCrossStructField is the validation function for validating if the current field's value is less than or equal to the field, within a separate struct, specified by the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsLteCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isLteCrossStructField(fl FieldLevel) bool {
- topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
- if !ok || topKind != fieldKind {
+ field := fl.Field()
+ kind := field.Kind()
+
+ topField, topKind, ok := fl.GetStructFieldOK()
+ if !ok || topKind != kind {
return false
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() <= topField.Int()
@@ -414,6 +416,8 @@ func IsLteCrossStructField(v *Validate, topStruct reflect.Value, current reflect
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
@@ -434,14 +438,17 @@ func IsLteCrossStructField(v *Validate, topStruct reflect.Value, current reflect
// IsLtCrossStructField is the validation function for validating if the current field's value is less than the field, within a separate struct, specified by the param's value.
// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsLtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isLtCrossStructField(fl FieldLevel) bool {
- topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
- if !ok || topKind != fieldKind {
+ field := fl.Field()
+ kind := field.Kind()
+
+ topField, topKind, ok := fl.GetStructFieldOK()
+ if !ok || topKind != kind {
return false
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() < topField.Int()
@@ -457,6 +464,8 @@ func IsLtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
@@ -476,15 +485,17 @@ func IsLtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.
}
// IsGteCrossStructField is the validation function for validating if the current field's value is greater than or equal to the field, within a separate struct, specified by the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsGteCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isGteCrossStructField(fl FieldLevel) bool {
+
+ field := fl.Field()
+ kind := field.Kind()
- topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
- if !ok || topKind != fieldKind {
+ topField, topKind, ok := fl.GetStructFieldOK()
+ if !ok || topKind != kind {
return false
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() >= topField.Int()
@@ -500,6 +511,8 @@ func IsGteCrossStructField(v *Validate, topStruct reflect.Value, current reflect
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
@@ -519,15 +532,17 @@ func IsGteCrossStructField(v *Validate, topStruct reflect.Value, current reflect
}
// IsGtCrossStructField is the validation function for validating if the current field's value is greater than the field, within a separate struct, specified by the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsGtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isGtCrossStructField(fl FieldLevel) bool {
+
+ field := fl.Field()
+ kind := field.Kind()
- topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
- if !ok || topKind != fieldKind {
+ topField, topKind, ok := fl.GetStructFieldOK()
+ if !ok || topKind != kind {
return false
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() > topField.Int()
@@ -543,6 +558,8 @@ func IsGtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
@@ -562,15 +579,17 @@ func IsGtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.
}
// IsNeCrossStructField is the validation function for validating that the current field's value is not equal to the field, within a separate struct, specified by the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsNeCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isNeCrossStructField(fl FieldLevel) bool {
- topField, currentKind, ok := v.GetStructFieldOK(topStruct, param)
- if !ok || currentKind != fieldKind {
+ field := fl.Field()
+ kind := field.Kind()
+
+ topField, currentKind, ok := fl.GetStructFieldOK()
+ if !ok || currentKind != kind {
return true
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return topField.Int() != field.Int()
@@ -586,6 +605,8 @@ func IsNeCrossStructField(v *Validate, topStruct reflect.Value, current reflect.
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return true
@@ -605,15 +626,17 @@ func IsNeCrossStructField(v *Validate, topStruct reflect.Value, current reflect.
}
// IsEqCrossStructField is the validation function for validating that the current field's value is equal to the field, within a separate struct, specified by the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsEqCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isEqCrossStructField(fl FieldLevel) bool {
+
+ field := fl.Field()
+ kind := field.Kind()
- topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
- if !ok || topKind != fieldKind {
+ topField, topKind, ok := fl.GetStructFieldOK()
+ if !ok || topKind != kind {
return false
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return topField.Int() == field.Int()
@@ -629,6 +652,8 @@ func IsEqCrossStructField(v *Validate, topStruct reflect.Value, current reflect.
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != topField.Type() {
return false
@@ -648,15 +673,17 @@ func IsEqCrossStructField(v *Validate, topStruct reflect.Value, current reflect.
}
// IsEqField is the validation function for validating if the current field's value is equal to the field specified by the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsEqField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isEqField(fl FieldLevel) bool {
- currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
- if !ok || currentKind != fieldKind {
+ field := fl.Field()
+ kind := field.Kind()
+
+ currentField, currentKind, ok := fl.GetStructFieldOK()
+ if !ok || currentKind != kind {
return false
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return field.Int() == currentField.Int()
@@ -672,6 +699,8 @@ func IsEqField(v *Validate, topStruct reflect.Value, currentStructOrField reflec
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
@@ -692,10 +721,12 @@ func IsEqField(v *Validate, topStruct reflect.Value, currentStructOrField reflec
}
// IsEq is the validation function for validating if the current field's value is equal to the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsEq(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isEq(fl FieldLevel) bool {
+
+ field := fl.Field()
+ param := fl.Param()
- switch fieldKind {
+ switch field.Kind() {
case reflect.String:
return field.String() == param
@@ -725,16 +756,16 @@ func IsEq(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Val
}
// IsBase64 is the validation function for validating if the current field's value is a valid base 64.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsBase64(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return base64Regex.MatchString(field.String())
+func isBase64(fl FieldLevel) bool {
+ return base64Regex.MatchString(fl.Field().String())
}
// IsURI is the validation function for validating if the current field's value is a valid URI.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsURI(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isURI(fl FieldLevel) bool {
- switch fieldKind {
+ field := fl.Field()
+
+ switch field.Kind() {
case reflect.String:
@@ -746,7 +777,7 @@ func IsURI(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Va
s = s[:i]
}
- if s == blank {
+ if len(s) == 0 {
return false
}
@@ -759,10 +790,11 @@ func IsURI(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Va
}
// IsURL is the validation function for validating if the current field's value is a valid URL.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsURL(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isURL(fl FieldLevel) bool {
+
+ field := fl.Field()
- switch fieldKind {
+ switch field.Kind() {
case reflect.String:
@@ -775,13 +807,13 @@ func IsURL(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Va
s = s[:i]
}
- if s == blank {
+ if len(s) == 0 {
return false
}
url, err := url.ParseRequestURI(s)
- if err != nil || url.Scheme == blank {
+ if err != nil || url.Scheme == "" {
return false
}
@@ -792,93 +824,85 @@ func IsURL(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Va
}
// IsEmail is the validation function for validating if the current field's value is a valid email address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsEmail(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return emailRegex.MatchString(field.String())
+func isEmail(fl FieldLevel) bool {
+ return emailRegex.MatchString(fl.Field().String())
}
// IsHSLA is the validation function for validating if the current field's value is a valid HSLA color.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsHSLA(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return hslaRegex.MatchString(field.String())
+func isHSLA(fl FieldLevel) bool {
+ return hslaRegex.MatchString(fl.Field().String())
}
// IsHSL is the validation function for validating if the current field's value is a valid HSL color.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsHSL(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return hslRegex.MatchString(field.String())
+func isHSL(fl FieldLevel) bool {
+ return hslRegex.MatchString(fl.Field().String())
}
// IsRGBA is the validation function for validating if the current field's value is a valid RGBA color.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsRGBA(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return rgbaRegex.MatchString(field.String())
+func isRGBA(fl FieldLevel) bool {
+ return rgbaRegex.MatchString(fl.Field().String())
}
// IsRGB is the validation function for validating if the current field's value is a valid RGB color.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsRGB(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return rgbRegex.MatchString(field.String())
+func isRGB(fl FieldLevel) bool {
+ return rgbRegex.MatchString(fl.Field().String())
}
// IsHEXColor is the validation function for validating if the current field's value is a valid HEX color.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsHEXColor(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return hexcolorRegex.MatchString(field.String())
+func isHEXColor(fl FieldLevel) bool {
+ return hexcolorRegex.MatchString(fl.Field().String())
}
// IsHexadecimal is the validation function for validating if the current field's value is a valid hexadecimal.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsHexadecimal(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return hexadecimalRegex.MatchString(field.String())
+func isHexadecimal(fl FieldLevel) bool {
+ return hexadecimalRegex.MatchString(fl.Field().String())
}
// IsNumber is the validation function for validating if the current field's value is a valid number.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsNumber(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return numberRegex.MatchString(field.String())
+func isNumber(fl FieldLevel) bool {
+ return numberRegex.MatchString(fl.Field().String())
}
// IsNumeric is the validation function for validating if the current field's value is a valid numeric value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsNumeric(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return numericRegex.MatchString(field.String())
+func isNumeric(fl FieldLevel) bool {
+ return numericRegex.MatchString(fl.Field().String())
}
// IsAlphanum is the validation function for validating if the current field's value is a valid alphanumeric value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsAlphanum(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return alphaNumericRegex.MatchString(field.String())
+func isAlphanum(fl FieldLevel) bool {
+ return alphaNumericRegex.MatchString(fl.Field().String())
}
// IsAlpha is the validation function for validating if the current field's value is a valid alpha value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsAlpha(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return alphaRegex.MatchString(field.String())
+func isAlpha(fl FieldLevel) bool {
+ return alphaRegex.MatchString(fl.Field().String())
}
// HasValue is the validation function for validating if the current field's value is not the default static value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func HasValue(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func hasValue(fl FieldLevel) bool {
+
+ field := fl.Field()
- switch fieldKind {
+ switch field.Kind() {
case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
return !field.IsNil()
default:
- return field.IsValid() && field.Interface() != reflect.Zero(fieldType).Interface()
+ return field.IsValid() && field.Interface() != reflect.Zero(field.Type()).Interface()
}
}
// IsGteField is the validation function for validating if the current field's value is greater than or equal to the field specified by the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsGteField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isGteField(fl FieldLevel) bool {
+
+ field := fl.Field()
+ kind := field.Kind()
- currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
- if !ok || currentKind != fieldKind {
+ currentField, currentKind, ok := fl.GetStructFieldOK()
+ if !ok || currentKind != kind {
return false
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@@ -894,6 +918,8 @@ func IsGteField(v *Validate, topStruct reflect.Value, currentStructOrField refle
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
@@ -913,15 +939,17 @@ func IsGteField(v *Validate, topStruct reflect.Value, currentStructOrField refle
}
// IsGtField is the validation function for validating if the current field's value is greater than the field specified by the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsGtField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isGtField(fl FieldLevel) bool {
+
+ field := fl.Field()
+ kind := field.Kind()
- currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
- if !ok || currentKind != fieldKind {
+ currentField, currentKind, ok := fl.GetStructFieldOK()
+ if !ok || currentKind != kind {
return false
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@@ -937,6 +965,8 @@ func IsGtField(v *Validate, topStruct reflect.Value, currentStructOrField reflec
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
@@ -956,10 +986,12 @@ func IsGtField(v *Validate, topStruct reflect.Value, currentStructOrField reflec
}
// IsGte is the validation function for validating if the current field's value is greater than or equal to the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsGte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isGte(fl FieldLevel) bool {
- switch fieldKind {
+ field := fl.Field()
+ param := fl.Param()
+
+ switch field.Kind() {
case reflect.String:
p := asInt(param)
@@ -988,7 +1020,7 @@ func IsGte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Va
case reflect.Struct:
- if fieldType == timeType || fieldType == timePtrType {
+ if field.Type() == timeType {
now := time.Now().UTC()
t := field.Interface().(time.Time)
@@ -1001,10 +1033,12 @@ func IsGte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Va
}
// IsGt is the validation function for validating if the current field's value is greater than the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsGt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isGt(fl FieldLevel) bool {
- switch fieldKind {
+ field := fl.Field()
+ param := fl.Param()
+
+ switch field.Kind() {
case reflect.String:
p := asInt(param)
@@ -1032,7 +1066,7 @@ func IsGt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Val
return field.Float() > p
case reflect.Struct:
- if fieldType == timeType || fieldType == timePtrType {
+ if field.Type() == timeType {
return field.Interface().(time.Time).After(time.Now().UTC())
}
@@ -1042,10 +1076,12 @@ func IsGt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Val
}
// HasLengthOf is the validation function for validating if the current field's value is equal to the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func HasLengthOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func hasLengthOf(fl FieldLevel) bool {
- switch fieldKind {
+ field := fl.Field()
+ param := fl.Param()
+
+ switch field.Kind() {
case reflect.String:
p := asInt(param)
@@ -1077,22 +1113,22 @@ func HasLengthOf(v *Validate, topStruct reflect.Value, currentStructOrField refl
}
// HasMinOf is the validation function for validating if the current field's value is greater than or equal to the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func HasMinOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
-
- return IsGte(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
+func hasMinOf(fl FieldLevel) bool {
+ return isGte(fl)
}
// IsLteField is the validation function for validating if the current field's value is less than or equal to the field specified by the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsLteField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isLteField(fl FieldLevel) bool {
- currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
- if !ok || currentKind != fieldKind {
+ field := fl.Field()
+ kind := field.Kind()
+
+ currentField, currentKind, ok := fl.GetStructFieldOK()
+ if !ok || currentKind != kind {
return false
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@@ -1108,6 +1144,8 @@ func IsLteField(v *Validate, topStruct reflect.Value, currentStructOrField refle
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
@@ -1127,15 +1165,17 @@ func IsLteField(v *Validate, topStruct reflect.Value, currentStructOrField refle
}
// IsLtField is the validation function for validating if the current field's value is less than the field specified by the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsLtField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isLtField(fl FieldLevel) bool {
+
+ field := fl.Field()
+ kind := field.Kind()
- currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
- if !ok || currentKind != fieldKind {
+ currentField, currentKind, ok := fl.GetStructFieldOK()
+ if !ok || currentKind != kind {
return false
}
- switch fieldKind {
+ switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@@ -1151,6 +1191,8 @@ func IsLtField(v *Validate, topStruct reflect.Value, currentStructOrField reflec
case reflect.Struct:
+ fieldType := field.Type()
+
// Not Same underlying type i.e. struct and time
if fieldType != currentField.Type() {
return false
@@ -1170,10 +1212,12 @@ func IsLtField(v *Validate, topStruct reflect.Value, currentStructOrField reflec
}
// IsLte is the validation function for validating if the current field's value is less than or equal to the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsLte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isLte(fl FieldLevel) bool {
+
+ field := fl.Field()
+ param := fl.Param()
- switch fieldKind {
+ switch field.Kind() {
case reflect.String:
p := asInt(param)
@@ -1202,7 +1246,7 @@ func IsLte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Va
case reflect.Struct:
- if fieldType == timeType || fieldType == timePtrType {
+ if field.Type() == timeType {
now := time.Now().UTC()
t := field.Interface().(time.Time)
@@ -1215,10 +1259,12 @@ func IsLte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Va
}
// IsLt is the validation function for validating if the current field's value is less than the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsLt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isLt(fl FieldLevel) bool {
+
+ field := fl.Field()
+ param := fl.Param()
- switch fieldKind {
+ switch field.Kind() {
case reflect.String:
p := asInt(param)
@@ -1247,7 +1293,7 @@ func IsLt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Val
case reflect.Struct:
- if fieldType == timeType || fieldType == timePtrType {
+ if field.Type() == timeType {
return field.Interface().(time.Time).Before(time.Now().UTC())
}
@@ -1257,144 +1303,141 @@ func IsLt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Val
}
// HasMaxOf is the validation function for validating if the current field's value is less than or equal to the param's value.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func HasMaxOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- return IsLte(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
+func hasMaxOf(fl FieldLevel) bool {
+ return isLte(fl)
}
// IsTCP4AddrResolvable is the validation function for validating if the field's value is a resolvable tcp4 address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsTCP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isTCP4AddrResolvable(fl FieldLevel) bool {
- if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
+ if !isIP4Addr(fl) {
return false
}
- _, err := net.ResolveTCPAddr("tcp4", field.String())
+ _, err := net.ResolveTCPAddr("tcp4", fl.Field().String())
return err == nil
}
// IsTCP6AddrResolvable is the validation function for validating if the field's value is a resolvable tcp6 address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsTCP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isTCP6AddrResolvable(fl FieldLevel) bool {
- if !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
+ if !isIP6Addr(fl) {
return false
}
- _, err := net.ResolveTCPAddr("tcp6", field.String())
+ _, err := net.ResolveTCPAddr("tcp6", fl.Field().String())
+
return err == nil
}
// IsTCPAddrResolvable is the validation function for validating if the field's value is a resolvable tcp address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsTCPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isTCPAddrResolvable(fl FieldLevel) bool {
- if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) &&
- !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
+ if !isIP4Addr(fl) && !isIP6Addr(fl) {
return false
}
- _, err := net.ResolveTCPAddr("tcp", field.String())
+ _, err := net.ResolveTCPAddr("tcp", fl.Field().String())
+
return err == nil
}
// IsUDP4AddrResolvable is the validation function for validating if the field's value is a resolvable udp4 address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsUDP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isUDP4AddrResolvable(fl FieldLevel) bool {
- if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
+ if !isIP4Addr(fl) {
return false
}
- _, err := net.ResolveUDPAddr("udp4", field.String())
+ _, err := net.ResolveUDPAddr("udp4", fl.Field().String())
+
return err == nil
}
// IsUDP6AddrResolvable is the validation function for validating if the field's value is a resolvable udp6 address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsUDP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isUDP6AddrResolvable(fl FieldLevel) bool {
- if !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
+ if !isIP6Addr(fl) {
return false
}
- _, err := net.ResolveUDPAddr("udp6", field.String())
+ _, err := net.ResolveUDPAddr("udp6", fl.Field().String())
+
return err == nil
}
// IsUDPAddrResolvable is the validation function for validating if the field's value is a resolvable udp address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsUDPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isUDPAddrResolvable(fl FieldLevel) bool {
- if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) &&
- !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
+ if !isIP4Addr(fl) && !isIP6Addr(fl) {
return false
}
- _, err := net.ResolveUDPAddr("udp", field.String())
+ _, err := net.ResolveUDPAddr("udp", fl.Field().String())
+
return err == nil
}
// IsIP4AddrResolvable is the validation function for validating if the field's value is a resolvable ip4 address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsIP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isIP4AddrResolvable(fl FieldLevel) bool {
- if !IsIPv4(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
+ if !isIPv4(fl) {
return false
}
- _, err := net.ResolveIPAddr("ip4", field.String())
+ _, err := net.ResolveIPAddr("ip4", fl.Field().String())
+
return err == nil
}
// IsIP6AddrResolvable is the validation function for validating if the field's value is a resolvable ip6 address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsIP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isIP6AddrResolvable(fl FieldLevel) bool {
- if !IsIPv6(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
+ if !isIPv6(fl) {
return false
}
- _, err := net.ResolveIPAddr("ip6", field.String())
+ _, err := net.ResolveIPAddr("ip6", fl.Field().String())
+
return err == nil
}
// IsIPAddrResolvable is the validation function for validating if the field's value is a resolvable ip address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsIPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+func isIPAddrResolvable(fl FieldLevel) bool {
- if !IsIP(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
+ if !isIP(fl) {
return false
}
- _, err := net.ResolveIPAddr("ip", field.String())
+ _, err := net.ResolveIPAddr("ip", fl.Field().String())
+
return err == nil
}
// IsUnixAddrResolvable is the validation function for validating if the field's value is a resolvable unix address.
-// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
-func IsUnixAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- _, err := net.ResolveUnixAddr("unix", field.String())
+func isUnixAddrResolvable(fl FieldLevel) bool {
+
+ _, err := net.ResolveUnixAddr("unix", fl.Field().String())
+
return err == nil
}
-func isIP4Addr(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- val := field.String()
+func isIP4Addr(fl FieldLevel) bool {
+
+ val := fl.Field().String()
if idx := strings.LastIndex(val, ":"); idx != -1 {
val = val[0:idx]
}
- if !IsIPv4(v, topStruct, currentStructOrField, reflect.ValueOf(val), fieldType, fieldKind, param) {
- return false
- }
+ ip := net.ParseIP(val)
- return true
+ return ip != nil && ip.To4() != nil
}
-func isIP6Addr(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- val := field.String()
+func isIP6Addr(fl FieldLevel) bool {
+
+ val := fl.Field().String()
if idx := strings.LastIndex(val, ":"); idx != -1 {
if idx != 0 && val[idx-1:idx] == "]" {
@@ -1402,9 +1445,7 @@ func isIP6Addr(v *Validate, topStruct reflect.Value, currentStructOrField reflec
}
}
- if !IsIPv6(v, topStruct, currentStructOrField, reflect.ValueOf(val), fieldType, fieldKind, param) {
- return false
- }
+ ip := net.ParseIP(val)
- return true
+ return ip != nil && ip.To4() == nil
}
diff --git a/benchmarks_test.go b/benchmarks_test.go
index 84db743..c369243 100644
--- a/benchmarks_test.go
+++ b/benchmarks_test.go
@@ -8,28 +8,38 @@ import (
func BenchmarkFieldSuccess(b *testing.B) {
+ validate := New()
+
var s *string
tmp := "1"
s = &tmp
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
- validate.Field(s, "len=1")
+ validate.Var(s, "len=1")
}
}
func BenchmarkFieldFailure(b *testing.B) {
+ validate := New()
+
var s *string
tmp := "12"
s = &tmp
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
- validate.Field(s, "len=1")
+ validate.Var(s, "len=1")
}
}
func BenchmarkFieldDiveSuccess(b *testing.B) {
+ validate := New()
+
m := make([]*string, 3)
t1 := "val1"
t2 := "val2"
@@ -39,13 +49,17 @@ func BenchmarkFieldDiveSuccess(b *testing.B) {
m[1] = &t2
m[2] = &t3
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
- validate.Field(m, "required,dive,required")
+ validate.Var(m, "required,dive,required")
}
}
func BenchmarkFieldDiveFailure(b *testing.B) {
+ validate := New()
+
m := make([]*string, 3)
t1 := "val1"
t2 := ""
@@ -55,65 +69,84 @@ func BenchmarkFieldDiveFailure(b *testing.B) {
m[1] = &t2
m[2] = &t3
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
- validate.Field(m, "required,dive,required")
+ validate.Var(m, "required,dive,required")
}
}
func BenchmarkFieldCustomTypeSuccess(b *testing.B) {
+ validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{
Name: "1",
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
- validate.Field(val, "len=1")
+ validate.Var(val, "len=1")
}
}
func BenchmarkFieldCustomTypeFailure(b *testing.B) {
+ validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
- validate.Field(val, "len=1")
+ validate.Var(val, "len=1")
}
}
func BenchmarkFieldOrTagSuccess(b *testing.B) {
+ validate := New()
+
var s *string
tmp := "rgba(0,0,0,1)"
s = &tmp
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
- validate.Field(s, "rgb|rgba")
+ validate.Var(s, "rgb|rgba")
}
}
func BenchmarkFieldOrTagFailure(b *testing.B) {
+ validate := New()
+
var s *string
tmp := "#000"
s = &tmp
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
- validate.Field(s, "rgb|rgba")
+ validate.Var(s, "rgb|rgba")
}
}
func BenchmarkStructLevelValidationSuccess(b *testing.B) {
+ validate := New()
validate.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{})
tst := &TestStruct{
String: "good value",
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(tst)
}
@@ -121,12 +154,15 @@ func BenchmarkStructLevelValidationSuccess(b *testing.B) {
func BenchmarkStructLevelValidationFailure(b *testing.B) {
+ validate := New()
validate.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
tst := &TestStruct{
String: "good value",
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(tst)
}
@@ -134,6 +170,7 @@ func BenchmarkStructLevelValidationFailure(b *testing.B) {
func BenchmarkStructSimpleCustomTypeSuccess(b *testing.B) {
+ validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{
@@ -147,6 +184,8 @@ func BenchmarkStructSimpleCustomTypeSuccess(b *testing.B) {
validFoo := &Foo{Valuer: val, IntValue: 7}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(validFoo)
}
@@ -154,6 +193,7 @@ func BenchmarkStructSimpleCustomTypeSuccess(b *testing.B) {
func BenchmarkStructSimpleCustomTypeFailure(b *testing.B) {
+ validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
val := valuer{}
@@ -165,6 +205,8 @@ func BenchmarkStructSimpleCustomTypeFailure(b *testing.B) {
validFoo := &Foo{Valuer: val, IntValue: 3}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(validFoo)
}
@@ -172,6 +214,8 @@ func BenchmarkStructSimpleCustomTypeFailure(b *testing.B) {
func BenchmarkStructPartialSuccess(b *testing.B) {
+ validate := New()
+
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
@@ -181,6 +225,8 @@ func BenchmarkStructPartialSuccess(b *testing.B) {
Name: "Joey Bloggs",
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.StructPartial(test, "Name")
}
@@ -188,6 +234,8 @@ func BenchmarkStructPartialSuccess(b *testing.B) {
func BenchmarkStructPartialFailure(b *testing.B) {
+ validate := New()
+
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
@@ -197,6 +245,8 @@ func BenchmarkStructPartialFailure(b *testing.B) {
Name: "Joey Bloggs",
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.StructPartial(test, "NickName")
}
@@ -204,6 +254,8 @@ func BenchmarkStructPartialFailure(b *testing.B) {
func BenchmarkStructExceptSuccess(b *testing.B) {
+ validate := New()
+
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
@@ -213,6 +265,8 @@ func BenchmarkStructExceptSuccess(b *testing.B) {
Name: "Joey Bloggs",
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.StructPartial(test, "Nickname")
}
@@ -220,6 +274,8 @@ func BenchmarkStructExceptSuccess(b *testing.B) {
func BenchmarkStructExceptFailure(b *testing.B) {
+ validate := New()
+
type Test struct {
Name string `validate:"required"`
NickName string `validate:"required"`
@@ -229,6 +285,8 @@ func BenchmarkStructExceptFailure(b *testing.B) {
Name: "Joey Bloggs",
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.StructPartial(test, "Name")
}
@@ -236,6 +294,8 @@ func BenchmarkStructExceptFailure(b *testing.B) {
func BenchmarkStructSimpleCrossFieldSuccess(b *testing.B) {
+ validate := New()
+
type Test struct {
Start time.Time
End time.Time `validate:"gtfield=Start"`
@@ -249,6 +309,8 @@ func BenchmarkStructSimpleCrossFieldSuccess(b *testing.B) {
End: then,
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(test)
}
@@ -256,6 +318,8 @@ func BenchmarkStructSimpleCrossFieldSuccess(b *testing.B) {
func BenchmarkStructSimpleCrossFieldFailure(b *testing.B) {
+ validate := New()
+
type Test struct {
Start time.Time
End time.Time `validate:"gtfield=Start"`
@@ -269,6 +333,8 @@ func BenchmarkStructSimpleCrossFieldFailure(b *testing.B) {
End: then,
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(test)
}
@@ -276,6 +342,8 @@ func BenchmarkStructSimpleCrossFieldFailure(b *testing.B) {
func BenchmarkStructSimpleCrossStructCrossFieldSuccess(b *testing.B) {
+ validate := New()
+
type Inner struct {
Start time.Time
}
@@ -296,6 +364,8 @@ func BenchmarkStructSimpleCrossStructCrossFieldSuccess(b *testing.B) {
CreatedAt: now,
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(outer)
}
@@ -303,6 +373,8 @@ func BenchmarkStructSimpleCrossStructCrossFieldSuccess(b *testing.B) {
func BenchmarkStructSimpleCrossStructCrossFieldFailure(b *testing.B) {
+ validate := New()
+
type Inner struct {
Start time.Time
}
@@ -324,6 +396,8 @@ func BenchmarkStructSimpleCrossStructCrossFieldFailure(b *testing.B) {
CreatedAt: now,
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(outer)
}
@@ -331,6 +405,8 @@ func BenchmarkStructSimpleCrossStructCrossFieldFailure(b *testing.B) {
func BenchmarkStructSimpleSuccess(b *testing.B) {
+ validate := New()
+
type Foo struct {
StringValue string `validate:"min=5,max=10"`
IntValue int `validate:"min=5,max=10"`
@@ -338,6 +414,8 @@ func BenchmarkStructSimpleSuccess(b *testing.B) {
validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(validFoo)
}
@@ -345,6 +423,8 @@ func BenchmarkStructSimpleSuccess(b *testing.B) {
func BenchmarkStructSimpleFailure(b *testing.B) {
+ validate := New()
+
type Foo struct {
StringValue string `validate:"min=5,max=10"`
IntValue int `validate:"min=5,max=10"`
@@ -352,6 +432,8 @@ func BenchmarkStructSimpleFailure(b *testing.B) {
invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(invalidFoo)
}
@@ -359,6 +441,8 @@ func BenchmarkStructSimpleFailure(b *testing.B) {
func BenchmarkStructSimpleSuccessParallel(b *testing.B) {
+ validate := New()
+
type Foo struct {
StringValue string `validate:"min=5,max=10"`
IntValue int `validate:"min=5,max=10"`
@@ -366,6 +450,8 @@ func BenchmarkStructSimpleSuccessParallel(b *testing.B) {
validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
+ b.ReportAllocs()
+
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
validate.Struct(validFoo)
@@ -375,6 +461,8 @@ func BenchmarkStructSimpleSuccessParallel(b *testing.B) {
func BenchmarkStructSimpleFailureParallel(b *testing.B) {
+ validate := New()
+
type Foo struct {
StringValue string `validate:"min=5,max=10"`
IntValue int `validate:"min=5,max=10"`
@@ -382,6 +470,8 @@ func BenchmarkStructSimpleFailureParallel(b *testing.B) {
invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
+ b.ReportAllocs()
+
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
validate.Struct(invalidFoo)
@@ -391,6 +481,8 @@ func BenchmarkStructSimpleFailureParallel(b *testing.B) {
func BenchmarkStructComplexSuccess(b *testing.B) {
+ validate := New()
+
tSuccess := &TestString{
Required: "Required",
Len: "length==10",
@@ -418,6 +510,8 @@ func BenchmarkStructComplexSuccess(b *testing.B) {
},
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(tSuccess)
}
@@ -425,6 +519,8 @@ func BenchmarkStructComplexSuccess(b *testing.B) {
func BenchmarkStructComplexFailure(b *testing.B) {
+ validate := New()
+
tFail := &TestString{
Required: "",
Len: "",
@@ -449,6 +545,8 @@ func BenchmarkStructComplexFailure(b *testing.B) {
},
}
+ b.ReportAllocs()
+
for n := 0; n < b.N; n++ {
validate.Struct(tFail)
}
@@ -456,6 +554,8 @@ func BenchmarkStructComplexFailure(b *testing.B) {
func BenchmarkStructComplexSuccessParallel(b *testing.B) {
+ validate := New()
+
tSuccess := &TestString{
Required: "Required",
Len: "length==10",
@@ -483,6 +583,8 @@ func BenchmarkStructComplexSuccessParallel(b *testing.B) {
},
}
+ b.ReportAllocs()
+
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
validate.Struct(tSuccess)
@@ -492,6 +594,8 @@ func BenchmarkStructComplexSuccessParallel(b *testing.B) {
func BenchmarkStructComplexFailureParallel(b *testing.B) {
+ validate := New()
+
tFail := &TestString{
Required: "",
Len: "",
@@ -516,6 +620,8 @@ func BenchmarkStructComplexFailureParallel(b *testing.B) {
},
}
+ b.ReportAllocs()
+
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
validate.Struct(tFail)
diff --git a/cache.go b/cache.go
index 76670c1..7534ea7 100644
--- a/cache.go
+++ b/cache.go
@@ -2,6 +2,7 @@ package validator
import (
"fmt"
+ "log"
"reflect"
"strings"
"sync"
@@ -20,6 +21,15 @@ const (
typeExists
)
+const (
+ invalidValidation = "Invalid validation tag on field %s"
+ undefinedValidation = "Undefined validation function on field %s"
+)
+
+// var (
+// validatable = reflect.ValueOf((*Validatable)(nil)).Elem()
+// )
+
type structCache struct {
lock sync.Mutex
m atomic.Value // map[reflect.Type]*cStruct
@@ -105,6 +115,15 @@ func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStr
cs = &cStruct{Name: sName, fields: make(map[int]*cField), fn: v.structLevelFuncs[typ]}
+ if vable, ok := reflect.PtrTo(typ).(Validatable); ok {
+
+ if cs.fn != nil {
+ log.Println("warning: struct level validation overriding 'Validatabe' interface function")
+ } else {
+ cs.fn = vable.Validate
+ }
+ }
+
numFields := current.NumField()
var ctag *cTag
@@ -116,7 +135,7 @@ func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStr
fld = typ.Field(i)
- if !fld.Anonymous && fld.PkgPath != blank {
+ if !fld.Anonymous && len(fld.PkgPath) > 0 {
continue
}
@@ -128,12 +147,11 @@ func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStr
customName = fld.Name
- if v.fieldNameTag != blank {
+ if v.hasTagNameFunc {
- name := strings.SplitN(fld.Tag.Get(v.fieldNameTag), ",", 2)[0]
+ name := v.tagNameFunc(fld)
- // dash check is for json "-" (aka skipValidationTag) means don't output in json
- if name != "" && name != skipValidationTag {
+ if len(name) > 0 {
customName = name
}
}
@@ -142,7 +160,7 @@ func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStr
// and so only struct level caching can be used instead of combined with Field tag caching
if len(tag) > 0 {
- ctag, _ = v.parseFieldTagsRecursive(tag, fld.Name, blank, false)
+ ctag, _ = v.parseFieldTagsRecursive(tag, fld.Name, "", false)
} else {
// even if field doesn't have validations need cTag for traversing to potential inner/nested
// elements of the field.
@@ -172,20 +190,18 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s
alias = t
}
- if v.hasAliasValidators {
- // check map for alias and process new tags, otherwise process as usual
- if tagsVal, found := v.aliasValidators[t]; found {
-
- if i == 0 {
- firstCtag, current = v.parseFieldTagsRecursive(tagsVal, fieldName, t, true)
- } else {
- next, curr := v.parseFieldTagsRecursive(tagsVal, fieldName, t, true)
- current.next, current = next, curr
+ // check map for alias and process new tags, otherwise process as usual
+ if tagsVal, found := v.aliases[t]; found {
- }
+ if i == 0 {
+ firstCtag, current = v.parseFieldTagsRecursive(tagsVal, fieldName, t, true)
+ } else {
+ next, curr := v.parseFieldTagsRecursive(tagsVal, fieldName, t, true)
+ current.next, current = next, curr
- continue
}
+
+ continue
}
if i == 0 {
@@ -214,10 +230,6 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s
current.typeof = typeNoStructLevel
continue
- case existsTag:
- current.typeof = typeExists
- continue
-
default:
// if a pipe character is needed within the param you must use the utf8Pipe representation "0x7C"
@@ -244,7 +256,7 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s
panic(strings.TrimSpace(fmt.Sprintf(invalidValidation, fieldName)))
}
- if current.fn, ok = v.validationFuncs[current.tag]; !ok {
+ if current.fn, ok = v.validations[current.tag]; !ok {
panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, fieldName)))
}
diff --git a/doc.go b/doc.go
index fdede2c..e44356d 100644
--- a/doc.go
+++ b/doc.go
@@ -192,17 +192,6 @@ Same as structonly tag except that any struct level validations will not run.
Usage: nostructlevel
-Exists
-
-Is a special tag without a validation function attached. It is used when a field
-is a Pointer, Interface or Invalid and you wish to validate that it exists.
-Example: want to ensure a bool exists if you define the bool as a pointer and
-use exists it will ensure there is a value; couldn't use required as it would
-fail when the bool was false. exists will fail is the value is a Pointer, Interface
-or Invalid and is nil.
-
- Usage: exists
-
Omit Empty
Allows conditional validation, for example if a field is not set with
diff --git a/errors.go b/errors.go
new file mode 100644
index 0000000..ce46333
--- /dev/null
+++ b/errors.go
@@ -0,0 +1,202 @@
+package validator
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "strings"
+)
+
+const (
+ fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag"
+)
+
+// InvalidValidationError describes an invalid argument passed to
+// `Struct`, `StructExcept`, StructPartial` or `Field`
+type InvalidValidationError struct {
+ Type reflect.Type
+}
+
+// Error returns InvalidValidationError message
+func (e *InvalidValidationError) Error() string {
+
+ if e.Type == nil {
+ return "validator: (nil)"
+ }
+
+ return "validator: (nil " + e.Type.String() + ")"
+}
+
+// ValidationErrors is an array of FieldError's
+// for use in custom error messages post validation.
+type ValidationErrors []FieldError
+
+// Error is intended for use in development + debugging and not intended to be a production error message.
+// It allows ValidationErrors to subscribe to the Error interface.
+// All information to create an error message specific to your application is contained within
+// the FieldError found within the ValidationErrors array
+func (ve ValidationErrors) Error() string {
+
+ buff := bytes.NewBufferString("")
+
+ var err *fieldError
+
+ for i := 0; i < len(ve); i++ {
+
+ err = ve[i].(*fieldError)
+ buff.WriteString(err.Error())
+ buff.WriteString("\n")
+ }
+
+ return strings.TrimSpace(buff.String())
+}
+
+// FieldError contains all functions to get error details
+type FieldError interface {
+
+ // returns the validation tag that failed. if the
+ // validation was an alias, this will return the
+ // alias name and not the underlying tag that failed.
+ //
+ // eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
+ // will return "iscolor"
+ Tag() string
+
+ // returns the validation tag that failed, even if an
+ // alias the actual tag within the alias will be returned.
+ // If an 'or' validation fails the entire or will be returned.
+ //
+ // eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
+ // will return "hexcolor|rgb|rgba|hsl|hsla"
+ ActualTag() string
+
+ // returns the namespace for the field error, with the tag
+ // name taking precedence over the fields actual name.
+ //
+ // eq. JSON name "User.fname" see ActualNamespace for comparison
+ //
+ // NOTE: this field can be blank when validating a single primitive field
+ // using validate.Field(...) as there is no way to extract it's name
+ Namespace() string
+
+ // returns the namespace for the field error, with the fields
+ // actual name.
+ //
+ // eq. "User.FirstName" see Namespace for comparison
+ //
+ // NOTE: this field can be blank when validating a single primitive field
+ // using validate.Field(...) as there is no way to extract it's name
+ ActualNamespace() string
+
+ // returns the fields name with the tag name taking precedence over the
+ // fields actual name.
+ //
+ // eq. JSON name "fname"
+ // see ActualField for comparison
+ Field() string
+
+ // returns the fields actual name.
+ //
+ // eq. "FirstName"
+ // see Field for comparison
+ ActualField() string
+
+ // returns the actual fields value in case needed for creating the error
+ // message
+ Value() interface{}
+
+ // returns the param value, already converted into the fields type for
+ // comparison; this will also help with generating an error message
+ Param() interface{}
+
+ // Kind returns the Field's reflect Kind
+ //
+ // eg. time.Time's kind is a struct
+ Kind() reflect.Kind
+
+ // Type returns the Field's reflect Type
+ //
+ // // eg. time.Time's type is time.Time
+ Type() reflect.Type
+}
+
+// compile time interface checks
+var _ FieldError = new(fieldError)
+var _ error = new(fieldError)
+
+// fieldError contains a single field's validation error along
+// with other properties that may be needed for error message creation
+// it complies with the FieldError interface
+type fieldError struct {
+ tag string
+ actualTag string
+ ns string
+ actualNs string
+ field string
+ actualField string
+ value interface{}
+ param interface{}
+ kind reflect.Kind
+ typ reflect.Type
+}
+
+// Tag returns the validation tag that failed.
+func (fe *fieldError) Tag() string {
+ return fe.tag
+}
+
+// ActualTag returns the validation tag that failed, even if an
+// alias the actual tag within the alias will be returned.
+func (fe *fieldError) ActualTag() string {
+ return fe.actualTag
+}
+
+// Namespace returns the namespace for the field error, with the tag
+// name taking precedence over the fields actual name.
+func (fe *fieldError) Namespace() string {
+ return fe.ns
+}
+
+// ActualNamespace returns the namespace for the field error, with the fields
+// actual name.
+func (fe *fieldError) ActualNamespace() string {
+ return fe.actualNs
+}
+
+// Field returns the fields name with the tag name taking precedence over the
+// fields actual name.
+func (fe *fieldError) Field() string {
+ return fe.field
+}
+
+// ActualField returns the fields actual name.
+func (fe *fieldError) ActualField() string {
+ return fe.actualField
+}
+
+// Value returns the actual fields value in case needed for creating the error
+// message
+func (fe *fieldError) Value() interface{} {
+ return fe.value
+}
+
+// Param returns the param value, already converted into the fields type for
+// comparison; this will also help with generating an error message
+func (fe *fieldError) Param() interface{} {
+ return fe.param
+}
+
+// Kind returns the Field's reflect Kind
+func (fe *fieldError) Kind() reflect.Kind {
+ return fe.kind
+}
+
+// Type returns the Field's reflect Type
+func (fe *fieldError) Type() reflect.Type {
+ return fe.typ
+}
+
+// Error returns the fieldError's error message
+func (fe *fieldError) Error() string {
+ return fmt.Sprintf(fieldErrMsg, fe.ns, fe.field, fe.tag)
+}
diff --git a/examples_test.go b/examples_test.go
index fde2246..3f4df7e 100644
--- a/examples_test.go
+++ b/examples_test.go
@@ -1,83 +1,83 @@
package validator_test
-import (
- "fmt"
-
- "gopkg.in/go-playground/validator.v8"
-)
-
-func ExampleValidate_new() {
- config := &validator.Config{TagName: "validate"}
-
- validator.New(config)
-}
-
-func ExampleValidate_field() {
- // This should be stored somewhere globally
- var validate *validator.Validate
-
- config := &validator.Config{TagName: "validate"}
-
- validate = validator.New(config)
-
- i := 0
- errs := validate.Field(i, "gt=1,lte=10")
- err := errs.(validator.ValidationErrors)[""]
- fmt.Println(err.Field)
- fmt.Println(err.Tag)
- fmt.Println(err.Kind) // NOTE: Kind and Type can be different i.e. time Kind=struct and Type=time.Time
- fmt.Println(err.Type)
- fmt.Println(err.Param)
- fmt.Println(err.Value)
- //Output:
- //
- //gt
- //int
- //int
- //1
- //0
-}
-
-func ExampleValidate_struct() {
- // This should be stored somewhere globally
- var validate *validator.Validate
-
- config := &validator.Config{TagName: "validate"}
-
- validate = validator.New(config)
-
- type ContactInformation struct {
- Phone string `validate:"required"`
- Street string `validate:"required"`
- City string `validate:"required"`
- }
-
- type User struct {
- Name string `validate:"required,excludesall=!@#$%^&*()_+-=:;?/0x2C"` // 0x2C = comma (,)
- Age int8 `validate:"required,gt=0,lt=150"`
- Email string `validate:"email"`
- ContactInformation []*ContactInformation
- }
-
- contactInfo := &ContactInformation{
- Street: "26 Here Blvd.",
- City: "Paradeso",
- }
-
- user := &User{
- Name: "Joey Bloggs",
- Age: 31,
- Email: "joeybloggs@gmail.com",
- ContactInformation: []*ContactInformation{contactInfo},
- }
-
- errs := validate.Struct(user)
- for _, v := range errs.(validator.ValidationErrors) {
- fmt.Println(v.Field) // Phone
- fmt.Println(v.Tag) // required
- //... and so forth
- //Output:
- //Phone
- //required
- }
-}
+// import (
+// "fmt"
+
+// "gopkg.in/go-playground/validator.v8"
+// )
+
+// func ExampleValidate_new() {
+// config := &validator.Config{TagName: "validate"}
+
+// validator.New(config)
+// }
+
+// func ExampleValidate_field() {
+// // This should be stored somewhere globally
+// var validate *validator.Validate
+
+// config := &validator.Config{TagName: "validate"}
+
+// validate = validator.New(config)
+
+// i := 0
+// errs := validate.Field(i, "gt=1,lte=10")
+// err := errs.(validator.ValidationErrors)[""]
+// fmt.Println(err.Field)
+// fmt.Println(err.Tag)
+// fmt.Println(err.Kind) // NOTE: Kind and Type can be different i.e. time Kind=struct and Type=time.Time
+// fmt.Println(err.Type)
+// fmt.Println(err.Param)
+// fmt.Println(err.Value)
+// //Output:
+// //
+// //gt
+// //int
+// //int
+// //1
+// //0
+// }
+
+// func ExampleValidate_struct() {
+// // This should be stored somewhere globally
+// var validate *validator.Validate
+
+// config := &validator.Config{TagName: "validate"}
+
+// validate = validator.New(config)
+
+// type ContactInformation struct {
+// Phone string `validate:"required"`
+// Street string `validate:"required"`
+// City string `validate:"required"`
+// }
+
+// type User struct {
+// Name string `validate:"required,excludesall=!@#$%^&*()_+-=:;?/0x2C"` // 0x2C = comma (,)
+// Age int8 `validate:"required,gt=0,lt=150"`
+// Email string `validate:"email"`
+// ContactInformation []*ContactInformation
+// }
+
+// contactInfo := &ContactInformation{
+// Street: "26 Here Blvd.",
+// City: "Paradeso",
+// }
+
+// user := &User{
+// Name: "Joey Bloggs",
+// Age: 31,
+// Email: "joeybloggs@gmail.com",
+// ContactInformation: []*ContactInformation{contactInfo},
+// }
+
+// errs := validate.Struct(user)
+// for _, v := range errs.(validator.ValidationErrors) {
+// fmt.Println(v.Field) // Phone
+// fmt.Println(v.Tag) // required
+// //... and so forth
+// //Output:
+// //Phone
+// //required
+// }
+// }
diff --git a/field_level.go b/field_level.go
new file mode 100644
index 0000000..4ffb5f3
--- /dev/null
+++ b/field_level.go
@@ -0,0 +1,50 @@
+package validator
+
+import "reflect"
+
+// FieldLevel contains all the information and helper functions
+// to validate a field
+type FieldLevel interface {
+
+ // returns the top level struct, if any
+ Top() reflect.Value
+
+ // returns the current fields parent struct, if any
+ Parent() reflect.Value
+
+ // returns current field for validation
+ Field() reflect.Value
+
+ // returns param for validation against current field
+ Param() string
+
+ // ExtractType gets the actual underlying type of field value.
+ // It will dive into pointers, customTypes and return you the
+ // underlying value and it's kind.
+ ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)
+
+ // traverses the parent struct to retrieve a specific field denoted by the provided namespace
+ // in the param and returns the field, field kind and whether is was successful in retrieving
+ // the field at all.
+ //
+ // NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field
+ // could not be retrieved because it didn't exist.
+ GetStructFieldOK() (reflect.Value, reflect.Kind, bool)
+}
+
+var _ FieldLevel = new(validate)
+
+// Field returns current field for validation
+func (v *validate) Field() reflect.Value {
+ return v.flField
+}
+
+// Param returns param for validation against current field
+func (v *validate) Param() string {
+ return v.flParam
+}
+
+// GetStructFieldOK returns Param returns param for validation against current field
+func (v *validate) GetStructFieldOK() (reflect.Value, reflect.Kind, bool) {
+ return v.getStructFieldOKInternal(v.slflParent, v.flParam)
+}
diff --git a/struct_level.go b/struct_level.go
new file mode 100644
index 0000000..33bfd59
--- /dev/null
+++ b/struct_level.go
@@ -0,0 +1,166 @@
+package validator
+
+import "reflect"
+
+// StructLevelFunc accepts all values needed for struct level validation
+type StructLevelFunc func(sl StructLevel)
+
+// StructLevel contains all the information and helper functions
+// to validate a struct
+type StructLevel interface {
+
+ // returns the main validation object, in case one want to call validations internally.
+ Validator() *Validate
+
+ // returns the top level struct, if any
+ Top() reflect.Value
+
+ // returns the current fields parent struct, if any
+ Parent() reflect.Value
+
+ // returns the current struct.
+ // this is not needed when implementing 'Validatable' interface,
+ // only when a StructLevel is registered
+ Current() reflect.Value
+
+ // ExtractType gets the actual underlying type of field value.
+ // It will dive into pointers, customTypes and return you the
+ // underlying value and it's kind.
+ ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)
+
+ // reports an error just by passing the field and tag information
+ //
+ // NOTES:
+ //
+ // fieldName and altName get appended to the existing namespace that
+ // validator is on. eg. pass 'FirstName' or 'Names[0]' depending
+ // on the nesting
+ //
+ // tag can be an existing validation tag or just something you make up
+ // and process on the flip side it's up to you.
+ ReportError(field interface{}, fieldName, altName, tag string)
+
+ // reports an error just by passing ValidationErrors
+ //
+ // NOTES:
+ //
+ // relativeNamespace and relativeActualNamespace get appended to the
+ // existing namespace that validator is on.
+ // eg. pass 'User.FirstName' or 'Users[0].FirstName' depending
+ // on the nesting. most of the time they will be blank, unless you validate
+ // at a level lower the the current field depth
+ //
+ // tag can be an existing validation tag or just something you make up
+ // and process on the flip side it's up to you.
+ ReportValidationErrors(relativeNamespace, relativeActualNamespace string, errs ValidationErrors)
+}
+
+var _ StructLevel = new(validate)
+
+// Top returns the top level struct
+//
+// NOTE: this can be the same as the current struct being validated
+// if not is a nested struct.
+//
+// this is only called when within Struct and Field Level validation and
+// should not be relied upon for an acurate value otherwise.
+func (v *validate) Top() reflect.Value {
+ return v.top
+}
+
+// Parent returns the current structs parent
+//
+// NOTE: this can be the same as the current struct being validated
+// if not is a nested struct.
+//
+// this is only called when within Struct and Field Level validation and
+// should not be relied upon for an acurate value otherwise.
+func (v *validate) Parent() reflect.Value {
+ return v.slflParent
+}
+
+// Current returns the current struct.
+func (v *validate) Current() reflect.Value {
+ return v.slCurrent
+}
+
+// Validator returns the main validation object, in case one want to call validations internally.
+func (v *validate) Validator() *Validate {
+ return v.v
+}
+
+// ExtractType gets the actual underlying type of field value.
+func (v *validate) ExtractType(field reflect.Value) (reflect.Value, reflect.Kind, bool) {
+ return v.extractTypeInternal(field, false)
+}
+
+// ReportError reports an error just by passing the field and tag information
+func (v *validate) ReportError(field interface{}, fieldName, altName, tag string) {
+
+ fv, kind, _ := v.extractTypeInternal(reflect.ValueOf(field), false)
+
+ if len(altName) == 0 {
+ altName = fieldName
+ }
+
+ ns := append(v.slNs, fieldName...)
+ nsActual := append(v.slActualNs, altName...)
+
+ switch kind {
+ case reflect.Invalid:
+
+ v.errs = append(v.errs,
+ &fieldError{
+ tag: tag,
+ actualTag: tag,
+ ns: string(ns),
+ actualNs: string(nsActual),
+ field: fieldName,
+ actualField: altName,
+ param: "",
+ kind: kind,
+ },
+ )
+
+ default:
+
+ v.errs = append(v.errs,
+ &fieldError{
+ tag: tag,
+ actualTag: tag,
+ ns: string(ns),
+ actualNs: string(nsActual),
+ field: fieldName,
+ actualField: altName,
+ value: fv.Interface(),
+ param: "",
+ kind: kind,
+ typ: fv.Type(),
+ },
+ )
+ }
+}
+
+// ReportValidationErrors reports ValidationErrors obtained from running validations within the Struct Level validation.
+//
+// NOTE: this function prepends the current namespace to the relative ones.
+func (v *validate) ReportValidationErrors(relativeNamespace, relativeActualNamespace string, errs ValidationErrors) {
+
+ var err *fieldError
+
+ for i := 0; i < len(errs); i++ {
+
+ err = errs[i].(*fieldError)
+ err.ns = string(append(append(v.slNs, err.ns...), err.field...))
+ err.actualNs = string(append(append(v.slActualNs, err.actualNs...), err.actualField...))
+
+ v.errs = append(v.errs, err)
+ }
+}
+
+// Validatable is the interface a struct can implement and
+// be validated just like registering a StructLevel validation
+// (they actually have the exact same signature.)
+type Validatable interface {
+ Validate(sl StructLevel)
+}
diff --git a/util.go b/util.go
index e811579..ee9874e 100644
--- a/util.go
+++ b/util.go
@@ -6,41 +6,26 @@ import (
"strings"
)
-const (
- blank = ""
- namespaceSeparator = "."
- leftBracket = "["
- rightBracket = "]"
- restrictedTagChars = ".[],|=+()`~!@#$%^&*\\\"/?<>{}"
- restrictedAliasErr = "Alias '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
- restrictedTagErr = "Tag '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
-)
-
-var (
- restrictedTags = map[string]struct{}{
- diveTag: {},
- existsTag: {},
- structOnlyTag: {},
- omitempty: {},
- skipValidationTag: {},
- utf8HexComma: {},
- utf8Pipe: {},
- noStructLevelTag: {},
- }
-)
-
-// ExtractType gets the actual underlying type of field value.
+// import (
+// "reflect"
+// "strconv"
+// "strings"
+// )
+
+// const (
+// blank = ""
+// namespaceSeparator = "."
+// leftBracket = "["
+// rightBracket = "]"
+// restrictedTagChars = ".[],|=+()`~!@#$%^&*\\\"/?<>{}"
+// restrictedAliasErr = "Alias '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
+// restrictedTagErr = "Tag '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
+// )
+
+// extractTypeInternal gets the actual underlying type of field value.
// It will dive into pointers, customTypes and return you the
// underlying value and it's kind.
-// it is exposed for use within you Custom Functions
-func (v *Validate) ExtractType(current reflect.Value) (reflect.Value, reflect.Kind) {
-
- val, k, _ := v.extractTypeInternal(current, false)
- return val, k
-}
-
-// only exists to not break backward compatibility, needed to return the third param for a bug fix internally
-func (v *Validate) extractTypeInternal(current reflect.Value, nullable bool) (reflect.Value, reflect.Kind, bool) {
+func (v *validate) extractTypeInternal(current reflect.Value, nullable bool) (reflect.Value, reflect.Kind, bool) {
switch current.Kind() {
case reflect.Ptr:
@@ -68,9 +53,9 @@ func (v *Validate) extractTypeInternal(current reflect.Value, nullable bool) (re
default:
- if v.hasCustomFuncs {
+ if v.v.hasCustomFuncs {
- if fn, ok := v.customTypeFuncs[current.Type()]; ok {
+ if fn, ok := v.v.customFuncs[current.Type()]; ok {
return v.extractTypeInternal(reflect.ValueOf(fn(current)), nullable)
}
}
@@ -79,19 +64,20 @@ func (v *Validate) extractTypeInternal(current reflect.Value, nullable bool) (re
}
}
-// GetStructFieldOK traverses a struct to retrieve a specific field denoted by the provided namespace and
+// getStructFieldOKInternal traverses a struct to retrieve a specific field denoted by the provided namespace and
// returns the field, field kind and whether is was successful in retrieving the field at all.
+//
// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field
// could not be retrieved because it didn't exist.
-func (v *Validate) GetStructFieldOK(current reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool) {
+func (v *validate) getStructFieldOKInternal(current reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool) {
- current, kind := v.ExtractType(current)
+ current, kind, _ := v.ExtractType(current)
if kind == reflect.Invalid {
return current, kind, false
}
- if namespace == blank {
+ if namespace == "" {
return current, kind, true
}
@@ -107,7 +93,7 @@ func (v *Validate) GetStructFieldOK(current reflect.Value, namespace string) (re
fld := namespace
ns := namespace
- if typ != timeType && typ != timePtrType {
+ if typ != timeType {
idx := strings.Index(namespace, namespaceSeparator)
@@ -115,7 +101,7 @@ func (v *Validate) GetStructFieldOK(current reflect.Value, namespace string) (re
fld = namespace[:idx]
ns = namespace[idx+1:]
} else {
- ns = blank
+ ns = ""
}
bracketIdx := strings.Index(fld, leftBracket)
@@ -127,7 +113,7 @@ func (v *Validate) GetStructFieldOK(current reflect.Value, namespace string) (re
current = current.FieldByName(fld)
- return v.GetStructFieldOK(current, ns)
+ return v.getStructFieldOKInternal(current, ns)
}
case reflect.Array, reflect.Slice:
@@ -148,7 +134,7 @@ func (v *Validate) GetStructFieldOK(current reflect.Value, namespace string) (re
}
}
- return v.GetStructFieldOK(current.Index(arrIdx), namespace[startIdx:])
+ return v.getStructFieldOKInternal(current.Index(arrIdx), namespace[startIdx:])
case reflect.Map:
idx := strings.Index(namespace, leftBracket) + 1
@@ -167,47 +153,47 @@ func (v *Validate) GetStructFieldOK(current reflect.Value, namespace string) (re
switch current.Type().Key().Kind() {
case reflect.Int:
i, _ := strconv.Atoi(key)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
case reflect.Int8:
i, _ := strconv.ParseInt(key, 10, 8)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(int8(i))), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(int8(i))), namespace[endIdx+1:])
case reflect.Int16:
i, _ := strconv.ParseInt(key, 10, 16)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(int16(i))), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(int16(i))), namespace[endIdx+1:])
case reflect.Int32:
i, _ := strconv.ParseInt(key, 10, 32)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(int32(i))), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(int32(i))), namespace[endIdx+1:])
case reflect.Int64:
i, _ := strconv.ParseInt(key, 10, 64)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
case reflect.Uint:
i, _ := strconv.ParseUint(key, 10, 0)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(uint(i))), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(uint(i))), namespace[endIdx+1:])
case reflect.Uint8:
i, _ := strconv.ParseUint(key, 10, 8)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(uint8(i))), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(uint8(i))), namespace[endIdx+1:])
case reflect.Uint16:
i, _ := strconv.ParseUint(key, 10, 16)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(uint16(i))), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(uint16(i))), namespace[endIdx+1:])
case reflect.Uint32:
i, _ := strconv.ParseUint(key, 10, 32)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(uint32(i))), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(uint32(i))), namespace[endIdx+1:])
case reflect.Uint64:
i, _ := strconv.ParseUint(key, 10, 64)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:])
case reflect.Float32:
f, _ := strconv.ParseFloat(key, 32)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(float32(f))), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(float32(f))), namespace[endIdx+1:])
case reflect.Float64:
f, _ := strconv.ParseFloat(key, 64)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(f)), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(f)), namespace[endIdx+1:])
case reflect.Bool:
b, _ := strconv.ParseBool(key)
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(b)), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(b)), namespace[endIdx+1:])
// reflect.Type = string
default:
- return v.GetStructFieldOK(current.MapIndex(reflect.ValueOf(key)), namespace[endIdx+1:])
+ return v.getStructFieldOKInternal(current.MapIndex(reflect.ValueOf(key)), namespace[endIdx+1:])
}
}
diff --git a/validator.go b/validator.go
index 2b1d716..dec2bd3 100644
--- a/validator.go
+++ b/validator.go
@@ -1,580 +1,95 @@
-/**
- * Package validator
- *
- * MISC:
- * - anonymous structs - they don't have names so expect the Struct name within StructErrors to be blank
- *
- */
-
package validator
import (
- "bytes"
- "errors"
"fmt"
"reflect"
- "strings"
- "sync"
- "time"
)
const (
- utf8HexComma = "0x2C"
- utf8Pipe = "0x7C"
- tagSeparator = ","
- orSeparator = "|"
- tagKeySeparator = "="
- structOnlyTag = "structonly"
- noStructLevelTag = "nostructlevel"
- omitempty = "omitempty"
- skipValidationTag = "-"
- diveTag = "dive"
- existsTag = "exists"
- fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag"
- arrayIndexFieldName = "%s" + leftBracket + "%d" + rightBracket
- mapIndexFieldName = "%s" + leftBracket + "%v" + rightBracket
- invalidValidation = "Invalid validation tag on field %s"
- undefinedValidation = "Undefined validation function on field %s"
- validatorNotInitialized = "Validator instance not initialized"
- fieldNameRequired = "Field Name Required"
- tagRequired = "Tag Required"
-)
-
-var (
- timeType = reflect.TypeOf(time.Time{})
- timePtrType = reflect.TypeOf(&time.Time{})
- defaultCField = new(cField)
+ arrayIndexFieldName = "%s" + leftBracket + "%d" + rightBracket
+ mapIndexFieldName = "%s" + leftBracket + "%v" + rightBracket
)
-// StructLevel contains all of the information and helper methods
-// for reporting errors during struct level validation
-type StructLevel struct {
- TopStruct reflect.Value
- CurrentStruct reflect.Value
- errPrefix string
- nsPrefix string
- errs ValidationErrors
- v *Validate
-}
-
-// ReportValidationErrors accepts the key relative to the top level struct and validatin errors.
-// Example: had a triple nested struct User, ContactInfo, Country and ran errs := validate.Struct(country)
-// from within a User struct level validation would call this method like so:
-// ReportValidationErrors("ContactInfo.", errs)
-// NOTE: relativeKey can contain both the Field Relative and Custom name relative paths
-// i.e. ReportValidationErrors("ContactInfo.|cInfo", errs) where cInfo represents say the JSON name of
-// the relative path; this will be split into 2 variables in the next valiator version.
-func (sl *StructLevel) ReportValidationErrors(relativeKey string, errs ValidationErrors) {
- for _, e := range errs {
-
- idx := strings.Index(relativeKey, "|")
- var rel string
- var cRel string
-
- if idx != -1 {
- rel = relativeKey[:idx]
- cRel = relativeKey[idx+1:]
- } else {
- rel = relativeKey
- }
-
- key := sl.errPrefix + rel + e.Field
-
- e.FieldNamespace = key
- e.NameNamespace = sl.nsPrefix + cRel + e.Name
-
- sl.errs[key] = e
- }
-}
-
-// ReportError reports an error just by passing the field and tag information
-// NOTE: tag can be an existing validation tag or just something you make up
-// and precess on the flip side it's up to you.
-func (sl *StructLevel) ReportError(field reflect.Value, fieldName string, customName string, tag string) {
-
- field, kind := sl.v.ExtractType(field)
-
- if fieldName == blank {
- panic(fieldNameRequired)
- }
-
- if customName == blank {
- customName = fieldName
- }
-
- if tag == blank {
- panic(tagRequired)
- }
-
- ns := sl.errPrefix + fieldName
-
- switch kind {
- case reflect.Invalid:
- sl.errs[ns] = &FieldError{
- FieldNamespace: ns,
- NameNamespace: sl.nsPrefix + customName,
- Name: customName,
- Field: fieldName,
- Tag: tag,
- ActualTag: tag,
- Param: blank,
- Kind: kind,
- }
- default:
- sl.errs[ns] = &FieldError{
- FieldNamespace: ns,
- NameNamespace: sl.nsPrefix + customName,
- Name: customName,
- Field: fieldName,
- Tag: tag,
- ActualTag: tag,
- Param: blank,
- Value: field.Interface(),
- Kind: kind,
- Type: field.Type(),
- }
- }
-}
-
-// Validate contains the validator settings passed in using the Config struct
-type Validate struct {
- tagName string
- fieldNameTag string
- validationFuncs map[string]Func
- structLevelFuncs map[reflect.Type]StructLevelFunc
- customTypeFuncs map[reflect.Type]CustomTypeFunc
- aliasValidators map[string]string
- hasCustomFuncs bool
- hasAliasValidators bool
- hasStructLevelFuncs bool
- tagCache *tagCache
- structCache *structCache
- errsPool *sync.Pool
-}
-
-func (v *Validate) initCheck() {
- if v == nil {
- panic(validatorNotInitialized)
- }
-}
-
-// Config contains the options that a Validator instance will use.
-// It is passed to the New() function
-type Config struct {
- TagName string
- FieldNameTag string
-}
-
-// CustomTypeFunc allows for overriding or adding custom field type handler functions
-// field = field value of the type to return a value to be validated
-// example Valuer from sql drive see https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29
-type CustomTypeFunc func(field reflect.Value) interface{}
-
-// Func accepts all values needed for file and cross field validation
-// v = validator instance, needed but some built in functions for it's custom types
-// topStruct = top level struct when validating by struct otherwise nil
-// currentStruct = current level struct when validating by struct otherwise optional comparison value
-// field = field value for validation
-// param = parameter used in validation i.e. gt=0 param would be 0
-type Func func(v *Validate, topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldtype reflect.Type, fieldKind reflect.Kind, param string) bool
-
-// StructLevelFunc accepts all values needed for struct level validation
-type StructLevelFunc func(v *Validate, structLevel *StructLevel)
-
-// ValidationErrors is a type of map[string]*FieldError
-// it exists to allow for multiple errors to be passed from this library
-// and yet still subscribe to the error interface
-type ValidationErrors map[string]*FieldError
-
-// Error is intended for use in development + debugging and not intended to be a production error message.
-// It allows ValidationErrors to subscribe to the Error interface.
-// All information to create an error message specific to your application is contained within
-// the FieldError found within the ValidationErrors map
-func (ve ValidationErrors) Error() string {
-
- buff := bytes.NewBufferString(blank)
-
- for key, err := range ve {
- buff.WriteString(fmt.Sprintf(fieldErrMsg, key, err.Field, err.Tag))
- buff.WriteString("\n")
- }
-
- return strings.TrimSpace(buff.String())
-}
-
-// FieldError contains a single field's validation error along
-// with other properties that may be needed for error message creation
-type FieldError struct {
- FieldNamespace string
- NameNamespace string
- Field string
- Name string
- Tag string
- ActualTag string
- Kind reflect.Kind
- Type reflect.Type
- Param string
- Value interface{}
-}
-
-// New creates a new Validate instance for use.
-func New(config *Config) *Validate {
-
- tc := new(tagCache)
- tc.m.Store(make(map[string]*cTag))
-
- sc := new(structCache)
- sc.m.Store(make(map[reflect.Type]*cStruct))
-
- v := &Validate{
- tagName: config.TagName,
- fieldNameTag: config.FieldNameTag,
- tagCache: tc,
- structCache: sc,
- errsPool: &sync.Pool{New: func() interface{} {
- return ValidationErrors{}
- }}}
-
- if len(v.aliasValidators) == 0 {
- // must copy alias validators for separate validations to be used in each validator instance
- v.aliasValidators = map[string]string{}
- for k, val := range bakedInAliasValidators {
- v.RegisterAliasValidation(k, val)
- }
- }
-
- if len(v.validationFuncs) == 0 {
- // must copy validators for separate validations to be used in each instance
- v.validationFuncs = map[string]Func{}
- for k, val := range bakedInValidators {
- v.RegisterValidation(k, val)
- }
- }
-
- return v
-}
-
-// RegisterStructValidation registers a StructLevelFunc against a number of types
-// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
-func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) {
- v.initCheck()
-
- if v.structLevelFuncs == nil {
- v.structLevelFuncs = map[reflect.Type]StructLevelFunc{}
- }
-
- for _, t := range types {
- v.structLevelFuncs[reflect.TypeOf(t)] = fn
- }
-
- v.hasStructLevelFuncs = true
-}
-
-// RegisterValidation adds a validation Func to a Validate's map of validators denoted by the key
-// NOTE: if the key already exists, the previous validation function will be replaced.
-// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
-func (v *Validate) RegisterValidation(key string, fn Func) error {
- v.initCheck()
-
- if key == blank {
- return errors.New("Function Key cannot be empty")
- }
-
- if fn == nil {
- return errors.New("Function cannot be empty")
- }
-
- _, ok := restrictedTags[key]
-
- if ok || strings.ContainsAny(key, restrictedTagChars) {
- panic(fmt.Sprintf(restrictedTagErr, key))
- }
-
- v.validationFuncs[key] = fn
-
- return nil
-}
-
-// RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types
-// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
-func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) {
- v.initCheck()
-
- if v.customTypeFuncs == nil {
- v.customTypeFuncs = map[reflect.Type]CustomTypeFunc{}
- }
-
- for _, t := range types {
- v.customTypeFuncs[reflect.TypeOf(t)] = fn
- }
-
- v.hasCustomFuncs = true
-}
-
-// RegisterAliasValidation registers a mapping of a single validationstag that
-// defines a common or complex set of validation(s) to simplify adding validation
-// to structs. NOTE: when returning an error the tag returned in FieldError will be
-// the alias tag unless the dive tag is part of the alias; everything after the
-// dive tag is not reported as the alias tag. Also the ActualTag in the before case
-// will be the actual tag within the alias that failed.
-// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
-func (v *Validate) RegisterAliasValidation(alias, tags string) {
- v.initCheck()
-
- _, ok := restrictedTags[alias]
-
- if ok || strings.ContainsAny(alias, restrictedTagChars) {
- panic(fmt.Sprintf(restrictedAliasErr, alias))
- }
-
- v.aliasValidators[alias] = tags
- v.hasAliasValidators = true
-}
-
-// Field validates a single field using tag style validation and returns nil or ValidationErrors as type error.
-// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors.
-// NOTE: it returns ValidationErrors instead of a single FieldError because this can also
-// validate Array, Slice and maps fields which may contain more than one error
-func (v *Validate) Field(field interface{}, tag string) error {
- v.initCheck()
-
- if len(tag) == 0 || tag == skipValidationTag {
- return nil
- }
-
- errs := v.errsPool.Get().(ValidationErrors)
- fieldVal := reflect.ValueOf(field)
-
- ctag, ok := v.tagCache.Get(tag)
- if !ok {
- v.tagCache.lock.Lock()
- defer v.tagCache.lock.Unlock()
-
- // could have been multiple trying to access, but once first is done this ensures tag
- // isn't parsed again.
- ctag, ok = v.tagCache.Get(tag)
- if !ok {
- ctag, _ = v.parseFieldTagsRecursive(tag, blank, blank, false)
- v.tagCache.Set(tag, ctag)
- }
- }
-
- v.traverseField(fieldVal, fieldVal, fieldVal, blank, blank, errs, false, false, nil, nil, defaultCField, ctag)
-
- if len(errs) == 0 {
- v.errsPool.Put(errs)
- return nil
- }
-
- return errs
+// per validate contruct
+type validate struct {
+ v *Validate
+ top reflect.Value
+ ns []byte
+ actualNs []byte
+ errs ValidationErrors
+ isPartial bool
+ hasExcludes bool
+ includeExclude map[string]struct{} // reset only if StructPartial or StructExcept are called, no need otherwise
+
+ // StructLevel & FieldLevel fields
+ slflParent reflect.Value
+ slCurrent reflect.Value
+ slNs []byte
+ slActualNs []byte
+ flField reflect.Value
+ flParam string
}
-// FieldWithValue validates a single field, against another fields value using tag style validation and returns nil or ValidationErrors.
-// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors.
-// NOTE: it returns ValidationErrors instead of a single FieldError because this can also
-// validate Array, Slice and maps fields which may contain more than one error
-func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string) error {
- v.initCheck()
+// parent and current will be the same the first run of validateStruct
+func (v *validate) validateStruct(parent reflect.Value, current reflect.Value, typ reflect.Type, ns []byte, actualNs []byte, ct *cTag) {
- if len(tag) == 0 || tag == skipValidationTag {
- return nil
- }
+ first := len(ns) == 0
- errs := v.errsPool.Get().(ValidationErrors)
- topVal := reflect.ValueOf(val)
-
- ctag, ok := v.tagCache.Get(tag)
+ cs, ok := v.v.structCache.Get(typ)
if !ok {
- v.tagCache.lock.Lock()
- defer v.tagCache.lock.Unlock()
-
- // could have been multiple trying to access, but once first is done this ensures tag
- // isn't parsed again.
- ctag, ok = v.tagCache.Get(tag)
- if !ok {
- ctag, _ = v.parseFieldTagsRecursive(tag, blank, blank, false)
- v.tagCache.Set(tag, ctag)
- }
- }
-
- v.traverseField(topVal, topVal, reflect.ValueOf(field), blank, blank, errs, false, false, nil, nil, defaultCField, ctag)
-
- if len(errs) == 0 {
- v.errsPool.Put(errs)
- return nil
+ cs = v.v.extractStructCache(current, typ.Name())
}
- return errs
-}
-
-// StructPartial validates the fields passed in only, ignoring all others.
-// Fields may be provided in a namespaced fashion relative to the struct provided
-// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name and returns nil or ValidationErrors as error
-// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors.
-func (v *Validate) StructPartial(current interface{}, fields ...string) error {
- v.initCheck()
-
- sv, _ := v.ExtractType(reflect.ValueOf(current))
- name := sv.Type().Name()
- m := map[string]struct{}{}
-
- if fields != nil {
- for _, k := range fields {
-
- flds := strings.Split(k, namespaceSeparator)
- if len(flds) > 0 {
-
- key := name + namespaceSeparator
- for _, s := range flds {
+ if first {
- idx := strings.Index(s, leftBracket)
+ ns = append(ns, cs.Name...)
+ ns = append(ns, '.')
- if idx != -1 {
- for idx != -1 {
- key += s[:idx]
- m[key] = struct{}{}
-
- idx2 := strings.Index(s, rightBracket)
- idx2++
- key += s[idx:idx2]
- m[key] = struct{}{}
- s = s[idx2:]
- idx = strings.Index(s, leftBracket)
- }
- } else {
-
- key += s
- m[key] = struct{}{}
- }
-
- key += namespaceSeparator
- }
- }
- }
+ actualNs = append(actualNs, cs.Name...)
+ actualNs = append(actualNs, '.')
}
- errs := v.errsPool.Get().(ValidationErrors)
-
- v.ensureValidStruct(sv, sv, sv, blank, blank, errs, true, len(m) != 0, false, m, false)
-
- if len(errs) == 0 {
- v.errsPool.Put(errs)
- return nil
- }
-
- return errs
-}
-
-// StructExcept validates all fields except the ones passed in.
-// Fields may be provided in a namespaced fashion relative to the struct provided
-// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name and returns nil or ValidationErrors as error
-// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors.
-func (v *Validate) StructExcept(current interface{}, fields ...string) error {
- v.initCheck()
-
- sv, _ := v.ExtractType(reflect.ValueOf(current))
- name := sv.Type().Name()
- m := map[string]struct{}{}
-
- for _, key := range fields {
- m[name+namespaceSeparator+key] = struct{}{}
- }
-
- errs := v.errsPool.Get().(ValidationErrors)
-
- v.ensureValidStruct(sv, sv, sv, blank, blank, errs, true, len(m) != 0, true, m, false)
-
- if len(errs) == 0 {
- v.errsPool.Put(errs)
- return nil
- }
-
- return errs
-}
-
-// Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified.
-// it returns nil or ValidationErrors as error.
-// You will need to assert the error if it's not nil i.e. err.(validator.ValidationErrors) to access the map of errors.
-func (v *Validate) Struct(current interface{}) error {
- v.initCheck()
-
- errs := v.errsPool.Get().(ValidationErrors)
- sv := reflect.ValueOf(current)
-
- v.ensureValidStruct(sv, sv, sv, blank, blank, errs, true, false, false, nil, false)
-
- if len(errs) == 0 {
- v.errsPool.Put(errs)
- return nil
- }
-
- return errs
-}
-
-func (v *Validate) ensureValidStruct(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, nsPrefix string, errs ValidationErrors, useStructName bool, partial bool, exclude bool, includeExclude map[string]struct{}, isStructOnly bool) {
-
- if current.Kind() == reflect.Ptr && !current.IsNil() {
- current = current.Elem()
- }
-
- if current.Kind() != reflect.Struct && current.Kind() != reflect.Interface {
- panic("value passed for validation is not a struct")
- }
-
- v.tranverseStruct(topStruct, currentStruct, current, errPrefix, nsPrefix, errs, useStructName, partial, exclude, includeExclude, nil, nil)
-}
-
-// tranverseStruct traverses a structs fields and then passes them to be validated by traverseField
-func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, nsPrefix string, errs ValidationErrors, useStructName bool, partial bool, exclude bool, includeExclude map[string]struct{}, cs *cStruct, ct *cTag) {
-
- var ok bool
- first := len(nsPrefix) == 0
- typ := current.Type()
-
- cs, ok = v.structCache.Get(typ)
- if !ok {
- cs = v.extractStructCache(current, typ.Name())
- }
-
- if useStructName {
- errPrefix += cs.Name + namespaceSeparator
-
- if len(v.fieldNameTag) != 0 {
- nsPrefix += cs.Name + namespaceSeparator
- }
- }
-
- // structonly tag present don't tranverseFields
- // but must still check and run below struct level validation
- // if present
- if first || ct == nil || ct.typeof != typeStructOnly {
+ // ct is nil on top level struct, and structs as fields that have no tag info
+ // so if nil or if not nil and the structonly tag isn't present
+ if ct == nil || ct.typeof != typeStructOnly {
for _, f := range cs.fields {
- if partial {
+ if v.isPartial {
- _, ok = includeExclude[errPrefix+f.Name]
+ _, ok = v.includeExclude[string(append(ns, f.Name...))]
- if (ok && exclude) || (!ok && !exclude) {
+ if (ok && v.hasExcludes) || (!ok && !v.hasExcludes) {
continue
}
}
- v.traverseField(topStruct, currentStruct, current.Field(f.Idx), errPrefix, nsPrefix, errs, partial, exclude, includeExclude, cs, f, f.cTags)
+ v.traverseField(parent, current.Field(f.Idx), ns, actualNs, f, f.cTags)
}
}
// check if any struct level validations, after all field validations already checked.
+ // first iteration will have no info about nostructlevel tag, and is checked prior to
+ // calling the next iteration of validateStruct called from traverseField.
if cs.fn != nil {
- cs.fn(v, &StructLevel{v: v, TopStruct: topStruct, CurrentStruct: current, errPrefix: errPrefix, nsPrefix: nsPrefix, errs: errs})
+
+ v.slflParent = parent
+ v.slCurrent = current
+ v.slNs = ns
+ v.slActualNs = actualNs
+
+ cs.fn(v)
}
}
// traverseField validates any field, be it a struct or single field, ensures it's validity and passes it along to be validated via it's tag options
-func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, nsPrefix string, errs ValidationErrors, partial bool, exclude bool, includeExclude map[string]struct{}, cs *cStruct, cf *cField, ct *cTag) {
+func (v *validate) traverseField(parent reflect.Value, current reflect.Value, ns []byte, actualNs []byte, cf *cField, ct *cTag) {
- current, kind, nullable := v.extractTypeInternal(current, false)
var typ reflect.Type
+ var kind reflect.Kind
+ var nullable bool
+
+ current, kind, nullable = v.extractTypeInternal(current, nullable)
switch kind {
case reflect.Ptr, reflect.Interface, reflect.Invalid:
@@ -589,39 +104,44 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
if ct.hasTag {
- ns := errPrefix + cf.Name
-
if kind == reflect.Invalid {
- errs[ns] = &FieldError{
- FieldNamespace: ns,
- NameNamespace: nsPrefix + cf.AltName,
- Name: cf.AltName,
- Field: cf.Name,
- Tag: ct.aliasTag,
- ActualTag: ct.tag,
- Param: ct.param,
- Kind: kind,
- }
+
+ v.errs = append(v.errs,
+ &fieldError{
+ tag: ct.aliasTag,
+ actualTag: ct.tag,
+ ns: string(append(ns, cf.Name...)),
+ actualNs: string(append(actualNs, cf.AltName...)),
+ field: cf.AltName,
+ actualField: cf.Name,
+ param: ct.param,
+ kind: kind,
+ },
+ )
+
return
}
- errs[ns] = &FieldError{
- FieldNamespace: ns,
- NameNamespace: nsPrefix + cf.AltName,
- Name: cf.AltName,
- Field: cf.Name,
- Tag: ct.aliasTag,
- ActualTag: ct.tag,
- Param: ct.param,
- Value: current.Interface(),
- Kind: kind,
- Type: current.Type(),
- }
+ v.errs = append(v.errs,
+ &fieldError{
+ tag: ct.aliasTag,
+ actualTag: ct.tag,
+ ns: string(append(ns, cf.Name...)),
+ actualNs: string(append(actualNs, cf.AltName...)),
+ field: cf.AltName,
+ actualField: cf.Name,
+ value: current.Interface(),
+ param: ct.param,
+ kind: kind,
+ typ: current.Type(),
+ },
+ )
return
}
case reflect.Struct:
+
typ = current.Type()
if typ != timeType {
@@ -634,7 +154,7 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
return
}
- v.tranverseStruct(topStruct, current, current, errPrefix+cf.Name+namespaceSeparator, nsPrefix+cf.AltName+namespaceSeparator, errs, false, partial, exclude, includeExclude, cs, ct)
+ v.validateStruct(current, current, typ, append(append(ns, cf.Name...), '.'), append(append(actualNs, cf.AltName...), '.'), ct)
return
}
}
@@ -659,7 +179,12 @@ OUTER:
case typeOmitEmpty:
- if !nullable && !HasValue(v, topStruct, currentStruct, current, typ, kind, blank) {
+ // set Field Level fields
+ v.slflParent = parent
+ v.flField = current
+ v.flParam = ""
+
+ if !nullable && !hasValue(v) {
return
}
@@ -676,12 +201,12 @@ OUTER:
case reflect.Slice, reflect.Array:
for i := 0; i < current.Len(); i++ {
- v.traverseField(topStruct, currentStruct, current.Index(i), errPrefix, nsPrefix, errs, partial, exclude, includeExclude, cs, &cField{Name: fmt.Sprintf(arrayIndexFieldName, cf.Name, i), AltName: fmt.Sprintf(arrayIndexFieldName, cf.AltName, i)}, ct)
+ v.traverseField(parent, current.Index(i), ns, actualNs, &cField{Name: fmt.Sprintf(arrayIndexFieldName, cf.Name, i), AltName: fmt.Sprintf(arrayIndexFieldName, cf.AltName, i)}, ct)
}
case reflect.Map:
for _, key := range current.MapKeys() {
- v.traverseField(topStruct, currentStruct, current.MapIndex(key), errPrefix, nsPrefix, errs, partial, exclude, includeExclude, cs, &cField{Name: fmt.Sprintf(mapIndexFieldName, cf.Name, key.Interface()), AltName: fmt.Sprintf(mapIndexFieldName, cf.AltName, key.Interface())}, ct)
+ v.traverseField(parent, current.MapIndex(key), ns, actualNs, &cField{Name: fmt.Sprintf(mapIndexFieldName, cf.Name, key.Interface()), AltName: fmt.Sprintf(mapIndexFieldName, cf.AltName, key.Interface())}, ct)
}
default:
@@ -694,11 +219,16 @@ OUTER:
case typeOr:
- errTag := blank
+ errTag := ""
for {
- if ct.fn(v, topStruct, currentStruct, current, typ, kind, ct.param) {
+ // set Field Level fields
+ v.slflParent = parent
+ v.flField = current
+ v.flParam = ct.param
+
+ if ct.fn(v) {
// drain rest of the 'or' values, then continue or leave
for {
@@ -720,32 +250,39 @@ OUTER:
if ct.next == nil {
// if we get here, no valid 'or' value and no more tags
- ns := errPrefix + cf.Name
-
if ct.hasAlias {
- errs[ns] = &FieldError{
- FieldNamespace: ns,
- NameNamespace: nsPrefix + cf.AltName,
- Name: cf.AltName,
- Field: cf.Name,
- Tag: ct.aliasTag,
- ActualTag: ct.actualAliasTag,
- Value: current.Interface(),
- Type: typ,
- Kind: kind,
- }
+
+ v.errs = append(v.errs,
+ &fieldError{
+ tag: ct.aliasTag,
+ actualTag: ct.actualAliasTag,
+ ns: string(append(ns, cf.Name...)),
+ actualNs: string(append(actualNs, cf.AltName...)),
+ field: cf.AltName,
+ actualField: cf.Name,
+ value: current.Interface(),
+ param: ct.param,
+ kind: kind,
+ typ: typ,
+ },
+ )
+
} else {
- errs[errPrefix+cf.Name] = &FieldError{
- FieldNamespace: ns,
- NameNamespace: nsPrefix + cf.AltName,
- Name: cf.AltName,
- Field: cf.Name,
- Tag: errTag[1:],
- ActualTag: errTag[1:],
- Value: current.Interface(),
- Type: typ,
- Kind: kind,
- }
+
+ v.errs = append(v.errs,
+ &fieldError{
+ tag: errTag[1:],
+ actualTag: errTag[1:],
+ ns: string(append(ns, cf.Name...)),
+ actualNs: string(append(actualNs, cf.AltName...)),
+ field: cf.AltName,
+ actualField: cf.Name,
+ value: current.Interface(),
+ param: ct.param,
+ kind: kind,
+ typ: typ,
+ },
+ )
}
return
@@ -755,22 +292,28 @@ OUTER:
}
default:
- if !ct.fn(v, topStruct, currentStruct, current, typ, kind, ct.param) {
-
- ns := errPrefix + cf.Name
-
- errs[ns] = &FieldError{
- FieldNamespace: ns,
- NameNamespace: nsPrefix + cf.AltName,
- Name: cf.AltName,
- Field: cf.Name,
- Tag: ct.aliasTag,
- ActualTag: ct.tag,
- Value: current.Interface(),
- Param: ct.param,
- Type: typ,
- Kind: kind,
- }
+
+ // set Field Level fields
+ v.slflParent = parent
+ v.flField = current
+ v.flParam = ct.param
+
+ if !ct.fn(v) {
+
+ v.errs = append(v.errs,
+ &fieldError{
+ tag: ct.aliasTag,
+ actualTag: ct.tag,
+ ns: string(append(ns, cf.Name...)),
+ actualNs: string(append(actualNs, cf.AltName...)),
+ field: cf.AltName,
+ actualField: cf.Name,
+ value: current.Interface(),
+ param: ct.param,
+ kind: kind,
+ typ: typ,
+ },
+ )
return
@@ -779,4 +322,5 @@ OUTER:
ct = ct.next
}
}
+
}
diff --git a/validator_instance.go b/validator_instance.go
new file mode 100644
index 0000000..8ade9cc
--- /dev/null
+++ b/validator_instance.go
@@ -0,0 +1,442 @@
+package validator
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "strings"
+ "sync"
+ "time"
+)
+
+const (
+ defaultTagName = "validate"
+ utf8HexComma = "0x2C"
+ utf8Pipe = "0x7C"
+ tagSeparator = ","
+ orSeparator = "|"
+ tagKeySeparator = "="
+ structOnlyTag = "structonly"
+ noStructLevelTag = "nostructlevel"
+ omitempty = "omitempty"
+ skipValidationTag = "-"
+ diveTag = "dive"
+ namespaceSeparator = "."
+ leftBracket = "["
+ rightBracket = "]"
+ restrictedTagChars = ".[],|=+()`~!@#$%^&*\\\"/?<>{}"
+ restrictedAliasErr = "Alias '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
+ restrictedTagErr = "Tag '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
+)
+
+var (
+ timeType = reflect.TypeOf(time.Time{})
+ defaultCField = new(cField)
+)
+
+// CustomTypeFunc allows for overriding or adding custom field type handler functions
+// field = field value of the type to return a value to be validated
+// example Valuer from sql drive see https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29
+type CustomTypeFunc func(field reflect.Value) interface{}
+
+// TagNameFunc allows for adding of a custom tag name parser
+type TagNameFunc func(field reflect.StructField) string
+
+// Validate contains the validator settings and cache
+type Validate struct {
+ tagName string
+ pool *sync.Pool
+ hasCustomFuncs bool
+ hasTagNameFunc bool
+ tagNameFunc TagNameFunc
+ structLevelFuncs map[reflect.Type]StructLevelFunc
+ customFuncs map[reflect.Type]CustomTypeFunc
+ aliases map[string]string
+ validations map[string]Func
+ tagCache *tagCache
+ structCache *structCache
+}
+
+// New returns a new instacne of 'validate' with sane defaults.
+func New() *Validate {
+
+ tc := new(tagCache)
+ tc.m.Store(make(map[string]*cTag))
+
+ sc := new(structCache)
+ sc.m.Store(make(map[reflect.Type]*cStruct))
+
+ v := &Validate{
+ tagName: defaultTagName,
+ aliases: make(map[string]string, len(bakedInAliases)),
+ validations: make(map[string]Func, len(bakedInValidators)),
+ tagCache: tc,
+ structCache: sc,
+ }
+
+ // must copy alias validators for separate validations to be used in each validator instance
+ for k, val := range bakedInAliases {
+ v.RegisterAlias(k, val)
+ }
+
+ // must copy validators for separate validations to be used in each instance
+ for k, val := range bakedInValidators {
+
+ // no need to error check here, baked in will alwaays be valid
+ v.RegisterValidation(k, val)
+ }
+
+ v.pool = &sync.Pool{
+ New: func() interface{} {
+ return &validate{
+ v: v,
+ }
+ },
+ }
+
+ return v
+}
+
+// SetTagName allows for changing of the default tag name of 'validate'
+func (v *Validate) SetTagName(name string) {
+ v.tagName = name
+}
+
+// RegisterTagNameFunc registers a function to get another name from the
+// StructField eg. the JSON name
+func (v *Validate) RegisterTagNameFunc(fn TagNameFunc) {
+ v.tagNameFunc = fn
+ v.hasTagNameFunc = true
+}
+
+// RegisterValidation adds a validation with the given tag
+//
+// NOTES:
+// - if the key already exists, the previous validation function will be replaced.
+// - this method is not thread-safe it is intended that these all be registered prior to any validation
+func (v *Validate) RegisterValidation(tag string, fn Func) error {
+
+ if len(tag) == 0 {
+ return errors.New("Function Key cannot be empty")
+ }
+
+ if fn == nil {
+ return errors.New("Function cannot be empty")
+ }
+
+ _, ok := restrictedTags[tag]
+
+ if ok || strings.ContainsAny(tag, restrictedTagChars) {
+ panic(fmt.Sprintf(restrictedTagErr, tag))
+ }
+
+ v.validations[tag] = fn
+
+ return nil
+}
+
+// RegisterAlias registers a mapping of a single validation tag that
+// defines a common or complex set of validation(s) to simplify adding validation
+// to structs.
+//
+// NOTE: this function is not thread-safe it is intended that these all be registered prior to any validation
+func (v *Validate) RegisterAlias(alias, tags string) {
+
+ _, ok := restrictedTags[alias]
+
+ if ok || strings.ContainsAny(alias, restrictedTagChars) {
+ panic(fmt.Sprintf(restrictedAliasErr, alias))
+ }
+
+ v.aliases[alias] = tags
+}
+
+// RegisterStructValidation registers a StructLevelFunc against a number of types.
+// This is akin to implementing the 'Validatable' interface, but for structs for which
+// you may not have access or rights to change.
+//
+// NOTES:
+// - if this and the 'Validatable' interface are implemented the Struct Level takes precedence as to enable
+// a struct out of your control's validation to be overridden
+// - this method is not thread-safe it is intended that these all be registered prior to any validation
+func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) {
+
+ if v.structLevelFuncs == nil {
+ v.structLevelFuncs = make(map[reflect.Type]StructLevelFunc)
+ }
+
+ for _, t := range types {
+ v.structLevelFuncs[reflect.TypeOf(t)] = fn
+ }
+}
+
+// RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types
+//
+// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
+func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) {
+
+ if v.customFuncs == nil {
+ v.customFuncs = make(map[reflect.Type]CustomTypeFunc)
+ }
+
+ for _, t := range types {
+ v.customFuncs[reflect.TypeOf(t)] = fn
+ }
+}
+
+// Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified.
+//
+// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
+// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
+func (v *Validate) Struct(s interface{}) (err error) {
+
+ val := reflect.ValueOf(s)
+ top := val
+
+ if val.Kind() == reflect.Ptr && !val.IsNil() {
+ val = val.Elem()
+ }
+
+ typ := val.Type()
+
+ if val.Kind() != reflect.Struct || typ == timeType {
+ return &InvalidValidationError{Type: typ}
+ }
+
+ // good to validate
+ vd := v.pool.Get().(*validate)
+ vd.top = top
+ vd.isPartial = false
+ // vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
+
+ vd.validateStruct(top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil)
+
+ if len(vd.errs) > 0 {
+ err = vd.errs
+ vd.errs = nil
+ }
+
+ v.pool.Put(vd)
+
+ return
+}
+
+// StructPartial validates the fields passed in only, ignoring all others.
+// Fields may be provided in a namespaced fashion relative to the struct provided
+// eg. NestedStruct.Field or NestedArrayField[0].Struct.Name
+//
+// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
+// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
+func (v *Validate) StructPartial(s interface{}, fields ...string) (err error) {
+
+ val := reflect.ValueOf(s)
+ top := val
+
+ if val.Kind() == reflect.Ptr && !val.IsNil() {
+ val = val.Elem()
+ }
+
+ typ := val.Type()
+
+ if val.Kind() != reflect.Struct || typ == timeType {
+ return &InvalidValidationError{Type: typ}
+ }
+
+ // good to validate
+ vd := v.pool.Get().(*validate)
+ vd.top = top
+ vd.isPartial = true
+ vd.hasExcludes = false
+ vd.includeExclude = make(map[string]struct{})
+
+ name := typ.Name()
+
+ if fields != nil {
+ for _, k := range fields {
+
+ flds := strings.Split(k, namespaceSeparator)
+ if len(flds) > 0 {
+
+ key := name + namespaceSeparator
+ for _, s := range flds {
+
+ idx := strings.Index(s, leftBracket)
+
+ if idx != -1 {
+ for idx != -1 {
+ key += s[:idx]
+ vd.includeExclude[key] = struct{}{}
+
+ idx2 := strings.Index(s, rightBracket)
+ idx2++
+ key += s[idx:idx2]
+ vd.includeExclude[key] = struct{}{}
+ s = s[idx2:]
+ idx = strings.Index(s, leftBracket)
+ }
+ } else {
+
+ key += s
+ vd.includeExclude[key] = struct{}{}
+ }
+
+ key += namespaceSeparator
+ }
+ }
+ }
+ }
+
+ vd.validateStruct(top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil)
+
+ if len(vd.errs) > 0 {
+ err = vd.errs
+ vd.errs = nil
+ }
+
+ v.pool.Put(vd)
+
+ return
+}
+
+// StructExcept validates all fields except the ones passed in.
+// Fields may be provided in a namespaced fashion relative to the struct provided
+// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
+//
+// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
+// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
+func (v *Validate) StructExcept(s interface{}, fields ...string) (err error) {
+
+ val := reflect.ValueOf(s)
+ top := val
+
+ if val.Kind() == reflect.Ptr && !val.IsNil() {
+ val = val.Elem()
+ }
+
+ typ := val.Type()
+
+ if val.Kind() != reflect.Struct || typ == timeType {
+ return &InvalidValidationError{Type: typ}
+ }
+
+ // good to validate
+ vd := v.pool.Get().(*validate)
+ vd.top = top
+ vd.isPartial = true
+ vd.hasExcludes = true
+ vd.includeExclude = make(map[string]struct{})
+
+ name := typ.Name()
+
+ for _, key := range fields {
+ vd.includeExclude[name+namespaceSeparator+key] = struct{}{}
+ }
+
+ vd.validateStruct(top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil)
+
+ if len(vd.errs) > 0 {
+ err = vd.errs
+ vd.errs = nil
+ }
+
+ v.pool.Put(vd)
+
+ return
+}
+
+// func (v *validate) traverseField(parent reflect.Value, current reflect.Value, ns []byte, actualNs []byte, cf *cField, ct *cTag) {
+
+// Var validates a single variable using tag style validation.
+// eg.
+// var i int
+// validate.Var(i, "gt=1,lt=10")
+//
+// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
+// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
+// validate Array, Slice and maps fields which may contain more than one error
+func (v *Validate) Var(field interface{}, tag string) (err error) {
+
+ if len(tag) == 0 || tag == skipValidationTag {
+ return nil
+ }
+
+ // find cached tag
+ ctag, ok := v.tagCache.Get(tag)
+ if !ok {
+ v.tagCache.lock.Lock()
+ defer v.tagCache.lock.Unlock()
+
+ // could have been multiple trying to access, but once first is done this ensures tag
+ // isn't parsed again.
+ ctag, ok = v.tagCache.Get(tag)
+ if !ok {
+ ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false)
+ v.tagCache.Set(tag, ctag)
+ }
+ }
+
+ val := reflect.ValueOf(field)
+
+ vd := v.pool.Get().(*validate)
+ vd.top = val
+ vd.isPartial = false
+
+ vd.traverseField(val, val, vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
+
+ if len(vd.errs) > 0 {
+ err = vd.errs
+ vd.errs = nil
+ }
+
+ v.pool.Put(vd)
+
+ return
+}
+
+// VarWithValue validates a single variable, against another variable/field's value using tag style validation
+// eg.
+// s1 := "abcd"
+// s2 := "abcd"
+// validate.VarWithValue(s1, s2, "eqcsfield") // returns true
+//
+// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
+// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
+// validate Array, Slice and maps fields which may contain more than one error
+func (v *Validate) VarWithValue(field interface{}, other interface{}, tag string) (err error) {
+
+ if len(tag) == 0 || tag == skipValidationTag {
+ return nil
+ }
+
+ // find cached tag
+ ctag, ok := v.tagCache.Get(tag)
+ if !ok {
+ v.tagCache.lock.Lock()
+ defer v.tagCache.lock.Unlock()
+
+ // could have been multiple trying to access, but once first is done this ensures tag
+ // isn't parsed again.
+ ctag, ok = v.tagCache.Get(tag)
+ if !ok {
+ ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false)
+ v.tagCache.Set(tag, ctag)
+ }
+ }
+
+ otherVal := reflect.ValueOf(other)
+
+ vd := v.pool.Get().(*validate)
+ vd.top = otherVal
+ vd.isPartial = false
+
+ vd.traverseField(otherVal, reflect.ValueOf(field), vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
+
+ if len(vd.errs) > 0 {
+ err = vd.errs
+ vd.errs = nil
+ }
+
+ v.pool.Put(vd)
+
+ return
+}
diff --git a/validator_test.go b/validator_test.go
index ee61527..30b2fab 100644
--- a/validator_test.go
+++ b/validator_test.go
@@ -1,13 +1,9 @@
package validator
import (
- "database/sql"
"database/sql/driver"
- "encoding/json"
- "fmt"
"reflect"
"testing"
- "time"
. "gopkg.in/go-playground/assert.v1"
)
@@ -70,115 +66,112 @@ type TestString struct {
Iface I
}
-type TestInt32 struct {
- Required int `validate:"required"`
- Len int `validate:"len=10"`
- Min int `validate:"min=1"`
- Max int `validate:"max=10"`
- MinMax int `validate:"min=1,max=10"`
- Lt int `validate:"lt=10"`
- Lte int `validate:"lte=10"`
- Gt int `validate:"gt=10"`
- Gte int `validate:"gte=10"`
- OmitEmpty int `validate:"omitempty,min=1,max=10"`
-}
-
-type TestUint64 struct {
- Required uint64 `validate:"required"`
- Len uint64 `validate:"len=10"`
- Min uint64 `validate:"min=1"`
- Max uint64 `validate:"max=10"`
- MinMax uint64 `validate:"min=1,max=10"`
- OmitEmpty uint64 `validate:"omitempty,min=1,max=10"`
-}
-
-type TestFloat64 struct {
- Required float64 `validate:"required"`
- Len float64 `validate:"len=10"`
- Min float64 `validate:"min=1"`
- Max float64 `validate:"max=10"`
- MinMax float64 `validate:"min=1,max=10"`
- Lte float64 `validate:"lte=10"`
- OmitEmpty float64 `validate:"omitempty,min=1,max=10"`
-}
-
-type TestSlice struct {
- Required []int `validate:"required"`
- Len []int `validate:"len=10"`
- Min []int `validate:"min=1"`
- Max []int `validate:"max=10"`
- MinMax []int `validate:"min=1,max=10"`
- OmitEmpty []int `validate:"omitempty,min=1,max=10"`
-}
-
-var validate = New(&Config{TagName: "validate"})
+// type TestUint64 struct {
+// Required uint64 `validate:"required"`
+// Len uint64 `validate:"len=10"`
+// Min uint64 `validate:"min=1"`
+// Max uint64 `validate:"max=10"`
+// MinMax uint64 `validate:"min=1,max=10"`
+// OmitEmpty uint64 `validate:"omitempty,min=1,max=10"`
+// }
+
+// type TestFloat64 struct {
+// Required float64 `validate:"required"`
+// Len float64 `validate:"len=10"`
+// Min float64 `validate:"min=1"`
+// Max float64 `validate:"max=10"`
+// MinMax float64 `validate:"min=1,max=10"`
+// Lte float64 `validate:"lte=10"`
+// OmitEmpty float64 `validate:"omitempty,min=1,max=10"`
+// }
+
+// type TestSlice struct {
+// Required []int `validate:"required"`
+// Len []int `validate:"len=10"`
+// Min []int `validate:"min=1"`
+// Max []int `validate:"max=10"`
+// MinMax []int `validate:"min=1,max=10"`
+// OmitEmpty []int `validate:"omitempty,min=1,max=10"`
+// }
+
+// var validate = New(&Config{TagName: "validate"})
func AssertError(t *testing.T, err error, key, field, expectedTag string) {
errs := err.(ValidationErrors)
- val, ok := errs[key]
- EqualSkip(t, 2, ok, true)
- NotEqualSkip(t, 2, val, nil)
- EqualSkip(t, 2, val.Field, field)
- EqualSkip(t, 2, val.Tag, expectedTag)
+ found := false
+ var fe FieldError
+
+ for i := 0; i < len(errs); i++ {
+ if errs[i].Namespace() == key {
+ found = true
+ fe = errs[i]
+ break
+ }
+ }
+
+ EqualSkip(t, 2, found, true)
+ NotEqualSkip(t, 2, fe, nil)
+ EqualSkip(t, 2, fe.Field(), field)
+ EqualSkip(t, 2, fe.Tag(), expectedTag)
}
type valuer struct {
Name string
}
-func (v valuer) Value() (driver.Value, error) {
+// func (v valuer) Value() (driver.Value, error) {
- if v.Name == "errorme" {
- panic("SQL Driver Valuer error: some kind of error")
- // return nil, errors.New("some kind of error")
- }
+// if v.Name == "errorme" {
+// panic("SQL Driver Valuer error: some kind of error")
+// // return nil, errors.New("some kind of error")
+// }
- if len(v.Name) == 0 {
- return nil, nil
- }
+// if len(v.Name) == 0 {
+// return nil, nil
+// }
- return v.Name, nil
-}
+// return v.Name, nil
+// }
-type MadeUpCustomType struct {
- FirstName string
- LastName string
-}
+// type MadeUpCustomType struct {
+// FirstName string
+// LastName string
+// }
-func ValidateCustomType(field reflect.Value) interface{} {
- if cust, ok := field.Interface().(MadeUpCustomType); ok {
+// func ValidateCustomType(field reflect.Value) interface{} {
+// if cust, ok := field.Interface().(MadeUpCustomType); ok {
- if len(cust.FirstName) == 0 || len(cust.LastName) == 0 {
- return ""
- }
+// if len(cust.FirstName) == 0 || len(cust.LastName) == 0 {
+// return ""
+// }
- return cust.FirstName + " " + cust.LastName
- }
+// return cust.FirstName + " " + cust.LastName
+// }
- return ""
-}
+// return ""
+// }
-func OverrideIntTypeForSomeReason(field reflect.Value) interface{} {
+// func OverrideIntTypeForSomeReason(field reflect.Value) interface{} {
- if i, ok := field.Interface().(int); ok {
- if i == 1 {
- return "1"
- }
+// if i, ok := field.Interface().(int); ok {
+// if i == 1 {
+// return "1"
+// }
- if i == 2 {
- return "12"
- }
- }
+// if i == 2 {
+// return "12"
+// }
+// }
- return ""
-}
+// return ""
+// }
-type CustomMadeUpStruct struct {
- MadeUp MadeUpCustomType `validate:"required"`
- OverriddenInt int `validate:"gt=1"`
-}
+// type CustomMadeUpStruct struct {
+// MadeUp MadeUpCustomType `validate:"required"`
+// OverriddenInt int `validate:"gt=1"`
+// }
func ValidateValuerType(field reflect.Value) interface{} {
@@ -196,5434 +189,5447 @@ func ValidateValuerType(field reflect.Value) interface{} {
return nil
}
-type TestPartial struct {
- NoTag string
- BlankTag string `validate:""`
- Required string `validate:"required"`
- SubSlice []*SubTest `validate:"required,dive"`
- Sub *SubTest
- SubIgnore *SubTest `validate:"-"`
- Anonymous struct {
- A string `validate:"required"`
- ASubSlice []*SubTest `validate:"required,dive"`
-
- SubAnonStruct []struct {
- Test string `validate:"required"`
- OtherTest string `validate:"required"`
- } `validate:"required,dive"`
- }
-}
+// type TestPartial struct {
+// NoTag string
+// BlankTag string `validate:""`
+// Required string `validate:"required"`
+// SubSlice []*SubTest `validate:"required,dive"`
+// Sub *SubTest
+// SubIgnore *SubTest `validate:"-"`
+// Anonymous struct {
+// A string `validate:"required"`
+// ASubSlice []*SubTest `validate:"required,dive"`
+
+// SubAnonStruct []struct {
+// Test string `validate:"required"`
+// OtherTest string `validate:"required"`
+// } `validate:"required,dive"`
+// }
+// }
type TestStruct struct {
String string `validate:"required" json:"StringVal"`
}
-func StructValidationTestStructSuccess(v *Validate, structLevel *StructLevel) {
+func StructValidationTestStructSuccess(sl StructLevel) {
- st := structLevel.CurrentStruct.Interface().(TestStruct)
+ st := sl.Current().Interface().(TestStruct)
if st.String != "good value" {
- structLevel.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "badvalueteststruct")
+ sl.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "badvalueteststruct")
}
}
-func StructValidationTestStruct(v *Validate, structLevel *StructLevel) {
+func StructValidationTestStruct(sl StructLevel) {
- st := structLevel.CurrentStruct.Interface().(TestStruct)
+ st := sl.Current().Interface().(TestStruct)
if st.String != "bad value" {
- structLevel.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "badvalueteststruct")
+ sl.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "badvalueteststruct")
}
}
-func StructValidationBadTestStructFieldName(v *Validate, structLevel *StructLevel) {
+// func StructValidationBadTestStructFieldName(v *Validate, structLevel *StructLevel) {
- st := structLevel.CurrentStruct.Interface().(TestStruct)
+// st := structLevel.CurrentStruct.Interface().(TestStruct)
- if st.String != "bad value" {
- structLevel.ReportError(reflect.ValueOf(st.String), "", "StringVal", "badvalueteststruct")
- }
-}
+// if st.String != "bad value" {
+// structLevel.ReportError(reflect.ValueOf(st.String), "", "StringVal", "badvalueteststruct")
+// }
+// }
-func StructValidationBadTestStructTag(v *Validate, structLevel *StructLevel) {
+// func StructValidationBadTestStructTag(v *Validate, structLevel *StructLevel) {
- st := structLevel.CurrentStruct.Interface().(TestStruct)
+// st := structLevel.CurrentStruct.Interface().(TestStruct)
- if st.String != "bad value" {
- structLevel.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "")
- }
-}
+// if st.String != "bad value" {
+// structLevel.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "")
+// }
+// }
-func StructValidationNoTestStructCustomName(v *Validate, structLevel *StructLevel) {
+// func StructValidationNoTestStructCustomName(v *Validate, structLevel *StructLevel) {
- st := structLevel.CurrentStruct.Interface().(TestStruct)
+// st := structLevel.CurrentStruct.Interface().(TestStruct)
- if st.String != "bad value" {
- structLevel.ReportError(reflect.ValueOf(st.String), "String", "", "badvalueteststruct")
- }
-}
+// if st.String != "bad value" {
+// structLevel.ReportError(reflect.ValueOf(st.String), "String", "", "badvalueteststruct")
+// }
+// }
-func StructValidationTestStructInvalid(v *Validate, structLevel *StructLevel) {
+// func StructValidationTestStructInvalid(v *Validate, structLevel *StructLevel) {
- st := structLevel.CurrentStruct.Interface().(TestStruct)
+// st := structLevel.CurrentStruct.Interface().(TestStruct)
- if st.String != "bad value" {
- structLevel.ReportError(reflect.ValueOf(nil), "String", "StringVal", "badvalueteststruct")
- }
-}
+// if st.String != "bad value" {
+// structLevel.ReportError(reflect.ValueOf(nil), "String", "StringVal", "badvalueteststruct")
+// }
+// }
-func StructValidationTestStructReturnValidationErrors(v *Validate, structLevel *StructLevel) {
+// func StructValidationTestStructReturnValidationErrors(v *Validate, structLevel *StructLevel) {
- s := structLevel.CurrentStruct.Interface().(TestStructReturnValidationErrors)
+// s := structLevel.CurrentStruct.Interface().(TestStructReturnValidationErrors)
- errs := v.Struct(s.Inner1.Inner2)
- if errs == nil {
- return
- }
+// errs := v.Struct(s.Inner1.Inner2)
+// if errs == nil {
+// return
+// }
- structLevel.ReportValidationErrors("Inner1.", errs.(ValidationErrors))
-}
+// structLevel.ReportValidationErrors("Inner1.", errs.(ValidationErrors))
+// }
-func StructValidationTestStructReturnValidationErrors2(v *Validate, structLevel *StructLevel) {
+// func StructValidationTestStructReturnValidationErrors2(v *Validate, structLevel *StructLevel) {
- s := structLevel.CurrentStruct.Interface().(TestStructReturnValidationErrors)
+// s := structLevel.CurrentStruct.Interface().(TestStructReturnValidationErrors)
- errs := v.Struct(s.Inner1.Inner2)
- if errs == nil {
- return
- }
+// errs := v.Struct(s.Inner1.Inner2)
+// if errs == nil {
+// return
+// }
- structLevel.ReportValidationErrors("Inner1.|Inner1JSON.", errs.(ValidationErrors))
-}
+// structLevel.ReportValidationErrors("Inner1.|Inner1JSON.", errs.(ValidationErrors))
+// }
-type TestStructReturnValidationErrorsInner2 struct {
- String string `validate:"required" json:"JSONString"`
-}
+// type TestStructReturnValidationErrorsInner2 struct {
+// String string `validate:"required" json:"JSONString"`
+// }
-type TestStructReturnValidationErrorsInner1 struct {
- Inner2 *TestStructReturnValidationErrorsInner2
-}
+// type TestStructReturnValidationErrorsInner1 struct {
+// Inner2 *TestStructReturnValidationErrorsInner2
+// }
-type TestStructReturnValidationErrors struct {
- Inner1 *TestStructReturnValidationErrorsInner1 `json:"Inner1JSON"`
-}
+// type TestStructReturnValidationErrors struct {
+// Inner1 *TestStructReturnValidationErrorsInner1 `json:"Inner1JSON"`
+// }
-type Inner2Namespace struct {
- String []string `validate:"dive,required" json:"JSONString"`
-}
+// type Inner2Namespace struct {
+// String []string `validate:"dive,required" json:"JSONString"`
+// }
-type Inner1Namespace struct {
- Inner2 *Inner2Namespace `json:"Inner2JSON"`
-}
+// type Inner1Namespace struct {
+// Inner2 *Inner2Namespace `json:"Inner2JSON"`
+// }
-type Namespace struct {
- Inner1 *Inner1Namespace `json:"Inner1JSON"`
-}
+// type Namespace struct {
+// Inner1 *Inner1Namespace `json:"Inner1JSON"`
+// }
-func TestNameNamespace(t *testing.T) {
+// func TestNameNamespace(t *testing.T) {
- config := &Config{
- TagName: "validate",
- FieldNameTag: "json",
- }
+// config := &Config{
+// TagName: "validate",
+// FieldNameTag: "json",
+// }
- v1 := New(config)
- i2 := &Inner2Namespace{String: []string{"ok", "ok", "ok"}}
- i1 := &Inner1Namespace{Inner2: i2}
- ns := &Namespace{Inner1: i1}
+// v1 := New(config)
+// i2 := &Inner2Namespace{String: []string{"ok", "ok", "ok"}}
+// i1 := &Inner1Namespace{Inner2: i2}
+// ns := &Namespace{Inner1: i1}
- errs := v1.Struct(ns)
- Equal(t, errs, nil)
+// errs := v1.Struct(ns)
+// Equal(t, errs, nil)
- i2.String[1] = ""
+// i2.String[1] = ""
- errs = v1.Struct(ns)
- NotEqual(t, errs, nil)
+// errs = v1.Struct(ns)
+// NotEqual(t, errs, nil)
- ve := errs.(ValidationErrors)
- Equal(t, len(ve), 1)
- AssertError(t, errs, "Namespace.Inner1.Inner2.String[1]", "String[1]", "required")
+// ve := errs.(ValidationErrors)
+// Equal(t, len(ve), 1)
+// AssertError(t, errs, "Namespace.Inner1.Inner2.String[1]", "String[1]", "required")
- fe, ok := ve["Namespace.Inner1.Inner2.String[1]"]
- Equal(t, ok, true)
+// fe, ok := ve["Namespace.Inner1.Inner2.String[1]"]
+// Equal(t, ok, true)
- Equal(t, fe.Field, "String[1]")
- Equal(t, fe.FieldNamespace, "Namespace.Inner1.Inner2.String[1]")
- Equal(t, fe.Name, "JSONString[1]")
- Equal(t, fe.NameNamespace, "Namespace.Inner1JSON.Inner2JSON.JSONString[1]")
-}
+// Equal(t, fe.Field, "String[1]")
+// Equal(t, fe.FieldNamespace, "Namespace.Inner1.Inner2.String[1]")
+// Equal(t, fe.Name, "JSONString[1]")
+// Equal(t, fe.NameNamespace, "Namespace.Inner1JSON.Inner2JSON.JSONString[1]")
+// }
-func TestAnonymous(t *testing.T) {
+// func TestAnonymous(t *testing.T) {
- v2 := New(&Config{TagName: "validate", FieldNameTag: "json"})
+// v2 := New(&Config{TagName: "validate", FieldNameTag: "json"})
+
+// type Test struct {
+// Anonymous struct {
+// A string `validate:"required" json:"EH"`
+// }
+// AnonymousB struct {
+// B string `validate:"required" json:"BEE"`
+// }
+// anonymousC struct {
+// c string `validate:"required"`
+// }
+// }
+
+// tst := &Test{
+// Anonymous: struct {
+// A string `validate:"required" json:"EH"`
+// }{
+// A: "1",
+// },
+// AnonymousB: struct {
+// B string `validate:"required" json:"BEE"`
+// }{
+// B: "",
+// },
+// anonymousC: struct {
+// c string `validate:"required"`
+// }{
+// c: "",
+// },
+// }
+
+// err := v2.Struct(tst)
+// NotEqual(t, err, nil)
+
+// errs := err.(ValidationErrors)
+
+// Equal(t, len(errs), 1)
+// AssertError(t, errs, "Test.AnonymousB.B", "B", "required")
+// Equal(t, errs["Test.AnonymousB.B"].Field, "B")
+// Equal(t, errs["Test.AnonymousB.B"].Name, "BEE")
+
+// s := struct {
+// c string `validate:"required"`
+// }{
+// c: "",
+// }
+
+// err = v2.Struct(s)
+// Equal(t, err, nil)
+// }
+
+// func TestAnonymousSameStructDifferentTags(t *testing.T) {
+
+// v2 := New(&Config{TagName: "validate", FieldNameTag: "json"})
+
+// type Test struct {
+// A interface{}
+// }
+
+// tst := &Test{
+// A: struct {
+// A string `validate:"required"`
+// }{
+// A: "",
+// },
+// }
+
+// err := v2.Struct(tst)
+// NotEqual(t, err, nil)
+
+// errs := err.(ValidationErrors)
+
+// Equal(t, len(errs), 1)
+// AssertError(t, errs, "Test.A.A", "A", "required")
+
+// tst = &Test{
+// A: struct {
+// A string `validate:"omitempty,required"`
+// }{
+// A: "",
+// },
+// }
+
+// err = v2.Struct(tst)
+// Equal(t, err, nil)
+// }
+
+// func TestStructLevelReturnValidationErrors(t *testing.T) {
+// config := &Config{
+// TagName: "validate",
+// }
+
+// v1 := New(config)
+// v1.RegisterStructValidation(StructValidationTestStructReturnValidationErrors, TestStructReturnValidationErrors{})
+
+// inner2 := &TestStructReturnValidationErrorsInner2{
+// String: "I'm HERE",
+// }
+
+// inner1 := &TestStructReturnValidationErrorsInner1{
+// Inner2: inner2,
+// }
+
+// val := &TestStructReturnValidationErrors{
+// Inner1: inner1,
+// }
+
+// errs := v1.Struct(val)
+// Equal(t, errs, nil)
+
+// inner2.String = ""
+
+// errs = v1.Struct(val)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 2)
+// AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.Inner2.String", "String", "required")
+// // this is an extra error reported from struct validation
+// AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.String", "String", "required")
+// }
- type Test struct {
- Anonymous struct {
- A string `validate:"required" json:"EH"`
- }
- AnonymousB struct {
- B string `validate:"required" json:"BEE"`
- }
- anonymousC struct {
- c string `validate:"required"`
- }
- }
+// func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) {
+// config := &Config{
+// TagName: "validate",
+// FieldNameTag: "json",
+// }
- tst := &Test{
- Anonymous: struct {
- A string `validate:"required" json:"EH"`
- }{
- A: "1",
- },
- AnonymousB: struct {
- B string `validate:"required" json:"BEE"`
- }{
- B: "",
- },
- anonymousC: struct {
- c string `validate:"required"`
- }{
- c: "",
- },
- }
+// v1 := New(config)
+// v1.RegisterStructValidation(StructValidationTestStructReturnValidationErrors2, TestStructReturnValidationErrors{})
- err := v2.Struct(tst)
- NotEqual(t, err, nil)
+// inner2 := &TestStructReturnValidationErrorsInner2{
+// String: "I'm HERE",
+// }
- errs := err.(ValidationErrors)
+// inner1 := &TestStructReturnValidationErrorsInner1{
+// Inner2: inner2,
+// }
- Equal(t, len(errs), 1)
- AssertError(t, errs, "Test.AnonymousB.B", "B", "required")
- Equal(t, errs["Test.AnonymousB.B"].Field, "B")
- Equal(t, errs["Test.AnonymousB.B"].Name, "BEE")
+// val := &TestStructReturnValidationErrors{
+// Inner1: inner1,
+// }
- s := struct {
- c string `validate:"required"`
- }{
- c: "",
- }
+// errs := v1.Struct(val)
+// Equal(t, errs, nil)
- err = v2.Struct(s)
- Equal(t, err, nil)
-}
+// inner2.String = ""
-func TestAnonymousSameStructDifferentTags(t *testing.T) {
+// errs = v1.Struct(val)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 2)
+// AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.Inner2.String", "String", "required")
+// // this is an extra error reported from struct validation, it's a badly formatted one, but on purpose
+// AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.String", "String", "required")
- v2 := New(&Config{TagName: "validate", FieldNameTag: "json"})
+// fe, ok := errs.(ValidationErrors)["TestStructReturnValidationErrors.Inner1.Inner2.String"]
+// Equal(t, ok, true)
- type Test struct {
- A interface{}
- }
+// // check for proper JSON namespace
+// Equal(t, fe.Field, "String")
+// Equal(t, fe.Name, "JSONString")
+// Equal(t, fe.FieldNamespace, "TestStructReturnValidationErrors.Inner1.Inner2.String")
+// Equal(t, fe.NameNamespace, "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString")
- tst := &Test{
- A: struct {
- A string `validate:"required"`
- }{
- A: "",
- },
- }
+// fe, ok = errs.(ValidationErrors)["TestStructReturnValidationErrors.Inner1.String"]
+// Equal(t, ok, true)
- err := v2.Struct(tst)
- NotEqual(t, err, nil)
+// // check for proper JSON namespace
+// Equal(t, fe.Field, "String")
+// Equal(t, fe.Name, "JSONString")
+// Equal(t, fe.FieldNamespace, "TestStructReturnValidationErrors.Inner1.String")
+// Equal(t, fe.NameNamespace, "TestStructReturnValidationErrors.Inner1JSON.JSONString")
+// }
- errs := err.(ValidationErrors)
+// func TestStructLevelValidations(t *testing.T) {
- Equal(t, len(errs), 1)
- AssertError(t, errs, "Test.A.A", "A", "required")
+// config := &Config{
+// TagName: "validate",
+// }
- tst = &Test{
- A: struct {
- A string `validate:"omitempty,required"`
- }{
- A: "",
- },
- }
+// v1 := New(config)
+// v1.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
- err = v2.Struct(tst)
- Equal(t, err, nil)
-}
+// tst := &TestStruct{
+// String: "good value",
+// }
-func TestStructLevelReturnValidationErrors(t *testing.T) {
- config := &Config{
- TagName: "validate",
- }
+// errs := v1.Struct(tst)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
- v1 := New(config)
- v1.RegisterStructValidation(StructValidationTestStructReturnValidationErrors, TestStructReturnValidationErrors{})
+// v2 := New(config)
+// v2.RegisterStructValidation(StructValidationBadTestStructFieldName, TestStruct{})
- inner2 := &TestStructReturnValidationErrorsInner2{
- String: "I'm HERE",
- }
+// PanicMatches(t, func() { v2.Struct(tst) }, fieldNameRequired)
- inner1 := &TestStructReturnValidationErrorsInner1{
- Inner2: inner2,
- }
+// v3 := New(config)
+// v3.RegisterStructValidation(StructValidationBadTestStructTag, TestStruct{})
- val := &TestStructReturnValidationErrors{
- Inner1: inner1,
- }
+// PanicMatches(t, func() { v3.Struct(tst) }, tagRequired)
- errs := v1.Struct(val)
- Equal(t, errs, nil)
+// v4 := New(config)
+// v4.RegisterStructValidation(StructValidationNoTestStructCustomName, TestStruct{})
- inner2.String = ""
+// errs = v4.Struct(tst)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
- errs = v1.Struct(val)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.Inner2.String", "String", "required")
- // this is an extra error reported from struct validation
- AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.String", "String", "required")
-}
+// v5 := New(config)
+// v5.RegisterStructValidation(StructValidationTestStructInvalid, TestStruct{})
-func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) {
- config := &Config{
- TagName: "validate",
- FieldNameTag: "json",
- }
+// errs = v5.Struct(tst)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
- v1 := New(config)
- v1.RegisterStructValidation(StructValidationTestStructReturnValidationErrors2, TestStructReturnValidationErrors{})
+// v6 := New(config)
+// v6.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{})
- inner2 := &TestStructReturnValidationErrorsInner2{
- String: "I'm HERE",
- }
+// errs = v6.Struct(tst)
+// Equal(t, errs, nil)
+// }
- inner1 := &TestStructReturnValidationErrorsInner1{
- Inner2: inner2,
- }
+// func TestAliasTags(t *testing.T) {
- val := &TestStructReturnValidationErrors{
- Inner1: inner1,
- }
+// validate.RegisterAliasValidation("iscolor", "hexcolor|rgb|rgba|hsl|hsla")
- errs := v1.Struct(val)
- Equal(t, errs, nil)
+// s := "rgb(255,255,255)"
+// errs := validate.Field(s, "iscolor")
+// Equal(t, errs, nil)
- inner2.String = ""
+// s = ""
+// errs = validate.Field(s, "omitempty,iscolor")
+// Equal(t, errs, nil)
- errs = v1.Struct(val)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.Inner2.String", "String", "required")
- // this is an extra error reported from struct validation, it's a badly formatted one, but on purpose
- AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.String", "String", "required")
-
- fe, ok := errs.(ValidationErrors)["TestStructReturnValidationErrors.Inner1.Inner2.String"]
- Equal(t, ok, true)
-
- // check for proper JSON namespace
- Equal(t, fe.Field, "String")
- Equal(t, fe.Name, "JSONString")
- Equal(t, fe.FieldNamespace, "TestStructReturnValidationErrors.Inner1.Inner2.String")
- Equal(t, fe.NameNamespace, "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString")
-
- fe, ok = errs.(ValidationErrors)["TestStructReturnValidationErrors.Inner1.String"]
- Equal(t, ok, true)
-
- // check for proper JSON namespace
- Equal(t, fe.Field, "String")
- Equal(t, fe.Name, "JSONString")
- Equal(t, fe.FieldNamespace, "TestStructReturnValidationErrors.Inner1.String")
- Equal(t, fe.NameNamespace, "TestStructReturnValidationErrors.Inner1JSON.JSONString")
-}
+// s = "rgb(255,255,0)"
+// errs = validate.Field(s, "iscolor,len=5")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "len")
-func TestStructLevelValidations(t *testing.T) {
+// type Test struct {
+// Color string `validate:"iscolor"`
+// }
- config := &Config{
- TagName: "validate",
- }
+// tst := &Test{
+// Color: "#000",
+// }
+
+// errs = validate.Struct(tst)
+// Equal(t, errs, nil)
+
+// tst.Color = "cfvre"
+// errs = validate.Struct(tst)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.Color", "Color", "iscolor")
+// Equal(t, errs.(ValidationErrors)["Test.Color"].ActualTag, "hexcolor|rgb|rgba|hsl|hsla")
+
+// validate.RegisterAliasValidation("req", "required,dive,iscolor")
+// arr := []string{"val1", "#fff", "#000"}
+
+// errs = validate.Field(arr, "req")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "[0]", "[0]", "iscolor")
+
+// PanicMatches(t, func() { validate.RegisterAliasValidation("exists", "gt=5,lt=10") }, "Alias 'exists' either contains restricted characters or is the same as a restricted tag needed for normal operation")
+// }
+
+// func TestNilValidator(t *testing.T) {
+
+// type TestStruct struct {
+// Test string `validate:"required"`
+// }
+
+// ts := TestStruct{}
+
+// var val *Validate
+
+// fn := func(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+
+// return current.String() == field.String()
+// }
+
+// PanicMatches(t, func() { val.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) }, validatorNotInitialized)
+// PanicMatches(t, func() { val.RegisterValidation("something", fn) }, validatorNotInitialized)
+// PanicMatches(t, func() { val.Field(ts.Test, "required") }, validatorNotInitialized)
+// PanicMatches(t, func() { val.FieldWithValue("test", ts.Test, "required") }, validatorNotInitialized)
+// PanicMatches(t, func() { val.Struct(ts) }, validatorNotInitialized)
+// PanicMatches(t, func() { val.StructExcept(ts, "Test") }, validatorNotInitialized)
+// PanicMatches(t, func() { val.StructPartial(ts, "Test") }, validatorNotInitialized)
+// }
+
+// func TestStructPartial(t *testing.T) {
+
+// p1 := []string{
+// "NoTag",
+// "Required",
+// }
+
+// p2 := []string{
+// "SubSlice[0].Test",
+// "Sub",
+// "SubIgnore",
+// "Anonymous.A",
+// }
+
+// p3 := []string{
+// "SubTest.Test",
+// }
+
+// p4 := []string{
+// "A",
+// }
+
+// tPartial := &TestPartial{
+// NoTag: "NoTag",
+// Required: "Required",
+
+// SubSlice: []*SubTest{
+// {
+
+// Test: "Required",
+// },
+// {
+
+// Test: "Required",
+// },
+// },
+
+// Sub: &SubTest{
+// Test: "1",
+// },
+// SubIgnore: &SubTest{
+// Test: "",
+// },
+// Anonymous: struct {
+// A string `validate:"required"`
+// ASubSlice []*SubTest `validate:"required,dive"`
+// SubAnonStruct []struct {
+// Test string `validate:"required"`
+// OtherTest string `validate:"required"`
+// } `validate:"required,dive"`
+// }{
+// A: "1",
+// ASubSlice: []*SubTest{
+// {
+// Test: "Required",
+// },
+// {
+// Test: "Required",
+// },
+// },
+
+// SubAnonStruct: []struct {
+// Test string `validate:"required"`
+// OtherTest string `validate:"required"`
+// }{
+// {"Required", "RequiredOther"},
+// {"Required", "RequiredOther"},
+// },
+// },
+// }
+
+// // the following should all return no errors as everything is valid in
+// // the default state
+// errs := validate.StructPartial(tPartial, p1...)
+// Equal(t, errs, nil)
+
+// errs = validate.StructPartial(tPartial, p2...)
+// Equal(t, errs, nil)
+
+// // this isn't really a robust test, but is ment to illustrate the ANON CASE below
+// errs = validate.StructPartial(tPartial.SubSlice[0], p3...)
+// Equal(t, errs, nil)
+
+// errs = validate.StructExcept(tPartial, p1...)
+// Equal(t, errs, nil)
+
+// errs = validate.StructExcept(tPartial, p2...)
+// Equal(t, errs, nil)
+
+// // mod tParial for required feild and re-test making sure invalid fields are NOT required:
+// tPartial.Required = ""
+
+// errs = validate.StructExcept(tPartial, p1...)
+// Equal(t, errs, nil)
+
+// errs = validate.StructPartial(tPartial, p2...)
+// Equal(t, errs, nil)
+
+// // inversion and retesting Partial to generate failures:
+// errs = validate.StructPartial(tPartial, p1...)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestPartial.Required", "Required", "required")
+
+// errs = validate.StructExcept(tPartial, p2...)
+// AssertError(t, errs, "TestPartial.Required", "Required", "required")
+
+// // reset Required field, and set nested struct
+// tPartial.Required = "Required"
+// tPartial.Anonymous.A = ""
+
+// // will pass as unset feilds is not going to be tested
+// errs = validate.StructPartial(tPartial, p1...)
+// Equal(t, errs, nil)
+
+// errs = validate.StructExcept(tPartial, p2...)
+// Equal(t, errs, nil)
+
+// // ANON CASE the response here is strange, it clearly does what it is being told to
+// errs = validate.StructExcept(tPartial.Anonymous, p4...)
+// Equal(t, errs, nil)
+
+// // will fail as unset feild is tested
+// errs = validate.StructPartial(tPartial, p2...)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestPartial.Anonymous.A", "A", "required")
+
+// errs = validate.StructExcept(tPartial, p1...)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestPartial.Anonymous.A", "A", "required")
+
+// // reset nested struct and unset struct in slice
+// tPartial.Anonymous.A = "Required"
+// tPartial.SubSlice[0].Test = ""
+
+// // these will pass as unset item is NOT tested
+// errs = validate.StructPartial(tPartial, p1...)
+// Equal(t, errs, nil)
+
+// errs = validate.StructExcept(tPartial, p2...)
+// Equal(t, errs, nil)
+
+// // these will fail as unset item IS tested
+// errs = validate.StructExcept(tPartial, p1...)
+// AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
+// Equal(t, len(errs.(ValidationErrors)), 1)
+
+// errs = validate.StructPartial(tPartial, p2...)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
+// Equal(t, len(errs.(ValidationErrors)), 1)
+
+// // Unset second slice member concurrently to test dive behavior:
+// tPartial.SubSlice[1].Test = ""
+
+// errs = validate.StructPartial(tPartial, p1...)
+// Equal(t, errs, nil)
+
+// // NOTE: When specifying nested items, it is still the users responsibility
+// // to specify the dive tag, the library does not override this.
+// errs = validate.StructExcept(tPartial, p2...)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
+
+// errs = validate.StructExcept(tPartial, p1...)
+// Equal(t, len(errs.(ValidationErrors)), 2)
+// AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
+// AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
+
+// errs = validate.StructPartial(tPartial, p2...)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
+
+// // reset struct in slice, and unset struct in slice in unset posistion
+// tPartial.SubSlice[0].Test = "Required"
+
+// // these will pass as the unset item is NOT tested
+// errs = validate.StructPartial(tPartial, p1...)
+// Equal(t, errs, nil)
+
+// errs = validate.StructPartial(tPartial, p2...)
+// Equal(t, errs, nil)
+
+// // testing for missing item by exception, yes it dives and fails
+// errs = validate.StructExcept(tPartial, p1...)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
+
+// errs = validate.StructExcept(tPartial, p2...)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
+
+// tPartial.SubSlice[1].Test = "Required"
+
+// tPartial.Anonymous.SubAnonStruct[0].Test = ""
+// // these will pass as the unset item is NOT tested
+// errs = validate.StructPartial(tPartial, p1...)
+// Equal(t, errs, nil)
+
+// errs = validate.StructPartial(tPartial, p2...)
+// Equal(t, errs, nil)
+
+// errs = validate.StructExcept(tPartial, p1...)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "required")
+
+// errs = validate.StructExcept(tPartial, p2...)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "required")
+
+// }
+
+// func TestCrossStructLteFieldValidation(t *testing.T) {
+
+// type Inner struct {
+// CreatedAt *time.Time
+// String string
+// Int int
+// Uint uint
+// Float float64
+// Array []string
+// }
+
+// type Test struct {
+// Inner *Inner
+// CreatedAt *time.Time `validate:"ltecsfield=Inner.CreatedAt"`
+// String string `validate:"ltecsfield=Inner.String"`
+// Int int `validate:"ltecsfield=Inner.Int"`
+// Uint uint `validate:"ltecsfield=Inner.Uint"`
+// Float float64 `validate:"ltecsfield=Inner.Float"`
+// Array []string `validate:"ltecsfield=Inner.Array"`
+// }
+
+// now := time.Now().UTC()
+// then := now.Add(time.Hour * 5)
+
+// inner := &Inner{
+// CreatedAt: &then,
+// String: "abcd",
+// Int: 13,
+// Uint: 13,
+// Float: 1.13,
+// Array: []string{"val1", "val2"},
+// }
+
+// test := &Test{
+// Inner: inner,
+// CreatedAt: &now,
+// String: "abc",
+// Int: 12,
+// Uint: 12,
+// Float: 1.12,
+// Array: []string{"val1"},
+// }
+
+// errs := validate.Struct(test)
+// Equal(t, errs, nil)
+
+// test.CreatedAt = &then
+// test.String = "abcd"
+// test.Int = 13
+// test.Uint = 13
+// test.Float = 1.13
+// test.Array = []string{"val1", "val2"}
+
+// errs = validate.Struct(test)
+// Equal(t, errs, nil)
+
+// after := now.Add(time.Hour * 10)
+
+// test.CreatedAt = &after
+// test.String = "abce"
+// test.Int = 14
+// test.Uint = 14
+// test.Float = 1.14
+// test.Array = []string{"val1", "val2", "val3"}
+
+// errs = validate.Struct(test)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "ltecsfield")
+// AssertError(t, errs, "Test.String", "String", "ltecsfield")
+// AssertError(t, errs, "Test.Int", "Int", "ltecsfield")
+// AssertError(t, errs, "Test.Uint", "Uint", "ltecsfield")
+// AssertError(t, errs, "Test.Float", "Float", "ltecsfield")
+// AssertError(t, errs, "Test.Array", "Array", "ltecsfield")
+
+// errs = validate.FieldWithValue(1, "", "ltecsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltecsfield")
+
+// errs = validate.FieldWithValue(test, now, "ltecsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltecsfield")
+// }
+
+// func TestCrossStructLtFieldValidation(t *testing.T) {
+
+// type Inner struct {
+// CreatedAt *time.Time
+// String string
+// Int int
+// Uint uint
+// Float float64
+// Array []string
+// }
+
+// type Test struct {
+// Inner *Inner
+// CreatedAt *time.Time `validate:"ltcsfield=Inner.CreatedAt"`
+// String string `validate:"ltcsfield=Inner.String"`
+// Int int `validate:"ltcsfield=Inner.Int"`
+// Uint uint `validate:"ltcsfield=Inner.Uint"`
+// Float float64 `validate:"ltcsfield=Inner.Float"`
+// Array []string `validate:"ltcsfield=Inner.Array"`
+// }
+
+// now := time.Now().UTC()
+// then := now.Add(time.Hour * 5)
+
+// inner := &Inner{
+// CreatedAt: &then,
+// String: "abcd",
+// Int: 13,
+// Uint: 13,
+// Float: 1.13,
+// Array: []string{"val1", "val2"},
+// }
+
+// test := &Test{
+// Inner: inner,
+// CreatedAt: &now,
+// String: "abc",
+// Int: 12,
+// Uint: 12,
+// Float: 1.12,
+// Array: []string{"val1"},
+// }
+
+// errs := validate.Struct(test)
+// Equal(t, errs, nil)
+
+// test.CreatedAt = &then
+// test.String = "abcd"
+// test.Int = 13
+// test.Uint = 13
+// test.Float = 1.13
+// test.Array = []string{"val1", "val2"}
+
+// errs = validate.Struct(test)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "ltcsfield")
+// AssertError(t, errs, "Test.String", "String", "ltcsfield")
+// AssertError(t, errs, "Test.Int", "Int", "ltcsfield")
+// AssertError(t, errs, "Test.Uint", "Uint", "ltcsfield")
+// AssertError(t, errs, "Test.Float", "Float", "ltcsfield")
+// AssertError(t, errs, "Test.Array", "Array", "ltcsfield")
+
+// errs = validate.FieldWithValue(1, "", "ltcsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltcsfield")
+
+// errs = validate.FieldWithValue(test, now, "ltcsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltcsfield")
+// }
+
+// func TestCrossStructGteFieldValidation(t *testing.T) {
+
+// type Inner struct {
+// CreatedAt *time.Time
+// String string
+// Int int
+// Uint uint
+// Float float64
+// Array []string
+// }
+
+// type Test struct {
+// Inner *Inner
+// CreatedAt *time.Time `validate:"gtecsfield=Inner.CreatedAt"`
+// String string `validate:"gtecsfield=Inner.String"`
+// Int int `validate:"gtecsfield=Inner.Int"`
+// Uint uint `validate:"gtecsfield=Inner.Uint"`
+// Float float64 `validate:"gtecsfield=Inner.Float"`
+// Array []string `validate:"gtecsfield=Inner.Array"`
+// }
+
+// now := time.Now().UTC()
+// then := now.Add(time.Hour * -5)
+
+// inner := &Inner{
+// CreatedAt: &then,
+// String: "abcd",
+// Int: 13,
+// Uint: 13,
+// Float: 1.13,
+// Array: []string{"val1", "val2"},
+// }
+
+// test := &Test{
+// Inner: inner,
+// CreatedAt: &now,
+// String: "abcde",
+// Int: 14,
+// Uint: 14,
+// Float: 1.14,
+// Array: []string{"val1", "val2", "val3"},
+// }
+
+// errs := validate.Struct(test)
+// Equal(t, errs, nil)
+
+// test.CreatedAt = &then
+// test.String = "abcd"
+// test.Int = 13
+// test.Uint = 13
+// test.Float = 1.13
+// test.Array = []string{"val1", "val2"}
+
+// errs = validate.Struct(test)
+// Equal(t, errs, nil)
+
+// before := now.Add(time.Hour * -10)
+
+// test.CreatedAt = &before
+// test.String = "abc"
+// test.Int = 12
+// test.Uint = 12
+// test.Float = 1.12
+// test.Array = []string{"val1"}
+
+// errs = validate.Struct(test)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "gtecsfield")
+// AssertError(t, errs, "Test.String", "String", "gtecsfield")
+// AssertError(t, errs, "Test.Int", "Int", "gtecsfield")
+// AssertError(t, errs, "Test.Uint", "Uint", "gtecsfield")
+// AssertError(t, errs, "Test.Float", "Float", "gtecsfield")
+// AssertError(t, errs, "Test.Array", "Array", "gtecsfield")
+
+// errs = validate.FieldWithValue(1, "", "gtecsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtecsfield")
+
+// errs = validate.FieldWithValue(test, now, "gtecsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtecsfield")
+// }
+
+// func TestCrossStructGtFieldValidation(t *testing.T) {
+
+// type Inner struct {
+// CreatedAt *time.Time
+// String string
+// Int int
+// Uint uint
+// Float float64
+// Array []string
+// }
+
+// type Test struct {
+// Inner *Inner
+// CreatedAt *time.Time `validate:"gtcsfield=Inner.CreatedAt"`
+// String string `validate:"gtcsfield=Inner.String"`
+// Int int `validate:"gtcsfield=Inner.Int"`
+// Uint uint `validate:"gtcsfield=Inner.Uint"`
+// Float float64 `validate:"gtcsfield=Inner.Float"`
+// Array []string `validate:"gtcsfield=Inner.Array"`
+// }
+
+// now := time.Now().UTC()
+// then := now.Add(time.Hour * -5)
+
+// inner := &Inner{
+// CreatedAt: &then,
+// String: "abcd",
+// Int: 13,
+// Uint: 13,
+// Float: 1.13,
+// Array: []string{"val1", "val2"},
+// }
+
+// test := &Test{
+// Inner: inner,
+// CreatedAt: &now,
+// String: "abcde",
+// Int: 14,
+// Uint: 14,
+// Float: 1.14,
+// Array: []string{"val1", "val2", "val3"},
+// }
+
+// errs := validate.Struct(test)
+// Equal(t, errs, nil)
+
+// test.CreatedAt = &then
+// test.String = "abcd"
+// test.Int = 13
+// test.Uint = 13
+// test.Float = 1.13
+// test.Array = []string{"val1", "val2"}
+
+// errs = validate.Struct(test)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "gtcsfield")
+// AssertError(t, errs, "Test.String", "String", "gtcsfield")
+// AssertError(t, errs, "Test.Int", "Int", "gtcsfield")
+// AssertError(t, errs, "Test.Uint", "Uint", "gtcsfield")
+// AssertError(t, errs, "Test.Float", "Float", "gtcsfield")
+// AssertError(t, errs, "Test.Array", "Array", "gtcsfield")
+
+// errs = validate.FieldWithValue(1, "", "gtcsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtcsfield")
+
+// errs = validate.FieldWithValue(test, now, "gtcsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtcsfield")
+// }
+
+// func TestCrossStructNeFieldValidation(t *testing.T) {
+
+// type Inner struct {
+// CreatedAt *time.Time
+// }
+
+// type Test struct {
+// Inner *Inner
+// CreatedAt *time.Time `validate:"necsfield=Inner.CreatedAt"`
+// }
+
+// now := time.Now().UTC()
+// then := now.Add(time.Hour * 5)
+
+// inner := &Inner{
+// CreatedAt: &then,
+// }
+
+// test := &Test{
+// Inner: inner,
+// CreatedAt: &now,
+// }
+
+// errs := validate.Struct(test)
+// Equal(t, errs, nil)
+
+// test.CreatedAt = &then
+
+// errs = validate.Struct(test)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "necsfield")
+
+// var j uint64
+// var k float64
+// var j2 uint64
+// var k2 float64
+// s := "abcd"
+// i := 1
+// j = 1
+// k = 1.543
+// arr := []string{"test"}
+
+// s2 := "abcd"
+// i2 := 1
+// j2 = 1
+// k2 = 1.543
+// arr2 := []string{"test"}
+// arr3 := []string{"test", "test2"}
+// now2 := now
+
+// errs = validate.FieldWithValue(s, s2, "necsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "necsfield")
+
+// errs = validate.FieldWithValue(i2, i, "necsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "necsfield")
+
+// errs = validate.FieldWithValue(j2, j, "necsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "necsfield")
+
+// errs = validate.FieldWithValue(k2, k, "necsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "necsfield")
+
+// errs = validate.FieldWithValue(arr2, arr, "necsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "necsfield")
+
+// errs = validate.FieldWithValue(now2, now, "necsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "necsfield")
+
+// errs = validate.FieldWithValue(arr3, arr, "necsfield")
+// Equal(t, errs, nil)
+
+// type SInner struct {
+// Name string
+// }
+
+// type TStruct struct {
+// Inner *SInner
+// CreatedAt *time.Time `validate:"necsfield=Inner"`
+// }
+
+// sinner := &SInner{
+// Name: "NAME",
+// }
+
+// test2 := &TStruct{
+// Inner: sinner,
+// CreatedAt: &now,
+// }
+
+// errs = validate.Struct(test2)
+// Equal(t, errs, nil)
+
+// test2.Inner = nil
+// errs = validate.Struct(test2)
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(nil, 1, "necsfield")
+// Equal(t, errs, nil)
+// }
+
+// func TestCrossStructEqFieldValidation(t *testing.T) {
+
+// type Inner struct {
+// CreatedAt *time.Time
+// }
+
+// type Test struct {
+// Inner *Inner
+// CreatedAt *time.Time `validate:"eqcsfield=Inner.CreatedAt"`
+// }
+
+// now := time.Now().UTC()
+
+// inner := &Inner{
+// CreatedAt: &now,
+// }
+
+// test := &Test{
+// Inner: inner,
+// CreatedAt: &now,
+// }
+
+// errs := validate.Struct(test)
+// Equal(t, errs, nil)
+
+// newTime := time.Now().UTC()
+// test.CreatedAt = &newTime
+
+// errs = validate.Struct(test)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "eqcsfield")
+
+// var j uint64
+// var k float64
+// s := "abcd"
+// i := 1
+// j = 1
+// k = 1.543
+// arr := []string{"test"}
+
+// var j2 uint64
+// var k2 float64
+// s2 := "abcd"
+// i2 := 1
+// j2 = 1
+// k2 = 1.543
+// arr2 := []string{"test"}
+// arr3 := []string{"test", "test2"}
+// now2 := now
+
+// errs = validate.FieldWithValue(s, s2, "eqcsfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(i2, i, "eqcsfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(j2, j, "eqcsfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(k2, k, "eqcsfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(arr2, arr, "eqcsfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(now2, now, "eqcsfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(arr3, arr, "eqcsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "eqcsfield")
+
+// type SInner struct {
+// Name string
+// }
+
+// type TStruct struct {
+// Inner *SInner
+// CreatedAt *time.Time `validate:"eqcsfield=Inner"`
+// }
+
+// sinner := &SInner{
+// Name: "NAME",
+// }
+
+// test2 := &TStruct{
+// Inner: sinner,
+// CreatedAt: &now,
+// }
+
+// errs = validate.Struct(test2)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqcsfield")
+
+// test2.Inner = nil
+// errs = validate.Struct(test2)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqcsfield")
+
+// errs = validate.FieldWithValue(nil, 1, "eqcsfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "eqcsfield")
+// }
+
+// func TestCrossNamespaceFieldValidation(t *testing.T) {
+
+// type SliceStruct struct {
+// Name string
+// }
+
+// type MapStruct struct {
+// Name string
+// }
+
+// type Inner struct {
+// CreatedAt *time.Time
+// Slice []string
+// SliceStructs []*SliceStruct
+// SliceSlice [][]string
+// SliceSliceStruct [][]*SliceStruct
+// SliceMap []map[string]string
+// Map map[string]string
+// MapMap map[string]map[string]string
+// MapStructs map[string]*SliceStruct
+// MapMapStruct map[string]map[string]*SliceStruct
+// MapSlice map[string][]string
+// MapInt map[int]string
+// MapInt8 map[int8]string
+// MapInt16 map[int16]string
+// MapInt32 map[int32]string
+// MapInt64 map[int64]string
+// MapUint map[uint]string
+// MapUint8 map[uint8]string
+// MapUint16 map[uint16]string
+// MapUint32 map[uint32]string
+// MapUint64 map[uint64]string
+// MapFloat32 map[float32]string
+// MapFloat64 map[float64]string
+// MapBool map[bool]string
+// }
+
+// type Test struct {
+// Inner *Inner
+// CreatedAt *time.Time
+// }
+
+// now := time.Now()
+
+// inner := &Inner{
+// CreatedAt: &now,
+// Slice: []string{"val1", "val2", "val3"},
+// SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}},
+// SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}},
+// SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}},
+// SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}},
+// Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"},
+// MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}},
+// MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}},
+// MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}},
+// MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}},
+// MapInt: map[int]string{1: "val1", 2: "val2", 3: "val3"},
+// MapInt8: map[int8]string{1: "val1", 2: "val2", 3: "val3"},
+// MapInt16: map[int16]string{1: "val1", 2: "val2", 3: "val3"},
+// MapInt32: map[int32]string{1: "val1", 2: "val2", 3: "val3"},
+// MapInt64: map[int64]string{1: "val1", 2: "val2", 3: "val3"},
+// MapUint: map[uint]string{1: "val1", 2: "val2", 3: "val3"},
+// MapUint8: map[uint8]string{1: "val1", 2: "val2", 3: "val3"},
+// MapUint16: map[uint16]string{1: "val1", 2: "val2", 3: "val3"},
+// MapUint32: map[uint32]string{1: "val1", 2: "val2", 3: "val3"},
+// MapUint64: map[uint64]string{1: "val1", 2: "val2", 3: "val3"},
+// MapFloat32: map[float32]string{1.01: "val1", 2.02: "val2", 3.03: "val3"},
+// MapFloat64: map[float64]string{1.01: "val1", 2.02: "val2", 3.03: "val3"},
+// MapBool: map[bool]string{true: "val1", false: "val2"},
+// }
+
+// test := &Test{
+// Inner: inner,
+// CreatedAt: &now,
+// }
+
+// val := reflect.ValueOf(test)
+
+// current, kind, ok := validate.GetStructFieldOK(val, "Inner.CreatedAt")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.Struct)
+// tm, ok := current.Interface().(time.Time)
+// Equal(t, ok, true)
+// Equal(t, tm, now)
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.Slice[1]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.CrazyNonExistantField")
+// Equal(t, ok, false)
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.Slice[101]")
+// Equal(t, ok, false)
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.Map[key3]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val3")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapMap[key2][key2-1]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapStructs[key2].Name")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "name2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapMapStruct[key3][key3-1].Name")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "name3")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceSlice[2][0]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "7")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceSliceStruct[2][1].Name")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "name8")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceMap[1][key5]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val5")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapSlice[key3][2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "9")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt[2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt8[2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt16[2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt32[2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt64[2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint[2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint8[2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint16[2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint32[2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint64[2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapFloat32[3.03]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val3")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapFloat64[2.02]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val2")
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapBool[true]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.String)
+// Equal(t, current.String(), "val1")
+
+// inner = &Inner{
+// CreatedAt: &now,
+// Slice: []string{"val1", "val2", "val3"},
+// SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, nil},
+// SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}},
+// SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}},
+// SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}},
+// Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"},
+// MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}},
+// MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}},
+// MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}},
+// MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}},
+// }
+
+// test = &Test{
+// Inner: inner,
+// CreatedAt: nil,
+// }
+
+// val = reflect.ValueOf(test)
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceStructs[2]")
+// Equal(t, ok, true)
+// Equal(t, kind, reflect.Ptr)
+// Equal(t, current.String(), "<*validator.SliceStruct Value>")
+// Equal(t, current.IsNil(), true)
+
+// current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceStructs[2].Name")
+// Equal(t, ok, false)
+// Equal(t, kind, reflect.Ptr)
+// Equal(t, current.String(), "<*validator.SliceStruct Value>")
+// Equal(t, current.IsNil(), true)
+
+// PanicMatches(t, func() { validate.GetStructFieldOK(reflect.ValueOf(1), "crazyinput") }, "Invalid field namespace")
+// }
+
+// func TestExistsValidation(t *testing.T) {
+
+// jsonText := "{ \"truthiness2\": true }"
+
+// type Thing struct {
+// Truthiness *bool `json:"truthiness" validate:"exists,required"`
+// }
+
+// var ting Thing
+
+// err := json.Unmarshal([]byte(jsonText), &ting)
+// Equal(t, err, nil)
+// NotEqual(t, ting, nil)
+// Equal(t, ting.Truthiness, nil)
+
+// errs := validate.Struct(ting)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Thing.Truthiness", "Truthiness", "exists")
- v1 := New(config)
- v1.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
+// jsonText = "{ \"truthiness\": true }"
- tst := &TestStruct{
- String: "good value",
- }
+// err = json.Unmarshal([]byte(jsonText), &ting)
+// Equal(t, err, nil)
+// NotEqual(t, ting, nil)
+// Equal(t, ting.Truthiness, true)
- errs := v1.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
+// errs = validate.Struct(ting)
+// Equal(t, errs, nil)
+// }
- v2 := New(config)
- v2.RegisterStructValidation(StructValidationBadTestStructFieldName, TestStruct{})
+// func TestSQLValue2Validation(t *testing.T) {
- PanicMatches(t, func() { v2.Struct(tst) }, fieldNameRequired)
+// config := &Config{
+// TagName: "validate",
+// }
- v3 := New(config)
- v3.RegisterStructValidation(StructValidationBadTestStructTag, TestStruct{})
+// validate := New(config)
+// validate.RegisterCustomTypeFunc(ValidateValuerType, valuer{}, (*driver.Valuer)(nil), sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
+// validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
+// validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1)
- PanicMatches(t, func() { v3.Struct(tst) }, tagRequired)
+// val := valuer{
+// Name: "",
+// }
- v4 := New(config)
- v4.RegisterStructValidation(StructValidationNoTestStructCustomName, TestStruct{})
+// errs := validate.Field(val, "required")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "required")
- errs = v4.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
+// val.Name = "Valid Name"
+// errs = validate.Field(val, "required")
+// Equal(t, errs, nil)
+
+// val.Name = "errorme"
+
+// PanicMatches(t, func() { validate.Field(val, "required") }, "SQL Driver Valuer error: some kind of error")
- v5 := New(config)
- v5.RegisterStructValidation(StructValidationTestStructInvalid, TestStruct{})
+// type myValuer valuer
- errs = v5.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
+// myVal := valuer{
+// Name: "",
+// }
- v6 := New(config)
- v6.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{})
+// errs = validate.Field(myVal, "required")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "required")
+
+// cust := MadeUpCustomType{
+// FirstName: "Joey",
+// LastName: "Bloggs",
+// }
+
+// c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
+
+// errs = validate.Struct(c)
+// Equal(t, errs, nil)
- errs = v6.Struct(tst)
- Equal(t, errs, nil)
-}
+// c.MadeUp.FirstName = ""
+// c.OverriddenInt = 1
+
+// errs = validate.Struct(c)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 2)
+// AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "MadeUp", "required")
+// AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "gt")
+// }
+
+// func TestSQLValueValidation(t *testing.T) {
+
+// validate := New(&Config{TagName: "validate"})
+// validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{})
+// validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
+// validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1)
+
+// val := valuer{
+// Name: "",
+// }
+
+// errs := validate.Field(val, "required")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "required")
+
+// val.Name = "Valid Name"
+// errs = validate.Field(val, "required")
+// Equal(t, errs, nil)
+
+// val.Name = "errorme"
+
+// PanicMatches(t, func() { errs = validate.Field(val, "required") }, "SQL Driver Valuer error: some kind of error")
+
+// type myValuer valuer
+
+// myVal := valuer{
+// Name: "",
+// }
+
+// errs = validate.Field(myVal, "required")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "required")
+
+// cust := MadeUpCustomType{
+// FirstName: "Joey",
+// LastName: "Bloggs",
+// }
+
+// c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
+
+// errs = validate.Struct(c)
+// Equal(t, errs, nil)
+
+// c.MadeUp.FirstName = ""
+// c.OverriddenInt = 1
+
+// errs = validate.Struct(c)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 2)
+// AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "MadeUp", "required")
+// AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "gt")
+// }
+
+// func TestMACValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"3D:F2:C9:A6:B3:4F", true},
+// {"3D-F2-C9-A6-B3:4F", false},
+// {"123", false},
+// {"", false},
+// {"abacaba", false},
+// {"00:25:96:FF:FE:12:34:56", true},
+// {"0025:96FF:FE12:3456", false},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "mac")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d mac failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d mac failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "mac" {
+// t.Fatalf("Index: %d mac failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestIPValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"10.0.0.1", true},
+// {"172.16.0.1", true},
+// {"192.168.0.1", true},
+// {"192.168.255.254", true},
+// {"192.168.255.256", false},
+// {"172.16.255.254", true},
+// {"172.16.256.255", false},
+// {"2001:cdba:0000:0000:0000:0000:3257:9652", true},
+// {"2001:cdba:0:0:0:0:3257:9652", true},
+// {"2001:cdba::3257:9652", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "ip")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ip failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ip failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "ip" {
+// t.Fatalf("Index: %d ip failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestIPv6Validation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"10.0.0.1", false},
+// {"172.16.0.1", false},
+// {"192.168.0.1", false},
+// {"192.168.255.254", false},
+// {"192.168.255.256", false},
+// {"172.16.255.254", false},
+// {"172.16.256.255", false},
+// {"2001:cdba:0000:0000:0000:0000:3257:9652", true},
+// {"2001:cdba:0:0:0:0:3257:9652", true},
+// {"2001:cdba::3257:9652", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "ipv6")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "ipv6" {
+// t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestIPv4Validation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"10.0.0.1", true},
+// {"172.16.0.1", true},
+// {"192.168.0.1", true},
+// {"192.168.255.254", true},
+// {"192.168.255.256", false},
+// {"172.16.255.254", true},
+// {"172.16.256.255", false},
+// {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
+// {"2001:cdba:0:0:0:0:3257:9652", false},
+// {"2001:cdba::3257:9652", false},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "ipv4")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "ipv4" {
+// t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestCIDRValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"10.0.0.0/0", true},
+// {"10.0.0.1/8", true},
+// {"172.16.0.1/16", true},
+// {"192.168.0.1/24", true},
+// {"192.168.255.254/24", true},
+// {"192.168.255.254/48", false},
+// {"192.168.255.256/24", false},
+// {"172.16.255.254/16", true},
+// {"172.16.256.255/16", false},
+// {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true},
+// {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
+// {"2001:cdba:0:0:0:0:3257:9652/32", true},
+// {"2001:cdba::3257:9652/16", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "cidr")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "cidr" {
+// t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestCIDRv6Validation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"10.0.0.0/0", false},
+// {"10.0.0.1/8", false},
+// {"172.16.0.1/16", false},
+// {"192.168.0.1/24", false},
+// {"192.168.255.254/24", false},
+// {"192.168.255.254/48", false},
+// {"192.168.255.256/24", false},
+// {"172.16.255.254/16", false},
+// {"172.16.256.255/16", false},
+// {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true},
+// {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
+// {"2001:cdba:0:0:0:0:3257:9652/32", true},
+// {"2001:cdba::3257:9652/16", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "cidrv6")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "cidrv6" {
+// t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestCIDRv4Validation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"10.0.0.0/0", true},
+// {"10.0.0.1/8", true},
+// {"172.16.0.1/16", true},
+// {"192.168.0.1/24", true},
+// {"192.168.255.254/24", true},
+// {"192.168.255.254/48", false},
+// {"192.168.255.256/24", false},
+// {"172.16.255.254/16", true},
+// {"172.16.256.255/16", false},
+// {"2001:cdba:0000:0000:0000:0000:3257:9652/64", false},
+// {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
+// {"2001:cdba:0:0:0:0:3257:9652/32", false},
+// {"2001:cdba::3257:9652/16", false},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "cidrv4")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "cidrv4" {
+// t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestTCPAddrValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {":80", false},
+// {"127.0.0.1:80", true},
+// {"[::1]:80", true},
+// {"256.0.0.0:1", false},
+// {"[::1]", false},
+// }
+
+// for i, test := range tests {
+// errs := validate.Field(test.param, "tcp_addr")
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "tcp_addr" {
+// t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestTCP6AddrValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {":80", false},
+// {"127.0.0.1:80", false},
+// {"[::1]:80", true},
+// {"256.0.0.0:1", false},
+// {"[::1]", false},
+// }
+
+// for i, test := range tests {
+// errs := validate.Field(test.param, "tcp6_addr")
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "tcp6_addr" {
+// t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestTCP4AddrValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {":80", false},
+// {"127.0.0.1:80", true},
+// {"[::1]:80", false}, // https://github.com/golang/go/issues/14037
+// {"256.0.0.0:1", false},
+// {"[::1]", false},
+// }
+
+// for i, test := range tests {
+// errs := validate.Field(test.param, "tcp4_addr")
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Log(test.param, IsEqual(errs, nil))
+// t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "tcp4_addr" {
+// t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestUDPAddrValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {":80", false},
+// {"127.0.0.1:80", true},
+// {"[::1]:80", true},
+// {"256.0.0.0:1", false},
+// {"[::1]", false},
+// }
+
+// for i, test := range tests {
+// errs := validate.Field(test.param, "udp_addr")
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "udp_addr" {
+// t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestUDP6AddrValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {":80", false},
+// {"127.0.0.1:80", false},
+// {"[::1]:80", true},
+// {"256.0.0.0:1", false},
+// {"[::1]", false},
+// }
+
+// for i, test := range tests {
+// errs := validate.Field(test.param, "udp6_addr")
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "udp6_addr" {
+// t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestUDP4AddrValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {":80", false},
+// {"127.0.0.1:80", true},
+// {"[::1]:80", false}, // https://github.com/golang/go/issues/14037
+// {"256.0.0.0:1", false},
+// {"[::1]", false},
+// }
+
+// for i, test := range tests {
+// errs := validate.Field(test.param, "udp4_addr")
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Log(test.param, IsEqual(errs, nil))
+// t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "udp4_addr" {
+// t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestIPAddrValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"127.0.0.1", true},
+// {"127.0.0.1:80", false},
+// {"::1", true},
+// {"256.0.0.0", false},
+// {"localhost", false},
+// }
+
+// for i, test := range tests {
+// errs := validate.Field(test.param, "ip_addr")
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "ip_addr" {
+// t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestIP6AddrValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"127.0.0.1", false}, // https://github.com/golang/go/issues/14037
+// {"127.0.0.1:80", false},
+// {"::1", true},
+// {"0:0:0:0:0:0:0:1", true},
+// {"256.0.0.0", false},
+// }
+
+// for i, test := range tests {
+// errs := validate.Field(test.param, "ip6_addr")
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "ip6_addr" {
+// t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestIP4AddrValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"127.0.0.1", true},
+// {"127.0.0.1:80", false},
+// {"::1", false}, // https://github.com/golang/go/issues/14037
+// {"256.0.0.0", false},
+// {"localhost", false},
+// }
+
+// for i, test := range tests {
+// errs := validate.Field(test.param, "ip4_addr")
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Log(test.param, IsEqual(errs, nil))
+// t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "ip4_addr" {
+// t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestUnixAddrValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", true},
+// {"v.sock", true},
+// }
+
+// for i, test := range tests {
+// errs := validate.Field(test.param, "unix_addr")
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Log(test.param, IsEqual(errs, nil))
+// t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "unix_addr" {
+// t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// 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.FieldWithValue(nil, iface, "")
+// Equal(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 TestDatePtrValidationIssueValidation(t *testing.T) {
+
+// type Test struct {
+// LastViewed *time.Time
+// Reminder *time.Time
+// }
+
+// test := &Test{}
+
+// errs := validate.Struct(test)
+// Equal(t, errs, nil)
+// }
+
+// func TestCommaAndPipeObfuscationValidation(t *testing.T) {
+// s := "My Name Is, |joeybloggs|"
-func TestAliasTags(t *testing.T) {
+// errs := validate.Field(s, "excludesall=0x2C")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "excludesall")
- validate.RegisterAliasValidation("iscolor", "hexcolor|rgb|rgba|hsl|hsla")
+// errs = validate.Field(s, "excludesall=0x7C")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "excludesall")
+// }
- s := "rgb(255,255,255)"
- errs := validate.Field(s, "iscolor")
- Equal(t, errs, nil)
+// func TestBadKeyValidation(t *testing.T) {
+// type Test struct {
+// Name string `validate:"required, "`
+// }
- s = ""
- errs = validate.Field(s, "omitempty,iscolor")
- Equal(t, errs, nil)
+// tst := &Test{
+// Name: "test",
+// }
- s = "rgb(255,255,0)"
- errs = validate.Field(s, "iscolor,len=5")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "len")
+// PanicMatches(t, func() { validate.Struct(tst) }, "Undefined validation function on field Name")
- type Test struct {
- Color string `validate:"iscolor"`
- }
+// type Test2 struct {
+// Name string `validate:"required,,len=2"`
+// }
- tst := &Test{
- Color: "#000",
- }
+// tst2 := &Test2{
+// Name: "test",
+// }
- errs = validate.Struct(tst)
- Equal(t, errs, nil)
+// PanicMatches(t, func() { validate.Struct(tst2) }, "Invalid validation tag on field Name")
+// }
- tst.Color = "cfvre"
- errs = validate.Struct(tst)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Color", "Color", "iscolor")
- Equal(t, errs.(ValidationErrors)["Test.Color"].ActualTag, "hexcolor|rgb|rgba|hsl|hsla")
+// func TestInterfaceErrValidation(t *testing.T) {
- validate.RegisterAliasValidation("req", "required,dive,iscolor")
- arr := []string{"val1", "#fff", "#000"}
+// var v1 interface{}
+// var v2 interface{}
- errs = validate.Field(arr, "req")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "[0]", "[0]", "iscolor")
+// v2 = 1
+// v1 = v2
- PanicMatches(t, func() { validate.RegisterAliasValidation("exists", "gt=5,lt=10") }, "Alias 'exists' either contains restricted characters or is the same as a restricted tag needed for normal operation")
-}
+// errs := validate.Field(v1, "len=1")
+// Equal(t, errs, nil)
-func TestNilValidator(t *testing.T) {
+// errs = validate.Field(v2, "len=1")
+// Equal(t, errs, nil)
- type TestStruct struct {
- Test string `validate:"required"`
- }
+// type ExternalCMD struct {
+// Userid string `json:"userid"`
+// Action uint32 `json:"action"`
+// Data interface{} `json:"data,omitempty" validate:"required"`
+// }
- ts := TestStruct{}
+// s := &ExternalCMD{
+// Userid: "123456",
+// Action: 10000,
+// // Data: 1,
+// }
- var val *Validate
+// errs = validate.Struct(s)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "ExternalCMD.Data", "Data", "required")
- fn := func(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
+// type ExternalCMD2 struct {
+// Userid string `json:"userid"`
+// Action uint32 `json:"action"`
+// Data interface{} `json:"data,omitempty" validate:"len=1"`
+// }
+
+// s2 := &ExternalCMD2{
+// Userid: "123456",
+// Action: 10000,
+// // Data: 1,
+// }
+
+// errs = validate.Struct(s2)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "ExternalCMD2.Data", "Data", "len")
+
+// s3 := &ExternalCMD2{
+// Userid: "123456",
+// Action: 10000,
+// Data: 2,
+// }
+
+// errs = validate.Struct(s3)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "ExternalCMD2.Data", "Data", "len")
+
+// type Inner struct {
+// Name string `validate:"required"`
+// }
+
+// inner := &Inner{
+// Name: "",
+// }
+
+// s4 := &ExternalCMD{
+// Userid: "123456",
+// Action: 10000,
+// Data: inner,
+// }
+
+// errs = validate.Struct(s4)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "ExternalCMD.Data.Name", "Name", "required")
+
+// type TestMapStructPtr struct {
+// Errs map[int]interface{} `validate:"gt=0,dive,len=2"`
+// }
+
+// mip := map[int]interface{}{0: &Inner{"ok"}, 3: nil, 4: &Inner{"ok"}}
+
+// msp := &TestMapStructPtr{
+// Errs: mip,
+// }
+
+// errs = validate.Struct(msp)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "TestMapStructPtr.Errs[3]", "Errs[3]", "len")
+
+// type TestMultiDimensionalStructs struct {
+// Errs [][]interface{} `validate:"gt=0,dive,dive"`
+// }
+
+// var errStructArray [][]interface{}
+
+// errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
+// errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
+
+// tms := &TestMultiDimensionalStructs{
+// Errs: errStructArray,
+// }
+
+// errs = validate.Struct(tms)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 4)
+// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "required")
+
+// type TestMultiDimensionalStructsPtr2 struct {
+// Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
+// }
+
+// var errStructPtr2Array [][]*Inner
+
+// errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
+// errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
+// errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
+
+// tmsp2 := &TestMultiDimensionalStructsPtr2{
+// Errs: errStructPtr2Array,
+// }
+
+// errs = validate.Struct(tmsp2)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 6)
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "required")
+
+// m := map[int]interface{}{0: "ok", 3: "", 4: "ok"}
+
+// errs = validate.Field(m, "len=3,dive,len=2")
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "[3]", "[3]", "len")
- return current.String() == field.String()
- }
+// errs = validate.Field(m, "len=2,dive,required")
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "", "", "len")
- PanicMatches(t, func() { val.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) }, validatorNotInitialized)
- PanicMatches(t, func() { val.RegisterValidation("something", fn) }, validatorNotInitialized)
- PanicMatches(t, func() { val.Field(ts.Test, "required") }, validatorNotInitialized)
- PanicMatches(t, func() { val.FieldWithValue("test", ts.Test, "required") }, validatorNotInitialized)
- PanicMatches(t, func() { val.Struct(ts) }, validatorNotInitialized)
- PanicMatches(t, func() { val.StructExcept(ts, "Test") }, validatorNotInitialized)
- PanicMatches(t, func() { val.StructPartial(ts, "Test") }, validatorNotInitialized)
-}
+// arr := []interface{}{"ok", "", "ok"}
-func TestStructPartial(t *testing.T) {
+// errs = validate.Field(arr, "len=3,dive,len=2")
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "[1]", "[1]", "len")
- p1 := []string{
- "NoTag",
- "Required",
- }
+// errs = validate.Field(arr, "len=2,dive,required")
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "", "", "len")
- p2 := []string{
- "SubSlice[0].Test",
- "Sub",
- "SubIgnore",
- "Anonymous.A",
- }
+// type MyStruct struct {
+// A, B string
+// C interface{}
+// }
- p3 := []string{
- "SubTest.Test",
- }
+// var a MyStruct
- p4 := []string{
- "A",
- }
+// a.A = "value"
+// a.C = "nu"
- tPartial := &TestPartial{
- NoTag: "NoTag",
- Required: "Required",
-
- SubSlice: []*SubTest{
- {
-
- Test: "Required",
- },
- {
-
- Test: "Required",
- },
- },
-
- Sub: &SubTest{
- Test: "1",
- },
- SubIgnore: &SubTest{
- Test: "",
- },
- Anonymous: struct {
- A string `validate:"required"`
- ASubSlice []*SubTest `validate:"required,dive"`
- SubAnonStruct []struct {
- Test string `validate:"required"`
- OtherTest string `validate:"required"`
- } `validate:"required,dive"`
- }{
- A: "1",
- ASubSlice: []*SubTest{
- {
- Test: "Required",
- },
- {
- Test: "Required",
- },
- },
-
- SubAnonStruct: []struct {
- Test string `validate:"required"`
- OtherTest string `validate:"required"`
- }{
- {"Required", "RequiredOther"},
- {"Required", "RequiredOther"},
- },
- },
- }
+// errs = validate.Struct(a)
+// Equal(t, errs, nil)
+// }
- // the following should all return no errors as everything is valid in
- // the default state
- errs := validate.StructPartial(tPartial, p1...)
- Equal(t, errs, nil)
+// func TestMapDiveValidation(t *testing.T) {
- errs = validate.StructPartial(tPartial, p2...)
- Equal(t, errs, nil)
+// n := map[int]interface{}{0: nil}
+// errs := validate.Field(n, "omitempty,required")
+// Equal(t, errs, nil)
- // this isn't really a robust test, but is ment to illustrate the ANON CASE below
- errs = validate.StructPartial(tPartial.SubSlice[0], p3...)
- Equal(t, errs, nil)
+// m := map[int]string{0: "ok", 3: "", 4: "ok"}
- errs = validate.StructExcept(tPartial, p1...)
- Equal(t, errs, nil)
+// errs = validate.Field(m, "len=3,dive,required")
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "[3]", "[3]", "required")
- errs = validate.StructExcept(tPartial, p2...)
- Equal(t, errs, nil)
+// errs = validate.Field(m, "len=2,dive,required")
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "", "", "len")
- // mod tParial for required feild and re-test making sure invalid fields are NOT required:
- tPartial.Required = ""
+// type Inner struct {
+// Name string `validate:"required"`
+// }
- errs = validate.StructExcept(tPartial, p1...)
- Equal(t, errs, nil)
+// type TestMapStruct struct {
+// Errs map[int]Inner `validate:"gt=0,dive"`
+// }
- errs = validate.StructPartial(tPartial, p2...)
- Equal(t, errs, nil)
+// mi := map[int]Inner{0: {"ok"}, 3: {""}, 4: {"ok"}}
- // inversion and retesting Partial to generate failures:
- errs = validate.StructPartial(tPartial, p1...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Required", "Required", "required")
+// ms := &TestMapStruct{
+// Errs: mi,
+// }
- errs = validate.StructExcept(tPartial, p2...)
- AssertError(t, errs, "TestPartial.Required", "Required", "required")
+// errs = validate.Struct(ms)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "TestMapStruct.Errs[3].Name", "Name", "required")
- // reset Required field, and set nested struct
- tPartial.Required = "Required"
- tPartial.Anonymous.A = ""
+// // for full test coverage
+// s := fmt.Sprint(errs.Error())
+// NotEqual(t, s, "")
- // will pass as unset feilds is not going to be tested
- errs = validate.StructPartial(tPartial, p1...)
- Equal(t, errs, nil)
+// type TestMapTimeStruct struct {
+// Errs map[int]*time.Time `validate:"gt=0,dive,required"`
+// }
- errs = validate.StructExcept(tPartial, p2...)
- Equal(t, errs, nil)
+// t1 := time.Now().UTC()
- // ANON CASE the response here is strange, it clearly does what it is being told to
- errs = validate.StructExcept(tPartial.Anonymous, p4...)
- Equal(t, errs, nil)
+// mta := map[int]*time.Time{0: &t1, 3: nil, 4: nil}
- // will fail as unset feild is tested
- errs = validate.StructPartial(tPartial, p2...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Anonymous.A", "A", "required")
+// mt := &TestMapTimeStruct{
+// Errs: mta,
+// }
- errs = validate.StructExcept(tPartial, p1...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Anonymous.A", "A", "required")
+// errs = validate.Struct(mt)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 2)
+// AssertError(t, errs, "TestMapTimeStruct.Errs[3]", "Errs[3]", "required")
+// AssertError(t, errs, "TestMapTimeStruct.Errs[4]", "Errs[4]", "required")
- // reset nested struct and unset struct in slice
- tPartial.Anonymous.A = "Required"
- tPartial.SubSlice[0].Test = ""
+// type TestMapStructPtr struct {
+// Errs map[int]*Inner `validate:"gt=0,dive,required"`
+// }
- // these will pass as unset item is NOT tested
- errs = validate.StructPartial(tPartial, p1...)
- Equal(t, errs, nil)
+// mip := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
- errs = validate.StructExcept(tPartial, p2...)
- Equal(t, errs, nil)
+// msp := &TestMapStructPtr{
+// Errs: mip,
+// }
- // these will fail as unset item IS tested
- errs = validate.StructExcept(tPartial, p1...)
- AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
- Equal(t, len(errs.(ValidationErrors)), 1)
+// errs = validate.Struct(msp)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "TestMapStructPtr.Errs[3]", "Errs[3]", "required")
- errs = validate.StructPartial(tPartial, p2...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
- Equal(t, len(errs.(ValidationErrors)), 1)
+// type TestMapStructPtr2 struct {
+// Errs map[int]*Inner `validate:"gt=0,dive,omitempty,required"`
+// }
- // Unset second slice member concurrently to test dive behavior:
- tPartial.SubSlice[1].Test = ""
+// mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
- errs = validate.StructPartial(tPartial, p1...)
- Equal(t, errs, nil)
+// msp2 := &TestMapStructPtr2{
+// Errs: mip2,
+// }
- // NOTE: When specifying nested items, it is still the users responsibility
- // to specify the dive tag, the library does not override this.
- errs = validate.StructExcept(tPartial, p2...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
+// errs = validate.Struct(msp2)
+// Equal(t, errs, nil)
+// }
- errs = validate.StructExcept(tPartial, p1...)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
- AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
+// func TestArrayDiveValidation(t *testing.T) {
- errs = validate.StructPartial(tPartial, p2...)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
+// arr := []string{"ok", "", "ok"}
- // reset struct in slice, and unset struct in slice in unset posistion
- tPartial.SubSlice[0].Test = "Required"
+// errs := validate.Field(arr, "len=3,dive,required")
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "[1]", "[1]", "required")
- // these will pass as the unset item is NOT tested
- errs = validate.StructPartial(tPartial, p1...)
- Equal(t, errs, nil)
+// errs = validate.Field(arr, "len=2,dive,required")
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "", "", "len")
- errs = validate.StructPartial(tPartial, p2...)
- Equal(t, errs, nil)
+// type BadDive struct {
+// Name string `validate:"dive"`
+// }
- // testing for missing item by exception, yes it dives and fails
- errs = validate.StructExcept(tPartial, p1...)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
+// bd := &BadDive{
+// Name: "TEST",
+// }
- errs = validate.StructExcept(tPartial, p2...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
+// PanicMatches(t, func() { validate.Struct(bd) }, "dive error! can't dive on a non slice or map")
- tPartial.SubSlice[1].Test = "Required"
+// type Test struct {
+// Errs []string `validate:"gt=0,dive,required"`
+// }
- tPartial.Anonymous.SubAnonStruct[0].Test = ""
- // these will pass as the unset item is NOT tested
- errs = validate.StructPartial(tPartial, p1...)
- Equal(t, errs, nil)
+// test := &Test{
+// Errs: []string{"ok", "", "ok"},
+// }
- errs = validate.StructPartial(tPartial, p2...)
- Equal(t, errs, nil)
+// errs = validate.Struct(test)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "Test.Errs[1]", "Errs[1]", "required")
- errs = validate.StructExcept(tPartial, p1...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "required")
+// test = &Test{
+// Errs: []string{"ok", "ok", ""},
+// }
+
+// errs = validate.Struct(test)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 1)
+// AssertError(t, errs, "Test.Errs[2]", "Errs[2]", "required")
+
+// type TestMultiDimensional struct {
+// Errs [][]string `validate:"gt=0,dive,dive,required"`
+// }
- errs = validate.StructExcept(tPartial, p2...)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "required")
+// var errArray [][]string
-}
+// errArray = append(errArray, []string{"ok", "", ""})
+// errArray = append(errArray, []string{"ok", "", ""})
-func TestCrossStructLteFieldValidation(t *testing.T) {
+// tm := &TestMultiDimensional{
+// Errs: errArray,
+// }
- type Inner struct {
- CreatedAt *time.Time
- String string
- Int int
- Uint uint
- Float float64
- Array []string
- }
+// errs = validate.Struct(tm)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 4)
+// AssertError(t, errs, "TestMultiDimensional.Errs[0][1]", "Errs[0][1]", "required")
+// AssertError(t, errs, "TestMultiDimensional.Errs[0][2]", "Errs[0][2]", "required")
+// AssertError(t, errs, "TestMultiDimensional.Errs[1][1]", "Errs[1][1]", "required")
+// AssertError(t, errs, "TestMultiDimensional.Errs[1][2]", "Errs[1][2]", "required")
+
+// type Inner struct {
+// Name string `validate:"required"`
+// }
+
+// type TestMultiDimensionalStructs struct {
+// Errs [][]Inner `validate:"gt=0,dive,dive"`
+// }
+
+// var errStructArray [][]Inner
+
+// errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
+// errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
+
+// tms := &TestMultiDimensionalStructs{
+// Errs: errStructArray,
+// }
+
+// errs = validate.Struct(tms)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 4)
+// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "required")
+
+// type TestMultiDimensionalStructsPtr struct {
+// Errs [][]*Inner `validate:"gt=0,dive,dive"`
+// }
+
+// var errStructPtrArray [][]*Inner
+
+// errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
+// errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
+// errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, nil})
+
+// tmsp := &TestMultiDimensionalStructsPtr{
+// Errs: errStructPtrArray,
+// }
+
+// errs = validate.Struct(tmsp)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 5)
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[2][1].Name", "Name", "required")
+
+// // for full test coverage
+// s := fmt.Sprint(errs.Error())
+// NotEqual(t, s, "")
+
+// type TestMultiDimensionalStructsPtr2 struct {
+// Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
+// }
+
+// var errStructPtr2Array [][]*Inner
+
+// errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
+// errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
+// errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
+
+// tmsp2 := &TestMultiDimensionalStructsPtr2{
+// Errs: errStructPtr2Array,
+// }
+
+// errs = validate.Struct(tmsp2)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 6)
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "required")
+
+// type TestMultiDimensionalStructsPtr3 struct {
+// Errs [][]*Inner `validate:"gt=0,dive,dive,omitempty"`
+// }
+
+// var errStructPtr3Array [][]*Inner
+
+// errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
+// errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
+// errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, nil})
+
+// tmsp3 := &TestMultiDimensionalStructsPtr3{
+// Errs: errStructPtr3Array,
+// }
+
+// errs = validate.Struct(tmsp3)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 5)
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "Name", "required")
+// AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[2][1].Name", "Name", "required")
+
+// type TestMultiDimensionalTimeTime struct {
+// Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
+// }
+
+// var errTimePtr3Array [][]*time.Time
+
+// t1 := time.Now().UTC()
+// t2 := time.Now().UTC()
+// t3 := time.Now().UTC().Add(time.Hour * 24)
+
+// errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, &t3})
+// errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, nil})
+// errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, nil, nil})
+
+// tmtp3 := &TestMultiDimensionalTimeTime{
+// Errs: errTimePtr3Array,
+// }
+
+// errs = validate.Struct(tmtp3)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 3)
+// AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[1][2]", "Errs[1][2]", "required")
+// AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][1]", "Errs[2][1]", "required")
+// AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][2]", "Errs[2][2]", "required")
+
+// type TestMultiDimensionalTimeTime2 struct {
+// Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
+// }
+
+// var errTimeArray [][]*time.Time
+
+// t1 = time.Now().UTC()
+// t2 = time.Now().UTC()
+// t3 = time.Now().UTC().Add(time.Hour * 24)
+
+// errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, &t3})
+// errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, nil})
+// errTimeArray = append(errTimeArray, []*time.Time{&t1, nil, nil})
+
+// tmtp := &TestMultiDimensionalTimeTime2{
+// Errs: errTimeArray,
+// }
+
+// errs = validate.Struct(tmtp)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 3)
+// AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[1][2]", "Errs[1][2]", "required")
+// AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][1]", "Errs[2][1]", "required")
+// AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][2]", "Errs[2][2]", "required")
+// }
+
+// func TestNilStructPointerValidation(t *testing.T) {
+// type Inner struct {
+// Data string
+// }
+
+// type Outer struct {
+// Inner *Inner `validate:"omitempty"`
+// }
+
+// inner := &Inner{
+// Data: "test",
+// }
+
+// outer := &Outer{
+// Inner: inner,
+// }
+
+// errs := validate.Struct(outer)
+// Equal(t, errs, nil)
+
+// outer = &Outer{
+// Inner: nil,
+// }
+
+// errs = validate.Struct(outer)
+// Equal(t, errs, nil)
+
+// type Inner2 struct {
+// Data string
+// }
+
+// type Outer2 struct {
+// Inner2 *Inner2 `validate:"required"`
+// }
+
+// inner2 := &Inner2{
+// Data: "test",
+// }
+
+// outer2 := &Outer2{
+// Inner2: inner2,
+// }
+
+// errs = validate.Struct(outer2)
+// Equal(t, errs, nil)
+
+// outer2 = &Outer2{
+// Inner2: nil,
+// }
+
+// errs = validate.Struct(outer2)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Outer2.Inner2", "Inner2", "required")
+
+// type Inner3 struct {
+// Data string
+// }
+
+// type Outer3 struct {
+// Inner3 *Inner3
+// }
+
+// inner3 := &Inner3{
+// Data: "test",
+// }
+
+// outer3 := &Outer3{
+// Inner3: inner3,
+// }
+
+// errs = validate.Struct(outer3)
+// Equal(t, errs, nil)
+
+// type Inner4 struct {
+// Data string
+// }
+
+// type Outer4 struct {
+// Inner4 *Inner4 `validate:"-"`
+// }
+
+// inner4 := &Inner4{
+// Data: "test",
+// }
+
+// outer4 := &Outer4{
+// Inner4: inner4,
+// }
+
+// errs = validate.Struct(outer4)
+// Equal(t, errs, nil)
+// }
+
+// func TestSSNValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"00-90-8787", false},
+// {"66690-76", false},
+// {"191 60 2869", true},
+// {"191-60-2869", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "ssn")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "ssn" {
+// t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestLongitudeValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"-180.000", true},
+// {"180.1", false},
+// {"+73.234", true},
+// {"+382.3811", false},
+// {"23.11111111", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "longitude")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "longitude" {
+// t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestLatitudeValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"-90.000", true},
+// {"+90", true},
+// {"47.1231231", true},
+// {"+99.9", false},
+// {"108", false},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "latitude")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "latitude" {
+// t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestDataURIValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"data:image/png;base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true},
+// {"data:text/plain;base64,Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true},
+// {"image/gif;base64,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
+// {"data:image/gif;base64,MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" +
+// "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" +
+// "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" +
+// "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" +
+// "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" +
+// "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true},
+// {"data:image/png;base64,12345", false},
+// {"", false},
+// {"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "datauri")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "datauri" {
+// t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestMultibyteValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", true},
+// {"abc", false},
+// {"123", false},
+// {"<>@;.-=", false},
+// {"ひらがな・カタカナ、.漢字", true},
+// {"あいうえお foobar", true},
+// {"test@example.com", true},
+// {"test@example.com", true},
+// {"1234abcDExyz", true},
+// {"カタカナ", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "multibyte")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "multibyte" {
+// t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestPrintableASCIIValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", true},
+// {"foobar", false},
+// {"xyz098", false},
+// {"123456", false},
+// {"カタカナ", false},
+// {"foobar", true},
+// {"0987654321", true},
+// {"test@example.com", true},
+// {"1234abcDEF", true},
+// {"newline\n", false},
+// {"\x19test\x7F", false},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "printascii")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "printascii" {
+// t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestASCIIValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", true},
+// {"foobar", false},
+// {"xyz098", false},
+// {"123456", false},
+// {"カタカナ", false},
+// {"foobar", true},
+// {"0987654321", true},
+// {"test@example.com", true},
+// {"1234abcDEF", true},
+// {"", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "ascii")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "ascii" {
+// t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestUUID5Validation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+
+// {"", false},
+// {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
+// {"9c858901-8a57-4791-81fe-4c455b099bc9", false},
+// {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
+// {"987fbc97-4bed-5078-af07-9141ba07c9f3", true},
+// {"987fbc97-4bed-5078-9f07-9141ba07c9f3", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "uuid5")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "uuid5" {
+// t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestUUID4Validation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
+// {"a987fbc9-4bed-5078-af07-9141ba07c9f3", false},
+// {"934859", false},
+// {"57b73598-8764-4ad0-a76a-679bb6640eb1", true},
+// {"625e63f3-58f5-40b7-83a1-a72ad31acffb", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "uuid4")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "uuid4" {
+// t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestUUID3Validation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"412452646", false},
+// {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
+// {"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false},
+// {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "uuid3")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "uuid3" {
+// t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestUUIDValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
+// {"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false},
+// {"a987fbc94bed3078cf079141ba07c9f3", false},
+// {"934859", false},
+// {"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false},
+// {"aaaaaaaa-1111-1111-aaag-111111111111", false},
+// {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "uuid")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "uuid" {
+// t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestISBNValidation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"foo", false},
+// {"3836221195", true},
+// {"1-61729-085-8", true},
+// {"3 423 21412 0", true},
+// {"3 401 01319 X", true},
+// {"9784873113685", true},
+// {"978-4-87311-368-5", true},
+// {"978 3401013190", true},
+// {"978-3-8362-2119-1", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "isbn")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "isbn" {
+// t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestISBN13Validation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"foo", false},
+// {"3-8362-2119-5", false},
+// {"01234567890ab", false},
+// {"978 3 8362 2119 0", false},
+// {"9784873113685", true},
+// {"978-4-87311-368-5", true},
+// {"978 3401013190", true},
+// {"978-3-8362-2119-1", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "isbn13")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "isbn13" {
+// t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestISBN10Validation(t *testing.T) {
+// tests := []struct {
+// param string
+// expected bool
+// }{
+// {"", false},
+// {"foo", false},
+// {"3423214121", false},
+// {"978-3836221191", false},
+// {"3-423-21412-1", false},
+// {"3 423 21412 1", false},
+// {"3836221195", true},
+// {"1-61729-085-8", true},
+// {"3 423 21412 0", true},
+// {"3 401 01319 X", true},
+// }
+
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "isbn10")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "isbn10" {
+// t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+// }
+
+// func TestExcludesRuneValidation(t *testing.T) {
+
+// tests := []struct {
+// Value string `validate:"excludesrune=☻"`
+// Tag string
+// ExpectedNil bool
+// }{
+// {Value: "a☺b☻c☹d", Tag: "excludesrune=☻", ExpectedNil: false},
+// {Value: "abcd", Tag: "excludesrune=☻", ExpectedNil: true},
+// }
+
+// for i, s := range tests {
+// errs := validate.Field(s.Value, s.Tag)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+
+// errs = validate.Struct(s)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+// }
+// }
+
+// func TestExcludesAllValidation(t *testing.T) {
+
+// tests := []struct {
+// Value string `validate:"excludesall=@!{}[]"`
+// Tag string
+// ExpectedNil bool
+// }{
+// {Value: "abcd@!jfk", Tag: "excludesall=@!{}[]", ExpectedNil: false},
+// {Value: "abcdefg", Tag: "excludesall=@!{}[]", ExpectedNil: true},
+// }
+
+// for i, s := range tests {
+// errs := validate.Field(s.Value, s.Tag)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+
+// errs = validate.Struct(s)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+// }
+
+// username := "joeybloggs "
+
+// errs := validate.Field(username, "excludesall=@ ")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "excludesall")
+
+// excluded := ","
+
+// errs = validate.Field(excluded, "excludesall=!@#$%^&*()_+.0x2C?")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "excludesall")
+
+// excluded = "="
+
+// errs = validate.Field(excluded, "excludesall=!@#$%^&*()_+.0x2C=?")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "excludesall")
+// }
+
+// func TestExcludesValidation(t *testing.T) {
+
+// tests := []struct {
+// Value string `validate:"excludes=@"`
+// Tag string
+// ExpectedNil bool
+// }{
+// {Value: "abcd@!jfk", Tag: "excludes=@", ExpectedNil: false},
+// {Value: "abcdq!jfk", Tag: "excludes=@", ExpectedNil: true},
+// }
+
+// for i, s := range tests {
+// errs := validate.Field(s.Value, s.Tag)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+
+// errs = validate.Struct(s)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+// }
+// }
+
+// func TestContainsRuneValidation(t *testing.T) {
+
+// tests := []struct {
+// Value string `validate:"containsrune=☻"`
+// Tag string
+// ExpectedNil bool
+// }{
+// {Value: "a☺b☻c☹d", Tag: "containsrune=☻", ExpectedNil: true},
+// {Value: "abcd", Tag: "containsrune=☻", ExpectedNil: false},
+// }
+
+// for i, s := range tests {
+// errs := validate.Field(s.Value, s.Tag)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+
+// errs = validate.Struct(s)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+// }
+// }
+
+// func TestContainsAnyValidation(t *testing.T) {
+
+// tests := []struct {
+// Value string `validate:"containsany=@!{}[]"`
+// Tag string
+// ExpectedNil bool
+// }{
+// {Value: "abcd@!jfk", Tag: "containsany=@!{}[]", ExpectedNil: true},
+// {Value: "abcdefg", Tag: "containsany=@!{}[]", ExpectedNil: false},
+// }
+
+// for i, s := range tests {
+// errs := validate.Field(s.Value, s.Tag)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+
+// errs = validate.Struct(s)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+// }
+// }
+
+// func TestContainsValidation(t *testing.T) {
+
+// tests := []struct {
+// Value string `validate:"contains=@"`
+// Tag string
+// ExpectedNil bool
+// }{
+// {Value: "abcd@!jfk", Tag: "contains=@", ExpectedNil: true},
+// {Value: "abcdq!jfk", Tag: "contains=@", ExpectedNil: false},
+// }
+
+// for i, s := range tests {
+// errs := validate.Field(s.Value, s.Tag)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+
+// errs = validate.Struct(s)
+
+// if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+// t.Fatalf("Index: %d failed Error: %s", i, errs)
+// }
+// }
+// }
+
+// func TestIsNeFieldValidation(t *testing.T) {
+
+// var j uint64
+// var k float64
+// s := "abcd"
+// i := 1
+// j = 1
+// k = 1.543
+// arr := []string{"test"}
+// now := time.Now().UTC()
+
+// var j2 uint64
+// var k2 float64
+// s2 := "abcdef"
+// i2 := 3
+// j2 = 2
+// k2 = 1.5434456
+// arr2 := []string{"test", "test2"}
+// arr3 := []string{"test"}
+// now2 := now
+
+// errs := validate.FieldWithValue(s, s2, "nefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(i2, i, "nefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(j2, j, "nefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(k2, k, "nefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(arr2, arr, "nefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(now2, now, "nefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "nefield")
+
+// errs = validate.FieldWithValue(arr3, arr, "nefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "nefield")
+
+// type Test struct {
+// Start *time.Time `validate:"nefield=End"`
+// End *time.Time
+// }
+
+// sv := &Test{
+// Start: &now,
+// End: &now,
+// }
+
+// errs = validate.Struct(sv)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.Start", "Start", "nefield")
+
+// now3 := time.Now().UTC()
+
+// sv = &Test{
+// Start: &now,
+// End: &now3,
+// }
+
+// errs = validate.Struct(sv)
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(nil, 1, "nefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(sv, now, "nefield")
+// Equal(t, errs, nil)
+
+// type Test2 struct {
+// Start *time.Time `validate:"nefield=NonExistantField"`
+// End *time.Time
+// }
+
+// sv2 := &Test2{
+// Start: &now,
+// End: &now,
+// }
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"ltecsfield=Inner.CreatedAt"`
- String string `validate:"ltecsfield=Inner.String"`
- Int int `validate:"ltecsfield=Inner.Int"`
- Uint uint `validate:"ltecsfield=Inner.Uint"`
- Float float64 `validate:"ltecsfield=Inner.Float"`
- Array []string `validate:"ltecsfield=Inner.Array"`
- }
+// errs = validate.Struct(sv2)
+// Equal(t, errs, nil)
+// }
- now := time.Now().UTC()
- then := now.Add(time.Hour * 5)
+// func TestIsNeValidation(t *testing.T) {
+
+// var j uint64
+// var k float64
+// s := "abcdef"
+// i := 3
+// j = 2
+// k = 1.5434
+// arr := []string{"test"}
+// now := time.Now().UTC()
+
+// errs := validate.Field(s, "ne=abcd")
+// Equal(t, errs, nil)
+
+// errs = validate.Field(i, "ne=1")
+// Equal(t, errs, nil)
+
+// errs = validate.Field(j, "ne=1")
+// Equal(t, errs, nil)
+
+// errs = validate.Field(k, "ne=1.543")
+// Equal(t, errs, nil)
- inner := &Inner{
- CreatedAt: &then,
- String: "abcd",
- Int: 13,
- Uint: 13,
- Float: 1.13,
- Array: []string{"val1", "val2"},
- }
+// errs = validate.Field(arr, "ne=2")
+// Equal(t, errs, nil)
+
+// errs = validate.Field(arr, "ne=1")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ne")
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- String: "abc",
- Int: 12,
- Uint: 12,
- Float: 1.12,
- Array: []string{"val1"},
- }
+// PanicMatches(t, func() { validate.Field(now, "ne=now") }, "Bad field type time.Time")
+// }
- errs := validate.Struct(test)
- Equal(t, errs, nil)
+// func TestIsEqFieldValidation(t *testing.T) {
- test.CreatedAt = &then
- test.String = "abcd"
- test.Int = 13
- test.Uint = 13
- test.Float = 1.13
- test.Array = []string{"val1", "val2"}
+// var j uint64
+// var k float64
+// s := "abcd"
+// i := 1
+// j = 1
+// k = 1.543
+// arr := []string{"test"}
+// now := time.Now().UTC()
+
+// var j2 uint64
+// var k2 float64
+// s2 := "abcd"
+// i2 := 1
+// j2 = 1
+// k2 = 1.543
+// arr2 := []string{"test"}
+// arr3 := []string{"test", "test2"}
+// now2 := now
+
+// errs := validate.FieldWithValue(s, s2, "eqfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(i2, i, "eqfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(j2, j, "eqfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(k2, k, "eqfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(arr2, arr, "eqfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(now2, now, "eqfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(arr3, arr, "eqfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "eqfield")
- errs = validate.Struct(test)
- Equal(t, errs, nil)
+// type Test struct {
+// Start *time.Time `validate:"eqfield=End"`
+// End *time.Time
+// }
+
+// sv := &Test{
+// Start: &now,
+// End: &now,
+// }
- after := now.Add(time.Hour * 10)
+// errs = validate.Struct(sv)
+// Equal(t, errs, nil)
- test.CreatedAt = &after
- test.String = "abce"
- test.Int = 14
- test.Uint = 14
- test.Float = 1.14
- test.Array = []string{"val1", "val2", "val3"}
+// now3 := time.Now().UTC()
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "ltecsfield")
- AssertError(t, errs, "Test.String", "String", "ltecsfield")
- AssertError(t, errs, "Test.Int", "Int", "ltecsfield")
- AssertError(t, errs, "Test.Uint", "Uint", "ltecsfield")
- AssertError(t, errs, "Test.Float", "Float", "ltecsfield")
- AssertError(t, errs, "Test.Array", "Array", "ltecsfield")
-
- errs = validate.FieldWithValue(1, "", "ltecsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltecsfield")
+// sv = &Test{
+// Start: &now,
+// End: &now3,
+// }
- errs = validate.FieldWithValue(test, now, "ltecsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltecsfield")
-}
+// errs = validate.Struct(sv)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.Start", "Start", "eqfield")
-func TestCrossStructLtFieldValidation(t *testing.T) {
+// errs = validate.FieldWithValue(nil, 1, "eqfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "eqfield")
+
+// channel := make(chan string)
+// errs = validate.FieldWithValue(5, channel, "eqfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "eqfield")
- type Inner struct {
- CreatedAt *time.Time
- String string
- Int int
- Uint uint
- Float float64
- Array []string
- }
+// errs = validate.FieldWithValue(5, now, "eqfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "eqfield")
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"ltcsfield=Inner.CreatedAt"`
- String string `validate:"ltcsfield=Inner.String"`
- Int int `validate:"ltcsfield=Inner.Int"`
- Uint uint `validate:"ltcsfield=Inner.Uint"`
- Float float64 `validate:"ltcsfield=Inner.Float"`
- Array []string `validate:"ltcsfield=Inner.Array"`
- }
+// type Test2 struct {
+// Start *time.Time `validate:"eqfield=NonExistantField"`
+// End *time.Time
+// }
- now := time.Now().UTC()
- then := now.Add(time.Hour * 5)
+// sv2 := &Test2{
+// Start: &now,
+// End: &now,
+// }
- inner := &Inner{
- CreatedAt: &then,
- String: "abcd",
- Int: 13,
- Uint: 13,
- Float: 1.13,
- Array: []string{"val1", "val2"},
- }
+// errs = validate.Struct(sv2)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test2.Start", "Start", "eqfield")
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- String: "abc",
- Int: 12,
- Uint: 12,
- Float: 1.12,
- Array: []string{"val1"},
- }
+// type Inner struct {
+// Name string
+// }
- errs := validate.Struct(test)
- Equal(t, errs, nil)
+// type TStruct struct {
+// Inner *Inner
+// CreatedAt *time.Time `validate:"eqfield=Inner"`
+// }
+
+// inner := &Inner{
+// Name: "NAME",
+// }
- test.CreatedAt = &then
- test.String = "abcd"
- test.Int = 13
- test.Uint = 13
- test.Float = 1.13
- test.Array = []string{"val1", "val2"}
+// test := &TStruct{
+// Inner: inner,
+// CreatedAt: &now,
+// }
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "ltcsfield")
- AssertError(t, errs, "Test.String", "String", "ltcsfield")
- AssertError(t, errs, "Test.Int", "Int", "ltcsfield")
- AssertError(t, errs, "Test.Uint", "Uint", "ltcsfield")
- AssertError(t, errs, "Test.Float", "Float", "ltcsfield")
- AssertError(t, errs, "Test.Array", "Array", "ltcsfield")
-
- errs = validate.FieldWithValue(1, "", "ltcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltcsfield")
+// errs = validate.Struct(test)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqfield")
+// }
- errs = validate.FieldWithValue(test, now, "ltcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltcsfield")
-}
+// func TestIsEqValidation(t *testing.T) {
-func TestCrossStructGteFieldValidation(t *testing.T) {
+// var j uint64
+// var k float64
+// s := "abcd"
+// i := 1
+// j = 1
+// k = 1.543
+// arr := []string{"test"}
+// now := time.Now().UTC()
- type Inner struct {
- CreatedAt *time.Time
- String string
- Int int
- Uint uint
- Float float64
- Array []string
- }
+// errs := validate.Field(s, "eq=abcd")
+// Equal(t, errs, nil)
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"gtecsfield=Inner.CreatedAt"`
- String string `validate:"gtecsfield=Inner.String"`
- Int int `validate:"gtecsfield=Inner.Int"`
- Uint uint `validate:"gtecsfield=Inner.Uint"`
- Float float64 `validate:"gtecsfield=Inner.Float"`
- Array []string `validate:"gtecsfield=Inner.Array"`
- }
+// errs = validate.Field(i, "eq=1")
+// Equal(t, errs, nil)
- now := time.Now().UTC()
- then := now.Add(time.Hour * -5)
+// errs = validate.Field(j, "eq=1")
+// Equal(t, errs, nil)
- inner := &Inner{
- CreatedAt: &then,
- String: "abcd",
- Int: 13,
- Uint: 13,
- Float: 1.13,
- Array: []string{"val1", "val2"},
- }
+// errs = validate.Field(k, "eq=1.543")
+// Equal(t, errs, nil)
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- String: "abcde",
- Int: 14,
- Uint: 14,
- Float: 1.14,
- Array: []string{"val1", "val2", "val3"},
- }
+// errs = validate.Field(arr, "eq=1")
+// Equal(t, errs, nil)
- errs := validate.Struct(test)
- Equal(t, errs, nil)
+// errs = validate.Field(arr, "eq=2")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "eq")
- test.CreatedAt = &then
- test.String = "abcd"
- test.Int = 13
- test.Uint = 13
- test.Float = 1.13
- test.Array = []string{"val1", "val2"}
+// PanicMatches(t, func() { validate.Field(now, "eq=now") }, "Bad field type time.Time")
+// }
- errs = validate.Struct(test)
- Equal(t, errs, nil)
+// func TestBase64Validation(t *testing.T) {
- before := now.Add(time.Hour * -10)
+// s := "dW5pY29ybg=="
- test.CreatedAt = &before
- test.String = "abc"
- test.Int = 12
- test.Uint = 12
- test.Float = 1.12
- test.Array = []string{"val1"}
+// errs := validate.Field(s, "base64")
+// Equal(t, errs, nil)
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "gtecsfield")
- AssertError(t, errs, "Test.String", "String", "gtecsfield")
- AssertError(t, errs, "Test.Int", "Int", "gtecsfield")
- AssertError(t, errs, "Test.Uint", "Uint", "gtecsfield")
- AssertError(t, errs, "Test.Float", "Float", "gtecsfield")
- AssertError(t, errs, "Test.Array", "Array", "gtecsfield")
-
- errs = validate.FieldWithValue(1, "", "gtecsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtecsfield")
+// s = "dGhpIGlzIGEgdGVzdCBiYXNlNjQ="
+// errs = validate.Field(s, "base64")
+// Equal(t, errs, nil)
- errs = validate.FieldWithValue(test, now, "gtecsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtecsfield")
-}
+// s = ""
+// errs = validate.Field(s, "base64")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "base64")
-func TestCrossStructGtFieldValidation(t *testing.T) {
+// s = "dW5pY29ybg== foo bar"
+// errs = validate.Field(s, "base64")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "base64")
+// }
- type Inner struct {
- CreatedAt *time.Time
- String string
- Int int
- Uint uint
- Float float64
- Array []string
- }
+// func TestNoStructLevelValidation(t *testing.T) {
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"gtcsfield=Inner.CreatedAt"`
- String string `validate:"gtcsfield=Inner.String"`
- Int int `validate:"gtcsfield=Inner.Int"`
- Uint uint `validate:"gtcsfield=Inner.Uint"`
- Float float64 `validate:"gtcsfield=Inner.Float"`
- Array []string `validate:"gtcsfield=Inner.Array"`
- }
+// type Inner struct {
+// Test string `validate:"len=5"`
+// }
- now := time.Now().UTC()
- then := now.Add(time.Hour * -5)
+// type Outer struct {
+// InnerStruct *Inner `validate:"required,nostructlevel"`
+// }
- inner := &Inner{
- CreatedAt: &then,
- String: "abcd",
- Int: 13,
- Uint: 13,
- Float: 1.13,
- Array: []string{"val1", "val2"},
- }
+// outer := &Outer{
+// InnerStruct: nil,
+// }
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- String: "abcde",
- Int: 14,
- Uint: 14,
- Float: 1.14,
- Array: []string{"val1", "val2", "val3"},
- }
+// errs := validate.Struct(outer)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required")
- errs := validate.Struct(test)
- Equal(t, errs, nil)
+// inner := &Inner{
+// Test: "1234",
+// }
- test.CreatedAt = &then
- test.String = "abcd"
- test.Int = 13
- test.Uint = 13
- test.Float = 1.13
- test.Array = []string{"val1", "val2"}
+// outer = &Outer{
+// InnerStruct: inner,
+// }
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "gtcsfield")
- AssertError(t, errs, "Test.String", "String", "gtcsfield")
- AssertError(t, errs, "Test.Int", "Int", "gtcsfield")
- AssertError(t, errs, "Test.Uint", "Uint", "gtcsfield")
- AssertError(t, errs, "Test.Float", "Float", "gtcsfield")
- AssertError(t, errs, "Test.Array", "Array", "gtcsfield")
-
- errs = validate.FieldWithValue(1, "", "gtcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtcsfield")
+// errs = validate.Struct(outer)
+// Equal(t, errs, nil)
+// }
- errs = validate.FieldWithValue(test, now, "gtcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtcsfield")
-}
+// func TestStructOnlyValidation(t *testing.T) {
-func TestCrossStructNeFieldValidation(t *testing.T) {
+// type Inner struct {
+// Test string `validate:"len=5"`
+// }
- type Inner struct {
- CreatedAt *time.Time
- }
+// type Outer struct {
+// InnerStruct *Inner `validate:"required,structonly"`
+// }
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"necsfield=Inner.CreatedAt"`
- }
+// outer := &Outer{
+// InnerStruct: nil,
+// }
- now := time.Now().UTC()
- then := now.Add(time.Hour * 5)
+// errs := validate.Struct(outer)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required")
- inner := &Inner{
- CreatedAt: &then,
- }
+// inner := &Inner{
+// Test: "1234",
+// }
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- }
+// outer = &Outer{
+// InnerStruct: inner,
+// }
- errs := validate.Struct(test)
- Equal(t, errs, nil)
+// errs = validate.Struct(outer)
+// Equal(t, errs, nil)
+// }
- test.CreatedAt = &then
+// func TestGtField(t *testing.T) {
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "necsfield")
-
- var j uint64
- var k float64
- var j2 uint64
- var k2 float64
- s := "abcd"
- i := 1
- j = 1
- k = 1.543
- arr := []string{"test"}
-
- s2 := "abcd"
- i2 := 1
- j2 = 1
- k2 = 1.543
- arr2 := []string{"test"}
- arr3 := []string{"test", "test2"}
- now2 := now
-
- errs = validate.FieldWithValue(s, s2, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "necsfield")
+// type TimeTest struct {
+// Start *time.Time `validate:"required,gt"`
+// End *time.Time `validate:"required,gt,gtfield=Start"`
+// }
- errs = validate.FieldWithValue(i2, i, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "necsfield")
+// now := time.Now()
+// start := now.Add(time.Hour * 24)
+// end := start.Add(time.Hour * 24)
- errs = validate.FieldWithValue(j2, j, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "necsfield")
+// timeTest := &TimeTest{
+// Start: &start,
+// End: &end,
+// }
- errs = validate.FieldWithValue(k2, k, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "necsfield")
+// errs := validate.Struct(timeTest)
+// Equal(t, errs, nil)
- errs = validate.FieldWithValue(arr2, arr, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "necsfield")
+// timeTest = &TimeTest{
+// Start: &end,
+// End: &start,
+// }
- errs = validate.FieldWithValue(now2, now, "necsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "necsfield")
+// errs = validate.Struct(timeTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TimeTest.End", "End", "gtfield")
- errs = validate.FieldWithValue(arr3, arr, "necsfield")
- Equal(t, errs, nil)
+// errs = validate.FieldWithValue(&start, &end, "gtfield")
+// Equal(t, errs, nil)
- type SInner struct {
- Name string
- }
+// errs = validate.FieldWithValue(&end, &start, "gtfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtfield")
- type TStruct struct {
- Inner *SInner
- CreatedAt *time.Time `validate:"necsfield=Inner"`
- }
+// errs = validate.FieldWithValue(&timeTest, &end, "gtfield")
+// NotEqual(t, errs, nil)
- sinner := &SInner{
- Name: "NAME",
- }
+// errs = validate.FieldWithValue("test", "test bigger", "gtfield")
+// Equal(t, errs, nil)
- test2 := &TStruct{
- Inner: sinner,
- CreatedAt: &now,
- }
+// type IntTest struct {
+// Val1 int `validate:"required"`
+// Val2 int `validate:"required,gtfield=Val1"`
+// }
- errs = validate.Struct(test2)
- Equal(t, errs, nil)
+// intTest := &IntTest{
+// Val1: 1,
+// Val2: 5,
+// }
- test2.Inner = nil
- errs = validate.Struct(test2)
- Equal(t, errs, nil)
+// errs = validate.Struct(intTest)
+// Equal(t, errs, nil)
- errs = validate.FieldWithValue(nil, 1, "necsfield")
- Equal(t, errs, nil)
-}
+// intTest = &IntTest{
+// Val1: 5,
+// Val2: 1,
+// }
-func TestCrossStructEqFieldValidation(t *testing.T) {
+// errs = validate.Struct(intTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "IntTest.Val2", "Val2", "gtfield")
- type Inner struct {
- CreatedAt *time.Time
- }
+// errs = validate.FieldWithValue(int(1), int(5), "gtfield")
+// Equal(t, errs, nil)
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"eqcsfield=Inner.CreatedAt"`
- }
+// errs = validate.FieldWithValue(int(5), int(1), "gtfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtfield")
- now := time.Now().UTC()
+// type UIntTest struct {
+// Val1 uint `validate:"required"`
+// Val2 uint `validate:"required,gtfield=Val1"`
+// }
- inner := &Inner{
- CreatedAt: &now,
- }
+// uIntTest := &UIntTest{
+// Val1: 1,
+// Val2: 5,
+// }
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- }
+// errs = validate.Struct(uIntTest)
+// Equal(t, errs, nil)
- errs := validate.Struct(test)
- Equal(t, errs, nil)
+// uIntTest = &UIntTest{
+// Val1: 5,
+// Val2: 1,
+// }
- newTime := time.Now().UTC()
- test.CreatedAt = &newTime
+// errs = validate.Struct(uIntTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "UIntTest.Val2", "Val2", "gtfield")
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "eqcsfield")
-
- var j uint64
- var k float64
- s := "abcd"
- i := 1
- j = 1
- k = 1.543
- arr := []string{"test"}
-
- var j2 uint64
- var k2 float64
- s2 := "abcd"
- i2 := 1
- j2 = 1
- k2 = 1.543
- arr2 := []string{"test"}
- arr3 := []string{"test", "test2"}
- now2 := now
-
- errs = validate.FieldWithValue(s, s2, "eqcsfield")
- Equal(t, errs, nil)
+// errs = validate.FieldWithValue(uint(1), uint(5), "gtfield")
+// Equal(t, errs, nil)
- errs = validate.FieldWithValue(i2, i, "eqcsfield")
- Equal(t, errs, nil)
+// errs = validate.FieldWithValue(uint(5), uint(1), "gtfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtfield")
- errs = validate.FieldWithValue(j2, j, "eqcsfield")
- Equal(t, errs, nil)
+// type FloatTest struct {
+// Val1 float64 `validate:"required"`
+// Val2 float64 `validate:"required,gtfield=Val1"`
+// }
+
+// floatTest := &FloatTest{
+// Val1: 1,
+// Val2: 5,
+// }
+
+// errs = validate.Struct(floatTest)
+// Equal(t, errs, nil)
+
+// floatTest = &FloatTest{
+// Val1: 5,
+// Val2: 1,
+// }
+
+// errs = validate.Struct(floatTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "FloatTest.Val2", "Val2", "gtfield")
+
+// errs = validate.FieldWithValue(float32(1), float32(5), "gtfield")
+// Equal(t, errs, nil)
- errs = validate.FieldWithValue(k2, k, "eqcsfield")
- Equal(t, errs, nil)
+// errs = validate.FieldWithValue(float32(5), float32(1), "gtfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtfield")
- errs = validate.FieldWithValue(arr2, arr, "eqcsfield")
- Equal(t, errs, nil)
+// errs = validate.FieldWithValue(nil, 1, "gtfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtfield")
+
+// errs = validate.FieldWithValue(5, "T", "gtfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtfield")
+
+// errs = validate.FieldWithValue(5, start, "gtfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtfield")
+
+// type TimeTest2 struct {
+// Start *time.Time `validate:"required"`
+// End *time.Time `validate:"required,gtfield=NonExistantField"`
+// }
+
+// timeTest2 := &TimeTest2{
+// Start: &start,
+// End: &end,
+// }
+
+// errs = validate.Struct(timeTest2)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TimeTest2.End", "End", "gtfield")
+// }
+
+// func TestLtField(t *testing.T) {
+
+// type TimeTest struct {
+// Start *time.Time `validate:"required,lt,ltfield=End"`
+// End *time.Time `validate:"required,lt"`
+// }
+
+// now := time.Now()
+// start := now.Add(time.Hour * 24 * -1 * 2)
+// end := start.Add(time.Hour * 24)
+
+// timeTest := &TimeTest{
+// Start: &start,
+// End: &end,
+// }
+
+// errs := validate.Struct(timeTest)
+// Equal(t, errs, nil)
+
+// timeTest = &TimeTest{
+// Start: &end,
+// End: &start,
+// }
+
+// errs = validate.Struct(timeTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TimeTest.Start", "Start", "ltfield")
+
+// errs = validate.FieldWithValue(&end, &start, "ltfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(&start, &end, "ltfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltfield")
+
+// errs = validate.FieldWithValue(timeTest, &end, "ltfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltfield")
+
+// errs = validate.FieldWithValue("test", "tes", "ltfield")
+// Equal(t, errs, nil)
+
+// type IntTest struct {
+// Val1 int `validate:"required"`
+// Val2 int `validate:"required,ltfield=Val1"`
+// }
+
+// intTest := &IntTest{
+// Val1: 5,
+// Val2: 1,
+// }
+
+// errs = validate.Struct(intTest)
+// Equal(t, errs, nil)
+
+// intTest = &IntTest{
+// Val1: 1,
+// Val2: 5,
+// }
+
+// errs = validate.Struct(intTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "IntTest.Val2", "Val2", "ltfield")
+
+// errs = validate.FieldWithValue(int(5), int(1), "ltfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(int(1), int(5), "ltfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltfield")
+
+// type UIntTest struct {
+// Val1 uint `validate:"required"`
+// Val2 uint `validate:"required,ltfield=Val1"`
+// }
+
+// uIntTest := &UIntTest{
+// Val1: 5,
+// Val2: 1,
+// }
+
+// errs = validate.Struct(uIntTest)
+// Equal(t, errs, nil)
+
+// uIntTest = &UIntTest{
+// Val1: 1,
+// Val2: 5,
+// }
+
+// errs = validate.Struct(uIntTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "UIntTest.Val2", "Val2", "ltfield")
+
+// errs = validate.FieldWithValue(uint(5), uint(1), "ltfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(uint(1), uint(5), "ltfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltfield")
- errs = validate.FieldWithValue(now2, now, "eqcsfield")
- Equal(t, errs, nil)
+// type FloatTest struct {
+// Val1 float64 `validate:"required"`
+// Val2 float64 `validate:"required,ltfield=Val1"`
+// }
+
+// floatTest := &FloatTest{
+// Val1: 5,
+// Val2: 1,
+// }
+
+// errs = validate.Struct(floatTest)
+// Equal(t, errs, nil)
+
+// floatTest = &FloatTest{
+// Val1: 1,
+// Val2: 5,
+// }
+
+// errs = validate.Struct(floatTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "FloatTest.Val2", "Val2", "ltfield")
+
+// errs = validate.FieldWithValue(float32(5), float32(1), "ltfield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(float32(1), float32(5), "ltfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltfield")
+
+// errs = validate.FieldWithValue(nil, 5, "ltfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltfield")
+
+// errs = validate.FieldWithValue(1, "T", "ltfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltfield")
+
+// errs = validate.FieldWithValue(1, end, "ltfield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltfield")
+
+// type TimeTest2 struct {
+// Start *time.Time `validate:"required"`
+// End *time.Time `validate:"required,ltfield=NonExistantField"`
+// }
+
+// timeTest2 := &TimeTest2{
+// Start: &end,
+// End: &start,
+// }
+
+// errs = validate.Struct(timeTest2)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TimeTest2.End", "End", "ltfield")
+// }
+
+// func TestLteField(t *testing.T) {
+
+// type TimeTest struct {
+// Start *time.Time `validate:"required,lte,ltefield=End"`
+// End *time.Time `validate:"required,lte"`
+// }
+
+// now := time.Now()
+// start := now.Add(time.Hour * 24 * -1 * 2)
+// end := start.Add(time.Hour * 24)
+
+// timeTest := &TimeTest{
+// Start: &start,
+// End: &end,
+// }
+
+// errs := validate.Struct(timeTest)
+// Equal(t, errs, nil)
+
+// timeTest = &TimeTest{
+// Start: &end,
+// End: &start,
+// }
+
+// errs = validate.Struct(timeTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TimeTest.Start", "Start", "ltefield")
- errs = validate.FieldWithValue(arr3, arr, "eqcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "eqcsfield")
+// errs = validate.FieldWithValue(&end, &start, "ltefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(&start, &end, "ltefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltefield")
+
+// errs = validate.FieldWithValue(timeTest, &end, "ltefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltefield")
+
+// errs = validate.FieldWithValue("test", "tes", "ltefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue("test", "test", "ltefield")
+// Equal(t, errs, nil)
+
+// type IntTest struct {
+// Val1 int `validate:"required"`
+// Val2 int `validate:"required,ltefield=Val1"`
+// }
+
+// intTest := &IntTest{
+// Val1: 5,
+// Val2: 1,
+// }
+
+// errs = validate.Struct(intTest)
+// Equal(t, errs, nil)
+
+// intTest = &IntTest{
+// Val1: 1,
+// Val2: 5,
+// }
+
+// errs = validate.Struct(intTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "IntTest.Val2", "Val2", "ltefield")
+
+// errs = validate.FieldWithValue(int(5), int(1), "ltefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(int(1), int(5), "ltefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltefield")
+
+// type UIntTest struct {
+// Val1 uint `validate:"required"`
+// Val2 uint `validate:"required,ltefield=Val1"`
+// }
+
+// uIntTest := &UIntTest{
+// Val1: 5,
+// Val2: 1,
+// }
+
+// errs = validate.Struct(uIntTest)
+// Equal(t, errs, nil)
+
+// uIntTest = &UIntTest{
+// Val1: 1,
+// Val2: 5,
+// }
+
+// errs = validate.Struct(uIntTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "UIntTest.Val2", "Val2", "ltefield")
+
+// errs = validate.FieldWithValue(uint(5), uint(1), "ltefield")
+// Equal(t, errs, nil)
- type SInner struct {
- Name string
- }
+// errs = validate.FieldWithValue(uint(1), uint(5), "ltefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltefield")
+
+// type FloatTest struct {
+// Val1 float64 `validate:"required"`
+// Val2 float64 `validate:"required,ltefield=Val1"`
+// }
+
+// floatTest := &FloatTest{
+// Val1: 5,
+// Val2: 1,
+// }
+
+// errs = validate.Struct(floatTest)
+// Equal(t, errs, nil)
- type TStruct struct {
- Inner *SInner
- CreatedAt *time.Time `validate:"eqcsfield=Inner"`
- }
+// floatTest = &FloatTest{
+// Val1: 1,
+// Val2: 5,
+// }
+
+// errs = validate.Struct(floatTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "FloatTest.Val2", "Val2", "ltefield")
+
+// errs = validate.FieldWithValue(float32(5), float32(1), "ltefield")
+// Equal(t, errs, nil)
- sinner := &SInner{
- Name: "NAME",
- }
+// errs = validate.FieldWithValue(float32(1), float32(5), "ltefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltefield")
+
+// errs = validate.FieldWithValue(nil, 5, "ltefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltefield")
+
+// errs = validate.FieldWithValue(1, "T", "ltefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltefield")
+
+// errs = validate.FieldWithValue(1, end, "ltefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "ltefield")
+
+// type TimeTest2 struct {
+// Start *time.Time `validate:"required"`
+// End *time.Time `validate:"required,ltefield=NonExistantField"`
+// }
+
+// timeTest2 := &TimeTest2{
+// Start: &end,
+// End: &start,
+// }
+
+// errs = validate.Struct(timeTest2)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TimeTest2.End", "End", "ltefield")
+// }
+
+// func TestGteField(t *testing.T) {
+
+// type TimeTest struct {
+// Start *time.Time `validate:"required,gte"`
+// End *time.Time `validate:"required,gte,gtefield=Start"`
+// }
+
+// now := time.Now()
+// start := now.Add(time.Hour * 24)
+// end := start.Add(time.Hour * 24)
+
+// timeTest := &TimeTest{
+// Start: &start,
+// End: &end,
+// }
+
+// errs := validate.Struct(timeTest)
+// Equal(t, errs, nil)
+
+// timeTest = &TimeTest{
+// Start: &end,
+// End: &start,
+// }
+
+// errs = validate.Struct(timeTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TimeTest.End", "End", "gtefield")
- test2 := &TStruct{
- Inner: sinner,
- CreatedAt: &now,
- }
+// errs = validate.FieldWithValue(&start, &end, "gtefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(&end, &start, "gtefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtefield")
+
+// errs = validate.FieldWithValue(timeTest, &start, "gtefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtefield")
+
+// errs = validate.FieldWithValue("test", "test", "gtefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue("test", "test bigger", "gtefield")
+// Equal(t, errs, nil)
+
+// type IntTest struct {
+// Val1 int `validate:"required"`
+// Val2 int `validate:"required,gtefield=Val1"`
+// }
+
+// intTest := &IntTest{
+// Val1: 1,
+// Val2: 5,
+// }
+
+// errs = validate.Struct(intTest)
+// Equal(t, errs, nil)
+
+// intTest = &IntTest{
+// Val1: 5,
+// Val2: 1,
+// }
+
+// errs = validate.Struct(intTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "IntTest.Val2", "Val2", "gtefield")
+
+// errs = validate.FieldWithValue(int(1), int(5), "gtefield")
+// Equal(t, errs, nil)
+
+// errs = validate.FieldWithValue(int(5), int(1), "gtefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtefield")
- errs = validate.Struct(test2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqcsfield")
+// type UIntTest struct {
+// Val1 uint `validate:"required"`
+// Val2 uint `validate:"required,gtefield=Val1"`
+// }
- test2.Inner = nil
- errs = validate.Struct(test2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqcsfield")
+// uIntTest := &UIntTest{
+// Val1: 1,
+// Val2: 5,
+// }
- errs = validate.FieldWithValue(nil, 1, "eqcsfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "eqcsfield")
-}
+// errs = validate.Struct(uIntTest)
+// Equal(t, errs, nil)
-func TestCrossNamespaceFieldValidation(t *testing.T) {
+// uIntTest = &UIntTest{
+// Val1: 5,
+// Val2: 1,
+// }
- type SliceStruct struct {
- Name string
- }
+// errs = validate.Struct(uIntTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "UIntTest.Val2", "Val2", "gtefield")
- type MapStruct struct {
- Name string
- }
+// errs = validate.FieldWithValue(uint(1), uint(5), "gtefield")
+// Equal(t, errs, nil)
- type Inner struct {
- CreatedAt *time.Time
- Slice []string
- SliceStructs []*SliceStruct
- SliceSlice [][]string
- SliceSliceStruct [][]*SliceStruct
- SliceMap []map[string]string
- Map map[string]string
- MapMap map[string]map[string]string
- MapStructs map[string]*SliceStruct
- MapMapStruct map[string]map[string]*SliceStruct
- MapSlice map[string][]string
- MapInt map[int]string
- MapInt8 map[int8]string
- MapInt16 map[int16]string
- MapInt32 map[int32]string
- MapInt64 map[int64]string
- MapUint map[uint]string
- MapUint8 map[uint8]string
- MapUint16 map[uint16]string
- MapUint32 map[uint32]string
- MapUint64 map[uint64]string
- MapFloat32 map[float32]string
- MapFloat64 map[float64]string
- MapBool map[bool]string
- }
+// errs = validate.FieldWithValue(uint(5), uint(1), "gtefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtefield")
- type Test struct {
- Inner *Inner
- CreatedAt *time.Time
- }
+// type FloatTest struct {
+// Val1 float64 `validate:"required"`
+// Val2 float64 `validate:"required,gtefield=Val1"`
+// }
- now := time.Now()
-
- inner := &Inner{
- CreatedAt: &now,
- Slice: []string{"val1", "val2", "val3"},
- SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}},
- SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}},
- SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}},
- SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}},
- Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"},
- MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}},
- MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}},
- MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}},
- MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}},
- MapInt: map[int]string{1: "val1", 2: "val2", 3: "val3"},
- MapInt8: map[int8]string{1: "val1", 2: "val2", 3: "val3"},
- MapInt16: map[int16]string{1: "val1", 2: "val2", 3: "val3"},
- MapInt32: map[int32]string{1: "val1", 2: "val2", 3: "val3"},
- MapInt64: map[int64]string{1: "val1", 2: "val2", 3: "val3"},
- MapUint: map[uint]string{1: "val1", 2: "val2", 3: "val3"},
- MapUint8: map[uint8]string{1: "val1", 2: "val2", 3: "val3"},
- MapUint16: map[uint16]string{1: "val1", 2: "val2", 3: "val3"},
- MapUint32: map[uint32]string{1: "val1", 2: "val2", 3: "val3"},
- MapUint64: map[uint64]string{1: "val1", 2: "val2", 3: "val3"},
- MapFloat32: map[float32]string{1.01: "val1", 2.02: "val2", 3.03: "val3"},
- MapFloat64: map[float64]string{1.01: "val1", 2.02: "val2", 3.03: "val3"},
- MapBool: map[bool]string{true: "val1", false: "val2"},
- }
+// floatTest := &FloatTest{
+// Val1: 1,
+// Val2: 5,
+// }
- test := &Test{
- Inner: inner,
- CreatedAt: &now,
- }
+// errs = validate.Struct(floatTest)
+// Equal(t, errs, nil)
- val := reflect.ValueOf(test)
-
- current, kind, ok := validate.GetStructFieldOK(val, "Inner.CreatedAt")
- Equal(t, ok, true)
- Equal(t, kind, reflect.Struct)
- tm, ok := current.Interface().(time.Time)
- Equal(t, ok, true)
- Equal(t, tm, now)
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.Slice[1]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.CrazyNonExistantField")
- Equal(t, ok, false)
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.Slice[101]")
- Equal(t, ok, false)
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.Map[key3]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val3")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapMap[key2][key2-1]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapStructs[key2].Name")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "name2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapMapStruct[key3][key3-1].Name")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "name3")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceSlice[2][0]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "7")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceSliceStruct[2][1].Name")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "name8")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceMap[1][key5]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val5")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapSlice[key3][2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "9")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt8[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt16[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt32[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt64[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint8[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint16[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint32[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint64[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapFloat32[3.03]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val3")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapFloat64[2.02]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val2")
-
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapBool[true]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.String)
- Equal(t, current.String(), "val1")
-
- inner = &Inner{
- CreatedAt: &now,
- Slice: []string{"val1", "val2", "val3"},
- SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, nil},
- SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}},
- SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}},
- SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}},
- Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"},
- MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}},
- MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}},
- MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}},
- MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}},
- }
+// floatTest = &FloatTest{
+// Val1: 5,
+// Val2: 1,
+// }
- test = &Test{
- Inner: inner,
- CreatedAt: nil,
- }
+// errs = validate.Struct(floatTest)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "FloatTest.Val2", "Val2", "gtefield")
- val = reflect.ValueOf(test)
+// errs = validate.FieldWithValue(float32(1), float32(5), "gtefield")
+// Equal(t, errs, nil)
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceStructs[2]")
- Equal(t, ok, true)
- Equal(t, kind, reflect.Ptr)
- Equal(t, current.String(), "<*validator.SliceStruct Value>")
- Equal(t, current.IsNil(), true)
+// errs = validate.FieldWithValue(float32(5), float32(1), "gtefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtefield")
- current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceStructs[2].Name")
- Equal(t, ok, false)
- Equal(t, kind, reflect.Ptr)
- Equal(t, current.String(), "<*validator.SliceStruct Value>")
- Equal(t, current.IsNil(), true)
+// errs = validate.FieldWithValue(nil, 1, "gtefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtefield")
- PanicMatches(t, func() { validate.GetStructFieldOK(reflect.ValueOf(1), "crazyinput") }, "Invalid field namespace")
-}
+// errs = validate.FieldWithValue(5, "T", "gtefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtefield")
-func TestExistsValidation(t *testing.T) {
+// errs = validate.FieldWithValue(5, start, "gtefield")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gtefield")
- jsonText := "{ \"truthiness2\": true }"
+// type TimeTest2 struct {
+// Start *time.Time `validate:"required"`
+// End *time.Time `validate:"required,gtefield=NonExistantField"`
+// }
- type Thing struct {
- Truthiness *bool `json:"truthiness" validate:"exists,required"`
- }
+// timeTest2 := &TimeTest2{
+// Start: &start,
+// End: &end,
+// }
- var ting Thing
+// errs = validate.Struct(timeTest2)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TimeTest2.End", "End", "gtefield")
+// }
- err := json.Unmarshal([]byte(jsonText), &ting)
- Equal(t, err, nil)
- NotEqual(t, ting, nil)
- Equal(t, ting.Truthiness, nil)
+// func TestValidateByTagAndValue(t *testing.T) {
- errs := validate.Struct(ting)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Thing.Truthiness", "Truthiness", "exists")
+// val := "test"
+// field := "test"
+// errs := validate.FieldWithValue(val, field, "required")
+// Equal(t, errs, nil)
- jsonText = "{ \"truthiness\": true }"
+// fn := func(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- err = json.Unmarshal([]byte(jsonText), &ting)
- Equal(t, err, nil)
- NotEqual(t, ting, nil)
- Equal(t, ting.Truthiness, true)
+// return current.String() == field.String()
+// }
- errs = validate.Struct(ting)
- Equal(t, errs, nil)
-}
+// validate.RegisterValidation("isequaltestfunc", fn)
-func TestSQLValue2Validation(t *testing.T) {
+// errs = validate.FieldWithValue(val, field, "isequaltestfunc")
+// Equal(t, errs, nil)
- config := &Config{
- TagName: "validate",
- }
+// val = "unequal"
- validate := New(config)
- validate.RegisterCustomTypeFunc(ValidateValuerType, valuer{}, (*driver.Valuer)(nil), sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
- validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
- validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1)
+// errs = validate.FieldWithValue(val, field, "isequaltestfunc")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "isequaltestfunc")
+// }
- val := valuer{
- Name: "",
- }
+// func TestAddFunctions(t *testing.T) {
- errs := validate.Field(val, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "required")
+// fn := func(v *Validate, topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
- val.Name = "Valid Name"
- errs = validate.Field(val, "required")
- Equal(t, errs, nil)
+// return true
+// }
- val.Name = "errorme"
+// config := &Config{
+// TagName: "validateme",
+// }
- PanicMatches(t, func() { validate.Field(val, "required") }, "SQL Driver Valuer error: some kind of error")
+// validate := New(config)
- type myValuer valuer
+// errs := validate.RegisterValidation("new", fn)
+// Equal(t, errs, nil)
- myVal := valuer{
- Name: "",
- }
+// errs = validate.RegisterValidation("", fn)
+// NotEqual(t, errs, nil)
- errs = validate.Field(myVal, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "required")
+// validate.RegisterValidation("new", nil)
+// NotEqual(t, errs, nil)
- cust := MadeUpCustomType{
- FirstName: "Joey",
- LastName: "Bloggs",
- }
+// errs = validate.RegisterValidation("new", fn)
+// Equal(t, errs, nil)
- c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
+// PanicMatches(t, func() { validate.RegisterValidation("dive", fn) }, "Tag 'dive' either contains restricted characters or is the same as a restricted tag needed for normal operation")
+// }
- errs = validate.Struct(c)
- Equal(t, errs, nil)
+// func TestChangeTag(t *testing.T) {
- c.MadeUp.FirstName = ""
- c.OverriddenInt = 1
+// config := &Config{
+// TagName: "val",
+// }
+// validate := New(config)
- errs = validate.Struct(c)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "MadeUp", "required")
- AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "gt")
-}
+// type Test struct {
+// Name string `val:"len=4"`
+// }
+// s := &Test{
+// Name: "TEST",
+// }
-func TestSQLValueValidation(t *testing.T) {
+// errs := validate.Struct(s)
+// Equal(t, errs, nil)
+// }
- validate := New(&Config{TagName: "validate"})
- validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{})
- validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
- validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1)
+// func TestUnexposedStruct(t *testing.T) {
- val := valuer{
- Name: "",
- }
+// type Test struct {
+// Name string
+// unexposed struct {
+// A string `validate:"required"`
+// }
+// }
- errs := validate.Field(val, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "required")
+// s := &Test{
+// Name: "TEST",
+// }
- val.Name = "Valid Name"
- errs = validate.Field(val, "required")
- Equal(t, errs, nil)
+// errs := validate.Struct(s)
+// Equal(t, errs, nil)
+// }
- val.Name = "errorme"
+// func TestBadParams(t *testing.T) {
- PanicMatches(t, func() { errs = validate.Field(val, "required") }, "SQL Driver Valuer error: some kind of error")
+// i := 1
+// errs := validate.Field(i, "-")
+// Equal(t, errs, nil)
- type myValuer valuer
+// PanicMatches(t, func() { validate.Field(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
+// PanicMatches(t, func() { validate.Field(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
- myVal := valuer{
- Name: "",
- }
+// var ui uint = 1
+// PanicMatches(t, func() { validate.Field(ui, "len=a") }, "strconv.ParseUint: parsing \"a\": invalid syntax")
- errs = validate.Field(myVal, "required")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "required")
+// f := 1.23
+// PanicMatches(t, func() { validate.Field(f, "len=a") }, "strconv.ParseFloat: parsing \"a\": invalid syntax")
+// }
- cust := MadeUpCustomType{
- FirstName: "Joey",
- LastName: "Bloggs",
- }
+// func TestLength(t *testing.T) {
- c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
+// i := true
+// PanicMatches(t, func() { validate.Field(i, "len") }, "Bad field type bool")
+// }
- errs = validate.Struct(c)
- Equal(t, errs, nil)
+// func TestIsGt(t *testing.T) {
- c.MadeUp.FirstName = ""
- c.OverriddenInt = 1
+// myMap := map[string]string{}
+// errs := validate.Field(myMap, "gt=0")
+// NotEqual(t, errs, nil)
- errs = validate.Struct(c)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "MadeUp", "required")
- AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "gt")
-}
+// f := 1.23
+// errs = validate.Field(f, "gt=5")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gt")
-func TestMACValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"3D:F2:C9:A6:B3:4F", true},
- {"3D-F2-C9-A6-B3:4F", false},
- {"123", false},
- {"", false},
- {"abacaba", false},
- {"00:25:96:FF:FE:12:34:56", true},
- {"0025:96FF:FE12:3456", false},
- }
+// var ui uint = 5
+// errs = validate.Field(ui, "gt=10")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gt")
- for i, test := range tests {
-
- errs := validate.Field(test.param, "mac")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d mac failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d mac failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "mac" {
- t.Fatalf("Index: %d mac failed Error: %s", i, errs)
- }
- }
- }
- }
-}
+// i := true
+// PanicMatches(t, func() { validate.Field(i, "gt") }, "Bad field type bool")
-func TestIPValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"10.0.0.1", true},
- {"172.16.0.1", true},
- {"192.168.0.1", true},
- {"192.168.255.254", true},
- {"192.168.255.256", false},
- {"172.16.255.254", true},
- {"172.16.256.255", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652", true},
- {"2001:cdba:0:0:0:0:3257:9652", true},
- {"2001:cdba::3257:9652", true},
- }
+// tm := time.Now().UTC()
+// tm = tm.Add(time.Hour * 24)
- for i, test := range tests {
-
- errs := validate.Field(test.param, "ip")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "ip" {
- t.Fatalf("Index: %d ip failed Error: %s", i, errs)
- }
- }
- }
- }
-}
+// errs = validate.Field(tm, "gt")
+// Equal(t, errs, nil)
-func TestIPv6Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"10.0.0.1", false},
- {"172.16.0.1", false},
- {"192.168.0.1", false},
- {"192.168.255.254", false},
- {"192.168.255.256", false},
- {"172.16.255.254", false},
- {"172.16.256.255", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652", true},
- {"2001:cdba:0:0:0:0:3257:9652", true},
- {"2001:cdba::3257:9652", true},
- }
+// t2 := time.Now().UTC()
- for i, test := range tests {
-
- errs := validate.Field(test.param, "ipv6")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "ipv6" {
- t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestIPv4Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"10.0.0.1", true},
- {"172.16.0.1", true},
- {"192.168.0.1", true},
- {"192.168.255.254", true},
- {"192.168.255.256", false},
- {"172.16.255.254", true},
- {"172.16.256.255", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
- {"2001:cdba:0:0:0:0:3257:9652", false},
- {"2001:cdba::3257:9652", false},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "ipv4")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "ipv4" {
- t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestCIDRValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"10.0.0.0/0", true},
- {"10.0.0.1/8", true},
- {"172.16.0.1/16", true},
- {"192.168.0.1/24", true},
- {"192.168.255.254/24", true},
- {"192.168.255.254/48", false},
- {"192.168.255.256/24", false},
- {"172.16.255.254/16", true},
- {"172.16.256.255/16", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
- {"2001:cdba:0:0:0:0:3257:9652/32", true},
- {"2001:cdba::3257:9652/16", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "cidr")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "cidr" {
- t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestCIDRv6Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"10.0.0.0/0", false},
- {"10.0.0.1/8", false},
- {"172.16.0.1/16", false},
- {"192.168.0.1/24", false},
- {"192.168.255.254/24", false},
- {"192.168.255.254/48", false},
- {"192.168.255.256/24", false},
- {"172.16.255.254/16", false},
- {"172.16.256.255/16", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
- {"2001:cdba:0:0:0:0:3257:9652/32", true},
- {"2001:cdba::3257:9652/16", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "cidrv6")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "cidrv6" {
- t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestCIDRv4Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"10.0.0.0/0", true},
- {"10.0.0.1/8", true},
- {"172.16.0.1/16", true},
- {"192.168.0.1/24", true},
- {"192.168.255.254/24", true},
- {"192.168.255.254/48", false},
- {"192.168.255.256/24", false},
- {"172.16.255.254/16", true},
- {"172.16.256.255/16", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/64", false},
- {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
- {"2001:cdba:0:0:0:0:3257:9652/32", false},
- {"2001:cdba::3257:9652/16", false},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "cidrv4")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "cidrv4" {
- t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestTCPAddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", true},
- {"[::1]:80", true},
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
-
- for i, test := range tests {
- errs := validate.Field(test.param, "tcp_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "tcp_addr" {
- t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestTCP6AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", false},
- {"[::1]:80", true},
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
-
- for i, test := range tests {
- errs := validate.Field(test.param, "tcp6_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "tcp6_addr" {
- t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestTCP4AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", true},
- {"[::1]:80", false}, // https://github.com/golang/go/issues/14037
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
-
- for i, test := range tests {
- errs := validate.Field(test.param, "tcp4_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Log(test.param, IsEqual(errs, nil))
- t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "tcp4_addr" {
- t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestUDPAddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", true},
- {"[::1]:80", true},
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
-
- for i, test := range tests {
- errs := validate.Field(test.param, "udp_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "udp_addr" {
- t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestUDP6AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", false},
- {"[::1]:80", true},
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
-
- for i, test := range tests {
- errs := validate.Field(test.param, "udp6_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "udp6_addr" {
- t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestUDP4AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {":80", false},
- {"127.0.0.1:80", true},
- {"[::1]:80", false}, // https://github.com/golang/go/issues/14037
- {"256.0.0.0:1", false},
- {"[::1]", false},
- }
-
- for i, test := range tests {
- errs := validate.Field(test.param, "udp4_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Log(test.param, IsEqual(errs, nil))
- t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "udp4_addr" {
- t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestIPAddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"127.0.0.1", true},
- {"127.0.0.1:80", false},
- {"::1", true},
- {"256.0.0.0", false},
- {"localhost", false},
- }
-
- for i, test := range tests {
- errs := validate.Field(test.param, "ip_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "ip_addr" {
- t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestIP6AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"127.0.0.1", false}, // https://github.com/golang/go/issues/14037
- {"127.0.0.1:80", false},
- {"::1", true},
- {"0:0:0:0:0:0:0:1", true},
- {"256.0.0.0", false},
- }
-
- for i, test := range tests {
- errs := validate.Field(test.param, "ip6_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "ip6_addr" {
- t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestIP4AddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"127.0.0.1", true},
- {"127.0.0.1:80", false},
- {"::1", false}, // https://github.com/golang/go/issues/14037
- {"256.0.0.0", false},
- {"localhost", false},
- }
-
- for i, test := range tests {
- errs := validate.Field(test.param, "ip4_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Log(test.param, IsEqual(errs, nil))
- t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "ip4_addr" {
- t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestUnixAddrValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", true},
- {"v.sock", true},
- }
-
- for i, test := range tests {
- errs := validate.Field(test.param, "unix_addr")
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Log(test.param, IsEqual(errs, nil))
- t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "unix_addr" {
- t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-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.FieldWithValue(nil, iface, "")
- Equal(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 TestDatePtrValidationIssueValidation(t *testing.T) {
-
- type Test struct {
- LastViewed *time.Time
- Reminder *time.Time
- }
-
- test := &Test{}
-
- errs := validate.Struct(test)
- Equal(t, errs, nil)
-}
-
-func TestCommaAndPipeObfuscationValidation(t *testing.T) {
- s := "My Name Is, |joeybloggs|"
-
- errs := validate.Field(s, "excludesall=0x2C")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "excludesall")
-
- errs = validate.Field(s, "excludesall=0x7C")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "excludesall")
-}
-
-func TestBadKeyValidation(t *testing.T) {
- type Test struct {
- Name string `validate:"required, "`
- }
-
- tst := &Test{
- Name: "test",
- }
-
- PanicMatches(t, func() { validate.Struct(tst) }, "Undefined validation function on field Name")
-
- type Test2 struct {
- Name string `validate:"required,,len=2"`
- }
-
- tst2 := &Test2{
- Name: "test",
- }
-
- PanicMatches(t, func() { validate.Struct(tst2) }, "Invalid validation tag on field Name")
-}
-
-func TestInterfaceErrValidation(t *testing.T) {
-
- var v1 interface{}
- var v2 interface{}
-
- v2 = 1
- v1 = v2
-
- errs := validate.Field(v1, "len=1")
- Equal(t, errs, nil)
-
- errs = validate.Field(v2, "len=1")
- Equal(t, errs, nil)
-
- type ExternalCMD struct {
- Userid string `json:"userid"`
- Action uint32 `json:"action"`
- Data interface{} `json:"data,omitempty" validate:"required"`
- }
-
- s := &ExternalCMD{
- Userid: "123456",
- Action: 10000,
- // Data: 1,
- }
-
- errs = validate.Struct(s)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "ExternalCMD.Data", "Data", "required")
-
- type ExternalCMD2 struct {
- Userid string `json:"userid"`
- Action uint32 `json:"action"`
- Data interface{} `json:"data,omitempty" validate:"len=1"`
- }
-
- s2 := &ExternalCMD2{
- Userid: "123456",
- Action: 10000,
- // Data: 1,
- }
-
- errs = validate.Struct(s2)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "ExternalCMD2.Data", "Data", "len")
-
- s3 := &ExternalCMD2{
- Userid: "123456",
- Action: 10000,
- Data: 2,
- }
-
- errs = validate.Struct(s3)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "ExternalCMD2.Data", "Data", "len")
-
- type Inner struct {
- Name string `validate:"required"`
- }
-
- inner := &Inner{
- Name: "",
- }
-
- s4 := &ExternalCMD{
- Userid: "123456",
- Action: 10000,
- Data: inner,
- }
-
- errs = validate.Struct(s4)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "ExternalCMD.Data.Name", "Name", "required")
-
- type TestMapStructPtr struct {
- Errs map[int]interface{} `validate:"gt=0,dive,len=2"`
- }
-
- mip := map[int]interface{}{0: &Inner{"ok"}, 3: nil, 4: &Inner{"ok"}}
-
- msp := &TestMapStructPtr{
- Errs: mip,
- }
-
- errs = validate.Struct(msp)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "TestMapStructPtr.Errs[3]", "Errs[3]", "len")
-
- type TestMultiDimensionalStructs struct {
- Errs [][]interface{} `validate:"gt=0,dive,dive"`
- }
-
- var errStructArray [][]interface{}
-
- errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
- errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
-
- tms := &TestMultiDimensionalStructs{
- Errs: errStructArray,
- }
-
- errs = validate.Struct(tms)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 4)
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "required")
-
- type TestMultiDimensionalStructsPtr2 struct {
- Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
- }
-
- var errStructPtr2Array [][]*Inner
-
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
-
- tmsp2 := &TestMultiDimensionalStructsPtr2{
- Errs: errStructPtr2Array,
- }
-
- errs = validate.Struct(tmsp2)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 6)
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "required")
-
- m := map[int]interface{}{0: "ok", 3: "", 4: "ok"}
-
- errs = validate.Field(m, "len=3,dive,len=2")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "[3]", "[3]", "len")
-
- errs = validate.Field(m, "len=2,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "", "", "len")
-
- arr := []interface{}{"ok", "", "ok"}
-
- errs = validate.Field(arr, "len=3,dive,len=2")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "[1]", "[1]", "len")
-
- errs = validate.Field(arr, "len=2,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "", "", "len")
-
- type MyStruct struct {
- A, B string
- C interface{}
- }
-
- var a MyStruct
-
- a.A = "value"
- a.C = "nu"
-
- errs = validate.Struct(a)
- Equal(t, errs, nil)
-}
-
-func TestMapDiveValidation(t *testing.T) {
-
- n := map[int]interface{}{0: nil}
- errs := validate.Field(n, "omitempty,required")
- Equal(t, errs, nil)
-
- m := map[int]string{0: "ok", 3: "", 4: "ok"}
-
- errs = validate.Field(m, "len=3,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "[3]", "[3]", "required")
-
- errs = validate.Field(m, "len=2,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "", "", "len")
-
- type Inner struct {
- Name string `validate:"required"`
- }
-
- type TestMapStruct struct {
- Errs map[int]Inner `validate:"gt=0,dive"`
- }
-
- mi := map[int]Inner{0: {"ok"}, 3: {""}, 4: {"ok"}}
-
- ms := &TestMapStruct{
- Errs: mi,
- }
-
- errs = validate.Struct(ms)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "TestMapStruct.Errs[3].Name", "Name", "required")
-
- // for full test coverage
- s := fmt.Sprint(errs.Error())
- NotEqual(t, s, "")
-
- type TestMapTimeStruct struct {
- Errs map[int]*time.Time `validate:"gt=0,dive,required"`
- }
-
- t1 := time.Now().UTC()
-
- mta := map[int]*time.Time{0: &t1, 3: nil, 4: nil}
-
- mt := &TestMapTimeStruct{
- Errs: mta,
- }
-
- errs = validate.Struct(mt)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 2)
- AssertError(t, errs, "TestMapTimeStruct.Errs[3]", "Errs[3]", "required")
- AssertError(t, errs, "TestMapTimeStruct.Errs[4]", "Errs[4]", "required")
-
- type TestMapStructPtr struct {
- Errs map[int]*Inner `validate:"gt=0,dive,required"`
- }
-
- mip := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
-
- msp := &TestMapStructPtr{
- Errs: mip,
- }
-
- errs = validate.Struct(msp)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "TestMapStructPtr.Errs[3]", "Errs[3]", "required")
-
- type TestMapStructPtr2 struct {
- Errs map[int]*Inner `validate:"gt=0,dive,omitempty,required"`
- }
-
- mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
-
- msp2 := &TestMapStructPtr2{
- Errs: mip2,
- }
-
- errs = validate.Struct(msp2)
- Equal(t, errs, nil)
-}
-
-func TestArrayDiveValidation(t *testing.T) {
-
- arr := []string{"ok", "", "ok"}
-
- errs := validate.Field(arr, "len=3,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "[1]", "[1]", "required")
-
- errs = validate.Field(arr, "len=2,dive,required")
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "", "", "len")
-
- type BadDive struct {
- Name string `validate:"dive"`
- }
-
- bd := &BadDive{
- Name: "TEST",
- }
-
- PanicMatches(t, func() { validate.Struct(bd) }, "dive error! can't dive on a non slice or map")
-
- type Test struct {
- Errs []string `validate:"gt=0,dive,required"`
- }
-
- test := &Test{
- Errs: []string{"ok", "", "ok"},
- }
-
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "Test.Errs[1]", "Errs[1]", "required")
-
- test = &Test{
- Errs: []string{"ok", "ok", ""},
- }
-
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 1)
- AssertError(t, errs, "Test.Errs[2]", "Errs[2]", "required")
-
- type TestMultiDimensional struct {
- Errs [][]string `validate:"gt=0,dive,dive,required"`
- }
-
- var errArray [][]string
-
- errArray = append(errArray, []string{"ok", "", ""})
- errArray = append(errArray, []string{"ok", "", ""})
-
- tm := &TestMultiDimensional{
- Errs: errArray,
- }
-
- errs = validate.Struct(tm)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 4)
- AssertError(t, errs, "TestMultiDimensional.Errs[0][1]", "Errs[0][1]", "required")
- AssertError(t, errs, "TestMultiDimensional.Errs[0][2]", "Errs[0][2]", "required")
- AssertError(t, errs, "TestMultiDimensional.Errs[1][1]", "Errs[1][1]", "required")
- AssertError(t, errs, "TestMultiDimensional.Errs[1][2]", "Errs[1][2]", "required")
-
- type Inner struct {
- Name string `validate:"required"`
- }
-
- type TestMultiDimensionalStructs struct {
- Errs [][]Inner `validate:"gt=0,dive,dive"`
- }
-
- var errStructArray [][]Inner
-
- errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
- errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
-
- tms := &TestMultiDimensionalStructs{
- Errs: errStructArray,
- }
-
- errs = validate.Struct(tms)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 4)
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "required")
-
- type TestMultiDimensionalStructsPtr struct {
- Errs [][]*Inner `validate:"gt=0,dive,dive"`
- }
-
- var errStructPtrArray [][]*Inner
-
- errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
- errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
- errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, nil})
-
- tmsp := &TestMultiDimensionalStructsPtr{
- Errs: errStructPtrArray,
- }
-
- errs = validate.Struct(tmsp)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 5)
- AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[2][1].Name", "Name", "required")
-
- // for full test coverage
- s := fmt.Sprint(errs.Error())
- NotEqual(t, s, "")
-
- type TestMultiDimensionalStructsPtr2 struct {
- Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
- }
-
- var errStructPtr2Array [][]*Inner
-
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
-
- tmsp2 := &TestMultiDimensionalStructsPtr2{
- Errs: errStructPtr2Array,
- }
-
- errs = validate.Struct(tmsp2)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 6)
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "required")
-
- type TestMultiDimensionalStructsPtr3 struct {
- Errs [][]*Inner `validate:"gt=0,dive,dive,omitempty"`
- }
-
- var errStructPtr3Array [][]*Inner
-
- errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
- errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, nil})
-
- tmsp3 := &TestMultiDimensionalStructsPtr3{
- Errs: errStructPtr3Array,
- }
-
- errs = validate.Struct(tmsp3)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 5)
- AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "Name", "required")
- AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[2][1].Name", "Name", "required")
-
- type TestMultiDimensionalTimeTime struct {
- Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
- }
-
- var errTimePtr3Array [][]*time.Time
-
- t1 := time.Now().UTC()
- t2 := time.Now().UTC()
- t3 := time.Now().UTC().Add(time.Hour * 24)
-
- errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, &t3})
- errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, nil})
- errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, nil, nil})
-
- tmtp3 := &TestMultiDimensionalTimeTime{
- Errs: errTimePtr3Array,
- }
-
- errs = validate.Struct(tmtp3)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 3)
- AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[1][2]", "Errs[1][2]", "required")
- AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][1]", "Errs[2][1]", "required")
- AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][2]", "Errs[2][2]", "required")
-
- type TestMultiDimensionalTimeTime2 struct {
- Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
- }
-
- var errTimeArray [][]*time.Time
-
- t1 = time.Now().UTC()
- t2 = time.Now().UTC()
- t3 = time.Now().UTC().Add(time.Hour * 24)
-
- errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, &t3})
- errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, nil})
- errTimeArray = append(errTimeArray, []*time.Time{&t1, nil, nil})
-
- tmtp := &TestMultiDimensionalTimeTime2{
- Errs: errTimeArray,
- }
-
- errs = validate.Struct(tmtp)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 3)
- AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[1][2]", "Errs[1][2]", "required")
- AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][1]", "Errs[2][1]", "required")
- AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][2]", "Errs[2][2]", "required")
-}
-
-func TestNilStructPointerValidation(t *testing.T) {
- type Inner struct {
- Data string
- }
-
- type Outer struct {
- Inner *Inner `validate:"omitempty"`
- }
-
- inner := &Inner{
- Data: "test",
- }
-
- outer := &Outer{
- Inner: inner,
- }
-
- errs := validate.Struct(outer)
- Equal(t, errs, nil)
-
- outer = &Outer{
- Inner: nil,
- }
-
- errs = validate.Struct(outer)
- Equal(t, errs, nil)
-
- type Inner2 struct {
- Data string
- }
-
- type Outer2 struct {
- Inner2 *Inner2 `validate:"required"`
- }
-
- inner2 := &Inner2{
- Data: "test",
- }
-
- outer2 := &Outer2{
- Inner2: inner2,
- }
-
- errs = validate.Struct(outer2)
- Equal(t, errs, nil)
-
- outer2 = &Outer2{
- Inner2: nil,
- }
-
- errs = validate.Struct(outer2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Outer2.Inner2", "Inner2", "required")
-
- type Inner3 struct {
- Data string
- }
-
- type Outer3 struct {
- Inner3 *Inner3
- }
-
- inner3 := &Inner3{
- Data: "test",
- }
-
- outer3 := &Outer3{
- Inner3: inner3,
- }
-
- errs = validate.Struct(outer3)
- Equal(t, errs, nil)
-
- type Inner4 struct {
- Data string
- }
-
- type Outer4 struct {
- Inner4 *Inner4 `validate:"-"`
- }
-
- inner4 := &Inner4{
- Data: "test",
- }
-
- outer4 := &Outer4{
- Inner4: inner4,
- }
-
- errs = validate.Struct(outer4)
- Equal(t, errs, nil)
-}
-
-func TestSSNValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"00-90-8787", false},
- {"66690-76", false},
- {"191 60 2869", true},
- {"191-60-2869", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "ssn")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "ssn" {
- t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestLongitudeValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"-180.000", true},
- {"180.1", false},
- {"+73.234", true},
- {"+382.3811", false},
- {"23.11111111", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "longitude")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "longitude" {
- t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestLatitudeValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"-90.000", true},
- {"+90", true},
- {"47.1231231", true},
- {"+99.9", false},
- {"108", false},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "latitude")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "latitude" {
- t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestDataURIValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"data:image/png;base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true},
- {"data:text/plain;base64,Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true},
- {"image/gif;base64,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
- {"data:image/gif;base64,MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" +
- "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" +
- "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" +
- "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" +
- "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" +
- "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true},
- {"data:image/png;base64,12345", false},
- {"", false},
- {"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "datauri")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "datauri" {
- t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestMultibyteValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", true},
- {"abc", false},
- {"123", false},
- {"<>@;.-=", false},
- {"ひらがな・カタカナ、.漢字", true},
- {"あいうえお foobar", true},
- {"test@example.com", true},
- {"test@example.com", true},
- {"1234abcDExyz", true},
- {"カタカナ", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "multibyte")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "multibyte" {
- t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestPrintableASCIIValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", true},
- {"foobar", false},
- {"xyz098", false},
- {"123456", false},
- {"カタカナ", false},
- {"foobar", true},
- {"0987654321", true},
- {"test@example.com", true},
- {"1234abcDEF", true},
- {"newline\n", false},
- {"\x19test\x7F", false},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "printascii")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "printascii" {
- t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestASCIIValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", true},
- {"foobar", false},
- {"xyz098", false},
- {"123456", false},
- {"カタカナ", false},
- {"foobar", true},
- {"0987654321", true},
- {"test@example.com", true},
- {"1234abcDEF", true},
- {"", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "ascii")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "ascii" {
- t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestUUID5Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
-
- {"", false},
- {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"9c858901-8a57-4791-81fe-4c455b099bc9", false},
- {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"987fbc97-4bed-5078-af07-9141ba07c9f3", true},
- {"987fbc97-4bed-5078-9f07-9141ba07c9f3", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "uuid5")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "uuid5" {
- t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestUUID4Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"a987fbc9-4bed-5078-af07-9141ba07c9f3", false},
- {"934859", false},
- {"57b73598-8764-4ad0-a76a-679bb6640eb1", true},
- {"625e63f3-58f5-40b7-83a1-a72ad31acffb", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "uuid4")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "uuid4" {
- t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestUUID3Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"412452646", false},
- {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false},
- {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "uuid3")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "uuid3" {
- t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestUUIDValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
- {"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false},
- {"a987fbc94bed3078cf079141ba07c9f3", false},
- {"934859", false},
- {"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false},
- {"aaaaaaaa-1111-1111-aaag-111111111111", false},
- {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "uuid")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "uuid" {
- t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestISBNValidation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"foo", false},
- {"3836221195", true},
- {"1-61729-085-8", true},
- {"3 423 21412 0", true},
- {"3 401 01319 X", true},
- {"9784873113685", true},
- {"978-4-87311-368-5", true},
- {"978 3401013190", true},
- {"978-3-8362-2119-1", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "isbn")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "isbn" {
- t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestISBN13Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"foo", false},
- {"3-8362-2119-5", false},
- {"01234567890ab", false},
- {"978 3 8362 2119 0", false},
- {"9784873113685", true},
- {"978-4-87311-368-5", true},
- {"978 3401013190", true},
- {"978-3-8362-2119-1", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "isbn13")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "isbn13" {
- t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestISBN10Validation(t *testing.T) {
- tests := []struct {
- param string
- expected bool
- }{
- {"", false},
- {"foo", false},
- {"3423214121", false},
- {"978-3836221191", false},
- {"3-423-21412-1", false},
- {"3 423 21412 1", false},
- {"3836221195", true},
- {"1-61729-085-8", true},
- {"3 423 21412 0", true},
- {"3 401 01319 X", true},
- }
-
- for i, test := range tests {
-
- errs := validate.Field(test.param, "isbn10")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "isbn10" {
- t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
- }
- }
- }
- }
-}
-
-func TestExcludesRuneValidation(t *testing.T) {
-
- tests := []struct {
- Value string `validate:"excludesrune=☻"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "a☺b☻c☹d", Tag: "excludesrune=☻", ExpectedNil: false},
- {Value: "abcd", Tag: "excludesrune=☻", ExpectedNil: true},
- }
-
- for i, s := range tests {
- errs := validate.Field(s.Value, s.Tag)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
-
- errs = validate.Struct(s)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
-}
-
-func TestExcludesAllValidation(t *testing.T) {
-
- tests := []struct {
- Value string `validate:"excludesall=@!{}[]"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "abcd@!jfk", Tag: "excludesall=@!{}[]", ExpectedNil: false},
- {Value: "abcdefg", Tag: "excludesall=@!{}[]", ExpectedNil: true},
- }
-
- for i, s := range tests {
- errs := validate.Field(s.Value, s.Tag)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
-
- errs = validate.Struct(s)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
-
- username := "joeybloggs "
-
- errs := validate.Field(username, "excludesall=@ ")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "excludesall")
-
- excluded := ","
-
- errs = validate.Field(excluded, "excludesall=!@#$%^&*()_+.0x2C?")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "excludesall")
-
- excluded = "="
-
- errs = validate.Field(excluded, "excludesall=!@#$%^&*()_+.0x2C=?")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "excludesall")
-}
-
-func TestExcludesValidation(t *testing.T) {
-
- tests := []struct {
- Value string `validate:"excludes=@"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "abcd@!jfk", Tag: "excludes=@", ExpectedNil: false},
- {Value: "abcdq!jfk", Tag: "excludes=@", ExpectedNil: true},
- }
-
- for i, s := range tests {
- errs := validate.Field(s.Value, s.Tag)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
-
- errs = validate.Struct(s)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
-}
-
-func TestContainsRuneValidation(t *testing.T) {
-
- tests := []struct {
- Value string `validate:"containsrune=☻"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "a☺b☻c☹d", Tag: "containsrune=☻", ExpectedNil: true},
- {Value: "abcd", Tag: "containsrune=☻", ExpectedNil: false},
- }
-
- for i, s := range tests {
- errs := validate.Field(s.Value, s.Tag)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
-
- errs = validate.Struct(s)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
-}
-
-func TestContainsAnyValidation(t *testing.T) {
-
- tests := []struct {
- Value string `validate:"containsany=@!{}[]"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "abcd@!jfk", Tag: "containsany=@!{}[]", ExpectedNil: true},
- {Value: "abcdefg", Tag: "containsany=@!{}[]", ExpectedNil: false},
- }
-
- for i, s := range tests {
- errs := validate.Field(s.Value, s.Tag)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
-
- errs = validate.Struct(s)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
-}
-
-func TestContainsValidation(t *testing.T) {
-
- tests := []struct {
- Value string `validate:"contains=@"`
- Tag string
- ExpectedNil bool
- }{
- {Value: "abcd@!jfk", Tag: "contains=@", ExpectedNil: true},
- {Value: "abcdq!jfk", Tag: "contains=@", ExpectedNil: false},
- }
-
- for i, s := range tests {
- errs := validate.Field(s.Value, s.Tag)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
-
- errs = validate.Struct(s)
-
- if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
- t.Fatalf("Index: %d failed Error: %s", i, errs)
- }
- }
-}
-
-func TestIsNeFieldValidation(t *testing.T) {
-
- var j uint64
- var k float64
- s := "abcd"
- i := 1
- j = 1
- k = 1.543
- arr := []string{"test"}
- now := time.Now().UTC()
-
- var j2 uint64
- var k2 float64
- s2 := "abcdef"
- i2 := 3
- j2 = 2
- k2 = 1.5434456
- arr2 := []string{"test", "test2"}
- arr3 := []string{"test"}
- now2 := now
-
- errs := validate.FieldWithValue(s, s2, "nefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(i2, i, "nefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(j2, j, "nefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(k2, k, "nefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(arr2, arr, "nefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(now2, now, "nefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "nefield")
-
- errs = validate.FieldWithValue(arr3, arr, "nefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "nefield")
-
- type Test struct {
- Start *time.Time `validate:"nefield=End"`
- End *time.Time
- }
-
- sv := &Test{
- Start: &now,
- End: &now,
- }
-
- errs = validate.Struct(sv)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Start", "Start", "nefield")
-
- now3 := time.Now().UTC()
-
- sv = &Test{
- Start: &now,
- End: &now3,
- }
-
- errs = validate.Struct(sv)
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(nil, 1, "nefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(sv, now, "nefield")
- Equal(t, errs, nil)
-
- type Test2 struct {
- Start *time.Time `validate:"nefield=NonExistantField"`
- End *time.Time
- }
-
- sv2 := &Test2{
- Start: &now,
- End: &now,
- }
-
- errs = validate.Struct(sv2)
- Equal(t, errs, nil)
-}
-
-func TestIsNeValidation(t *testing.T) {
-
- var j uint64
- var k float64
- s := "abcdef"
- i := 3
- j = 2
- k = 1.5434
- arr := []string{"test"}
- now := time.Now().UTC()
-
- errs := validate.Field(s, "ne=abcd")
- Equal(t, errs, nil)
-
- errs = validate.Field(i, "ne=1")
- Equal(t, errs, nil)
-
- errs = validate.Field(j, "ne=1")
- Equal(t, errs, nil)
-
- errs = validate.Field(k, "ne=1.543")
- Equal(t, errs, nil)
-
- errs = validate.Field(arr, "ne=2")
- Equal(t, errs, nil)
-
- errs = validate.Field(arr, "ne=1")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ne")
-
- PanicMatches(t, func() { validate.Field(now, "ne=now") }, "Bad field type time.Time")
-}
-
-func TestIsEqFieldValidation(t *testing.T) {
-
- var j uint64
- var k float64
- s := "abcd"
- i := 1
- j = 1
- k = 1.543
- arr := []string{"test"}
- now := time.Now().UTC()
-
- var j2 uint64
- var k2 float64
- s2 := "abcd"
- i2 := 1
- j2 = 1
- k2 = 1.543
- arr2 := []string{"test"}
- arr3 := []string{"test", "test2"}
- now2 := now
-
- errs := validate.FieldWithValue(s, s2, "eqfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(i2, i, "eqfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(j2, j, "eqfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(k2, k, "eqfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(arr2, arr, "eqfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(now2, now, "eqfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(arr3, arr, "eqfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "eqfield")
-
- type Test struct {
- Start *time.Time `validate:"eqfield=End"`
- End *time.Time
- }
-
- sv := &Test{
- Start: &now,
- End: &now,
- }
-
- errs = validate.Struct(sv)
- Equal(t, errs, nil)
-
- now3 := time.Now().UTC()
-
- sv = &Test{
- Start: &now,
- End: &now3,
- }
-
- errs = validate.Struct(sv)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Start", "Start", "eqfield")
-
- errs = validate.FieldWithValue(nil, 1, "eqfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "eqfield")
-
- channel := make(chan string)
- errs = validate.FieldWithValue(5, channel, "eqfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "eqfield")
-
- errs = validate.FieldWithValue(5, now, "eqfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "eqfield")
-
- type Test2 struct {
- Start *time.Time `validate:"eqfield=NonExistantField"`
- End *time.Time
- }
-
- sv2 := &Test2{
- Start: &now,
- End: &now,
- }
-
- errs = validate.Struct(sv2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test2.Start", "Start", "eqfield")
-
- type Inner struct {
- Name string
- }
-
- type TStruct struct {
- Inner *Inner
- CreatedAt *time.Time `validate:"eqfield=Inner"`
- }
-
- inner := &Inner{
- Name: "NAME",
- }
-
- test := &TStruct{
- Inner: inner,
- CreatedAt: &now,
- }
-
- errs = validate.Struct(test)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqfield")
-}
-
-func TestIsEqValidation(t *testing.T) {
-
- var j uint64
- var k float64
- s := "abcd"
- i := 1
- j = 1
- k = 1.543
- arr := []string{"test"}
- now := time.Now().UTC()
-
- errs := validate.Field(s, "eq=abcd")
- Equal(t, errs, nil)
-
- errs = validate.Field(i, "eq=1")
- Equal(t, errs, nil)
-
- errs = validate.Field(j, "eq=1")
- Equal(t, errs, nil)
-
- errs = validate.Field(k, "eq=1.543")
- Equal(t, errs, nil)
-
- errs = validate.Field(arr, "eq=1")
- Equal(t, errs, nil)
-
- errs = validate.Field(arr, "eq=2")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "eq")
-
- PanicMatches(t, func() { validate.Field(now, "eq=now") }, "Bad field type time.Time")
-}
-
-func TestBase64Validation(t *testing.T) {
-
- s := "dW5pY29ybg=="
-
- errs := validate.Field(s, "base64")
- Equal(t, errs, nil)
-
- s = "dGhpIGlzIGEgdGVzdCBiYXNlNjQ="
- errs = validate.Field(s, "base64")
- Equal(t, errs, nil)
-
- s = ""
- errs = validate.Field(s, "base64")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "base64")
-
- s = "dW5pY29ybg== foo bar"
- errs = validate.Field(s, "base64")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "base64")
-}
-
-func TestNoStructLevelValidation(t *testing.T) {
-
- type Inner struct {
- Test string `validate:"len=5"`
- }
-
- type Outer struct {
- InnerStruct *Inner `validate:"required,nostructlevel"`
- }
-
- outer := &Outer{
- InnerStruct: nil,
- }
-
- errs := validate.Struct(outer)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required")
-
- inner := &Inner{
- Test: "1234",
- }
-
- outer = &Outer{
- InnerStruct: inner,
- }
-
- errs = validate.Struct(outer)
- Equal(t, errs, nil)
-}
-
-func TestStructOnlyValidation(t *testing.T) {
-
- type Inner struct {
- Test string `validate:"len=5"`
- }
-
- type Outer struct {
- InnerStruct *Inner `validate:"required,structonly"`
- }
-
- outer := &Outer{
- InnerStruct: nil,
- }
-
- errs := validate.Struct(outer)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required")
-
- inner := &Inner{
- Test: "1234",
- }
-
- outer = &Outer{
- InnerStruct: inner,
- }
-
- errs = validate.Struct(outer)
- Equal(t, errs, nil)
-}
-
-func TestGtField(t *testing.T) {
-
- type TimeTest struct {
- Start *time.Time `validate:"required,gt"`
- End *time.Time `validate:"required,gt,gtfield=Start"`
- }
-
- now := time.Now()
- start := now.Add(time.Hour * 24)
- end := start.Add(time.Hour * 24)
-
- timeTest := &TimeTest{
- Start: &start,
- End: &end,
- }
-
- errs := validate.Struct(timeTest)
- Equal(t, errs, nil)
-
- timeTest = &TimeTest{
- Start: &end,
- End: &start,
- }
-
- errs = validate.Struct(timeTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest.End", "End", "gtfield")
-
- errs = validate.FieldWithValue(&start, &end, "gtfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(&end, &start, "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtfield")
-
- errs = validate.FieldWithValue(&timeTest, &end, "gtfield")
- NotEqual(t, errs, nil)
-
- errs = validate.FieldWithValue("test", "test bigger", "gtfield")
- Equal(t, errs, nil)
-
- type IntTest struct {
- Val1 int `validate:"required"`
- Val2 int `validate:"required,gtfield=Val1"`
- }
-
- intTest := &IntTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(intTest)
- Equal(t, errs, nil)
-
- intTest = &IntTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(intTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "IntTest.Val2", "Val2", "gtfield")
-
- errs = validate.FieldWithValue(int(1), int(5), "gtfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(int(5), int(1), "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtfield")
-
- type UIntTest struct {
- Val1 uint `validate:"required"`
- Val2 uint `validate:"required,gtfield=Val1"`
- }
-
- uIntTest := &UIntTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(uIntTest)
- Equal(t, errs, nil)
-
- uIntTest = &UIntTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(uIntTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "UIntTest.Val2", "Val2", "gtfield")
-
- errs = validate.FieldWithValue(uint(1), uint(5), "gtfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(uint(5), uint(1), "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtfield")
-
- type FloatTest struct {
- Val1 float64 `validate:"required"`
- Val2 float64 `validate:"required,gtfield=Val1"`
- }
-
- floatTest := &FloatTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(floatTest)
- Equal(t, errs, nil)
-
- floatTest = &FloatTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(floatTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "FloatTest.Val2", "Val2", "gtfield")
-
- errs = validate.FieldWithValue(float32(1), float32(5), "gtfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(float32(5), float32(1), "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtfield")
-
- errs = validate.FieldWithValue(nil, 1, "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtfield")
-
- errs = validate.FieldWithValue(5, "T", "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtfield")
-
- errs = validate.FieldWithValue(5, start, "gtfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtfield")
-
- type TimeTest2 struct {
- Start *time.Time `validate:"required"`
- End *time.Time `validate:"required,gtfield=NonExistantField"`
- }
-
- timeTest2 := &TimeTest2{
- Start: &start,
- End: &end,
- }
-
- errs = validate.Struct(timeTest2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest2.End", "End", "gtfield")
-}
-
-func TestLtField(t *testing.T) {
-
- type TimeTest struct {
- Start *time.Time `validate:"required,lt,ltfield=End"`
- End *time.Time `validate:"required,lt"`
- }
-
- now := time.Now()
- start := now.Add(time.Hour * 24 * -1 * 2)
- end := start.Add(time.Hour * 24)
-
- timeTest := &TimeTest{
- Start: &start,
- End: &end,
- }
-
- errs := validate.Struct(timeTest)
- Equal(t, errs, nil)
-
- timeTest = &TimeTest{
- Start: &end,
- End: &start,
- }
-
- errs = validate.Struct(timeTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest.Start", "Start", "ltfield")
-
- errs = validate.FieldWithValue(&end, &start, "ltfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(&start, &end, "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltfield")
-
- errs = validate.FieldWithValue(timeTest, &end, "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltfield")
-
- errs = validate.FieldWithValue("test", "tes", "ltfield")
- Equal(t, errs, nil)
-
- type IntTest struct {
- Val1 int `validate:"required"`
- Val2 int `validate:"required,ltfield=Val1"`
- }
-
- intTest := &IntTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(intTest)
- Equal(t, errs, nil)
-
- intTest = &IntTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(intTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "IntTest.Val2", "Val2", "ltfield")
-
- errs = validate.FieldWithValue(int(5), int(1), "ltfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(int(1), int(5), "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltfield")
-
- type UIntTest struct {
- Val1 uint `validate:"required"`
- Val2 uint `validate:"required,ltfield=Val1"`
- }
-
- uIntTest := &UIntTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(uIntTest)
- Equal(t, errs, nil)
-
- uIntTest = &UIntTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(uIntTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "UIntTest.Val2", "Val2", "ltfield")
-
- errs = validate.FieldWithValue(uint(5), uint(1), "ltfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(uint(1), uint(5), "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltfield")
-
- type FloatTest struct {
- Val1 float64 `validate:"required"`
- Val2 float64 `validate:"required,ltfield=Val1"`
- }
-
- floatTest := &FloatTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(floatTest)
- Equal(t, errs, nil)
-
- floatTest = &FloatTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(floatTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "FloatTest.Val2", "Val2", "ltfield")
-
- errs = validate.FieldWithValue(float32(5), float32(1), "ltfield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(float32(1), float32(5), "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltfield")
-
- errs = validate.FieldWithValue(nil, 5, "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltfield")
-
- errs = validate.FieldWithValue(1, "T", "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltfield")
-
- errs = validate.FieldWithValue(1, end, "ltfield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltfield")
-
- type TimeTest2 struct {
- Start *time.Time `validate:"required"`
- End *time.Time `validate:"required,ltfield=NonExistantField"`
- }
-
- timeTest2 := &TimeTest2{
- Start: &end,
- End: &start,
- }
-
- errs = validate.Struct(timeTest2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest2.End", "End", "ltfield")
-}
-
-func TestLteField(t *testing.T) {
-
- type TimeTest struct {
- Start *time.Time `validate:"required,lte,ltefield=End"`
- End *time.Time `validate:"required,lte"`
- }
-
- now := time.Now()
- start := now.Add(time.Hour * 24 * -1 * 2)
- end := start.Add(time.Hour * 24)
-
- timeTest := &TimeTest{
- Start: &start,
- End: &end,
- }
-
- errs := validate.Struct(timeTest)
- Equal(t, errs, nil)
-
- timeTest = &TimeTest{
- Start: &end,
- End: &start,
- }
-
- errs = validate.Struct(timeTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest.Start", "Start", "ltefield")
-
- errs = validate.FieldWithValue(&end, &start, "ltefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(&start, &end, "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltefield")
-
- errs = validate.FieldWithValue(timeTest, &end, "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltefield")
-
- errs = validate.FieldWithValue("test", "tes", "ltefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue("test", "test", "ltefield")
- Equal(t, errs, nil)
-
- type IntTest struct {
- Val1 int `validate:"required"`
- Val2 int `validate:"required,ltefield=Val1"`
- }
-
- intTest := &IntTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(intTest)
- Equal(t, errs, nil)
-
- intTest = &IntTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(intTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "IntTest.Val2", "Val2", "ltefield")
-
- errs = validate.FieldWithValue(int(5), int(1), "ltefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(int(1), int(5), "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltefield")
-
- type UIntTest struct {
- Val1 uint `validate:"required"`
- Val2 uint `validate:"required,ltefield=Val1"`
- }
-
- uIntTest := &UIntTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(uIntTest)
- Equal(t, errs, nil)
-
- uIntTest = &UIntTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(uIntTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "UIntTest.Val2", "Val2", "ltefield")
-
- errs = validate.FieldWithValue(uint(5), uint(1), "ltefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(uint(1), uint(5), "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltefield")
-
- type FloatTest struct {
- Val1 float64 `validate:"required"`
- Val2 float64 `validate:"required,ltefield=Val1"`
- }
-
- floatTest := &FloatTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(floatTest)
- Equal(t, errs, nil)
-
- floatTest = &FloatTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(floatTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "FloatTest.Val2", "Val2", "ltefield")
-
- errs = validate.FieldWithValue(float32(5), float32(1), "ltefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(float32(1), float32(5), "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltefield")
-
- errs = validate.FieldWithValue(nil, 5, "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltefield")
-
- errs = validate.FieldWithValue(1, "T", "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltefield")
-
- errs = validate.FieldWithValue(1, end, "ltefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "ltefield")
-
- type TimeTest2 struct {
- Start *time.Time `validate:"required"`
- End *time.Time `validate:"required,ltefield=NonExistantField"`
- }
-
- timeTest2 := &TimeTest2{
- Start: &end,
- End: &start,
- }
-
- errs = validate.Struct(timeTest2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest2.End", "End", "ltefield")
-}
-
-func TestGteField(t *testing.T) {
-
- type TimeTest struct {
- Start *time.Time `validate:"required,gte"`
- End *time.Time `validate:"required,gte,gtefield=Start"`
- }
-
- now := time.Now()
- start := now.Add(time.Hour * 24)
- end := start.Add(time.Hour * 24)
-
- timeTest := &TimeTest{
- Start: &start,
- End: &end,
- }
-
- errs := validate.Struct(timeTest)
- Equal(t, errs, nil)
-
- timeTest = &TimeTest{
- Start: &end,
- End: &start,
- }
-
- errs = validate.Struct(timeTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest.End", "End", "gtefield")
-
- errs = validate.FieldWithValue(&start, &end, "gtefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(&end, &start, "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtefield")
-
- errs = validate.FieldWithValue(timeTest, &start, "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtefield")
-
- errs = validate.FieldWithValue("test", "test", "gtefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue("test", "test bigger", "gtefield")
- Equal(t, errs, nil)
-
- type IntTest struct {
- Val1 int `validate:"required"`
- Val2 int `validate:"required,gtefield=Val1"`
- }
-
- intTest := &IntTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(intTest)
- Equal(t, errs, nil)
-
- intTest = &IntTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(intTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "IntTest.Val2", "Val2", "gtefield")
-
- errs = validate.FieldWithValue(int(1), int(5), "gtefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(int(5), int(1), "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtefield")
-
- type UIntTest struct {
- Val1 uint `validate:"required"`
- Val2 uint `validate:"required,gtefield=Val1"`
- }
-
- uIntTest := &UIntTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(uIntTest)
- Equal(t, errs, nil)
-
- uIntTest = &UIntTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(uIntTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "UIntTest.Val2", "Val2", "gtefield")
-
- errs = validate.FieldWithValue(uint(1), uint(5), "gtefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(uint(5), uint(1), "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtefield")
-
- type FloatTest struct {
- Val1 float64 `validate:"required"`
- Val2 float64 `validate:"required,gtefield=Val1"`
- }
-
- floatTest := &FloatTest{
- Val1: 1,
- Val2: 5,
- }
-
- errs = validate.Struct(floatTest)
- Equal(t, errs, nil)
-
- floatTest = &FloatTest{
- Val1: 5,
- Val2: 1,
- }
-
- errs = validate.Struct(floatTest)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "FloatTest.Val2", "Val2", "gtefield")
-
- errs = validate.FieldWithValue(float32(1), float32(5), "gtefield")
- Equal(t, errs, nil)
-
- errs = validate.FieldWithValue(float32(5), float32(1), "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtefield")
-
- errs = validate.FieldWithValue(nil, 1, "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtefield")
-
- errs = validate.FieldWithValue(5, "T", "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtefield")
-
- errs = validate.FieldWithValue(5, start, "gtefield")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gtefield")
-
- type TimeTest2 struct {
- Start *time.Time `validate:"required"`
- End *time.Time `validate:"required,gtefield=NonExistantField"`
- }
-
- timeTest2 := &TimeTest2{
- Start: &start,
- End: &end,
- }
-
- errs = validate.Struct(timeTest2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TimeTest2.End", "End", "gtefield")
-}
-
-func TestValidateByTagAndValue(t *testing.T) {
-
- val := "test"
- field := "test"
- errs := validate.FieldWithValue(val, field, "required")
- Equal(t, errs, nil)
-
- fn := func(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
-
- return current.String() == field.String()
- }
-
- validate.RegisterValidation("isequaltestfunc", fn)
-
- errs = validate.FieldWithValue(val, field, "isequaltestfunc")
- Equal(t, errs, nil)
-
- val = "unequal"
-
- errs = validate.FieldWithValue(val, field, "isequaltestfunc")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "isequaltestfunc")
-}
-
-func TestAddFunctions(t *testing.T) {
-
- fn := func(v *Validate, topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
-
- return true
- }
-
- config := &Config{
- TagName: "validateme",
- }
-
- validate := New(config)
-
- errs := validate.RegisterValidation("new", fn)
- Equal(t, errs, nil)
-
- errs = validate.RegisterValidation("", fn)
- NotEqual(t, errs, nil)
-
- validate.RegisterValidation("new", nil)
- NotEqual(t, errs, nil)
-
- errs = validate.RegisterValidation("new", fn)
- Equal(t, errs, nil)
-
- PanicMatches(t, func() { validate.RegisterValidation("dive", fn) }, "Tag 'dive' either contains restricted characters or is the same as a restricted tag needed for normal operation")
-}
-
-func TestChangeTag(t *testing.T) {
-
- config := &Config{
- TagName: "val",
- }
- validate := New(config)
-
- type Test struct {
- Name string `val:"len=4"`
- }
- s := &Test{
- Name: "TEST",
- }
-
- errs := validate.Struct(s)
- Equal(t, errs, nil)
-}
-
-func TestUnexposedStruct(t *testing.T) {
-
- type Test struct {
- Name string
- unexposed struct {
- A string `validate:"required"`
- }
- }
-
- s := &Test{
- Name: "TEST",
- }
-
- errs := validate.Struct(s)
- Equal(t, errs, nil)
-}
-
-func TestBadParams(t *testing.T) {
-
- i := 1
- errs := validate.Field(i, "-")
- Equal(t, errs, nil)
-
- PanicMatches(t, func() { validate.Field(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
- PanicMatches(t, func() { validate.Field(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
-
- var ui uint = 1
- PanicMatches(t, func() { validate.Field(ui, "len=a") }, "strconv.ParseUint: parsing \"a\": invalid syntax")
-
- f := 1.23
- PanicMatches(t, func() { validate.Field(f, "len=a") }, "strconv.ParseFloat: parsing \"a\": invalid syntax")
-}
-
-func TestLength(t *testing.T) {
-
- i := true
- PanicMatches(t, func() { validate.Field(i, "len") }, "Bad field type bool")
-}
-
-func TestIsGt(t *testing.T) {
-
- myMap := map[string]string{}
- errs := validate.Field(myMap, "gt=0")
- NotEqual(t, errs, nil)
-
- f := 1.23
- errs = validate.Field(f, "gt=5")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gt")
-
- var ui uint = 5
- errs = validate.Field(ui, "gt=10")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gt")
-
- i := true
- PanicMatches(t, func() { validate.Field(i, "gt") }, "Bad field type bool")
-
- tm := time.Now().UTC()
- tm = tm.Add(time.Hour * 24)
-
- errs = validate.Field(tm, "gt")
- Equal(t, errs, nil)
-
- t2 := time.Now().UTC()
-
- errs = validate.Field(t2, "gt")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gt")
-
- type Test struct {
- Now *time.Time `validate:"gt"`
- }
- s := &Test{
- Now: &tm,
- }
-
- errs = validate.Struct(s)
- Equal(t, errs, nil)
-
- s = &Test{
- Now: &t2,
- }
-
- errs = validate.Struct(s)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Now", "Now", "gt")
-}
-
-func TestIsGte(t *testing.T) {
-
- i := true
- PanicMatches(t, func() { validate.Field(i, "gte") }, "Bad field type bool")
-
- t1 := time.Now().UTC()
- t1 = t1.Add(time.Hour * 24)
-
- errs := validate.Field(t1, "gte")
- Equal(t, errs, nil)
-
- t2 := time.Now().UTC()
-
- errs = validate.Field(t2, "gte")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "gte")
-
- type Test struct {
- Now *time.Time `validate:"gte"`
- }
- s := &Test{
- Now: &t1,
- }
-
- errs = validate.Struct(s)
- Equal(t, errs, nil)
-
- s = &Test{
- Now: &t2,
- }
-
- errs = validate.Struct(s)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Now", "Now", "gte")
-}
-
-func TestIsLt(t *testing.T) {
-
- myMap := map[string]string{}
- errs := validate.Field(myMap, "lt=0")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "lt")
-
- f := 1.23
- errs = validate.Field(f, "lt=0")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "lt")
-
- var ui uint = 5
- errs = validate.Field(ui, "lt=0")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "lt")
-
- i := true
- PanicMatches(t, func() { validate.Field(i, "lt") }, "Bad field type bool")
-
- t1 := time.Now().UTC()
-
- errs = validate.Field(t1, "lt")
- Equal(t, errs, nil)
-
- t2 := time.Now().UTC()
- t2 = t2.Add(time.Hour * 24)
-
- errs = validate.Field(t2, "lt")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "lt")
-
- type Test struct {
- Now *time.Time `validate:"lt"`
- }
-
- s := &Test{
- Now: &t1,
- }
-
- errs = validate.Struct(s)
- Equal(t, errs, nil)
-
- s = &Test{
- Now: &t2,
- }
-
- errs = validate.Struct(s)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.Now", "Now", "lt")
-}
-
-func TestIsLte(t *testing.T) {
-
- i := true
- PanicMatches(t, func() { validate.Field(i, "lte") }, "Bad field type bool")
-
- t1 := time.Now().UTC()
-
- errs := validate.Field(t1, "lte")
- Equal(t, errs, nil)
-
- t2 := time.Now().UTC()
- t2 = t2.Add(time.Hour * 24)
-
- errs = validate.Field(t2, "lte")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "lte")
-
- type Test struct {
- Now *time.Time `validate:"lte"`
- }
-
- s := &Test{
- Now: &t1,
- }
-
- errs = validate.Struct(s)
- Equal(t, errs, nil)
-
- s = &Test{
- Now: &t2,
- }
-
- errs = validate.Struct(s)
- NotEqual(t, errs, nil)
-}
-
-func TestUrl(t *testing.T) {
-
- var tests = []struct {
- param string
- expected bool
- }{
- {"http://foo.bar#com", true},
- {"http://foobar.com", true},
- {"https://foobar.com", true},
- {"foobar.com", false},
- {"http://foobar.coffee/", true},
- {"http://foobar.中文网/", true},
- {"http://foobar.org/", true},
- {"http://foobar.org:8080/", true},
- {"ftp://foobar.ru/", true},
- {"http://user:pass@www.foobar.com/", true},
- {"http://127.0.0.1/", true},
- {"http://duckduckgo.com/?q=%2F", true},
- {"http://localhost:3000/", true},
- {"http://foobar.com/?foo=bar#baz=qux", true},
- {"http://foobar.com?foo=bar", true},
- {"http://www.xn--froschgrn-x9a.net/", true},
- {"", false},
- {"xyz://foobar.com", true},
- {"invalid.", false},
- {".com", false},
- {"rtmp://foobar.com", true},
- {"http://www.foo_bar.com/", true},
- {"http://localhost:3000/", true},
- {"http://foobar.com/#baz", true},
- {"http://foobar.com#baz=qux", true},
- {"http://foobar.com/t$-_.+!*\\'(),", true},
- {"http://www.foobar.com/~foobar", true},
- {"http://www.-foobar.com/", true},
- {"http://www.foo---bar.com/", true},
- {"mailto:someone@example.com", true},
- {"irc://irc.server.org/channel", true},
- {"irc://#channel@network", true},
- {"/abs/test/dir", false},
- {"./rel/test/dir", false},
- }
- for i, test := range tests {
-
- errs := validate.Field(test.param, "url")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d URL failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d URL failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "url" {
- t.Fatalf("Index: %d URL failed Error: %s", i, errs)
- }
- }
- }
- }
-
- i := 1
- PanicMatches(t, func() { validate.Field(i, "url") }, "Bad field type int")
-}
-
-func TestUri(t *testing.T) {
-
- var tests = []struct {
- param string
- expected bool
- }{
- {"http://foo.bar#com", true},
- {"http://foobar.com", true},
- {"https://foobar.com", true},
- {"foobar.com", false},
- {"http://foobar.coffee/", true},
- {"http://foobar.中文网/", true},
- {"http://foobar.org/", true},
- {"http://foobar.org:8080/", true},
- {"ftp://foobar.ru/", true},
- {"http://user:pass@www.foobar.com/", true},
- {"http://127.0.0.1/", true},
- {"http://duckduckgo.com/?q=%2F", true},
- {"http://localhost:3000/", true},
- {"http://foobar.com/?foo=bar#baz=qux", true},
- {"http://foobar.com?foo=bar", true},
- {"http://www.xn--froschgrn-x9a.net/", true},
- {"", false},
- {"xyz://foobar.com", true},
- {"invalid.", false},
- {".com", false},
- {"rtmp://foobar.com", true},
- {"http://www.foo_bar.com/", true},
- {"http://localhost:3000/", true},
- {"http://foobar.com#baz=qux", true},
- {"http://foobar.com/t$-_.+!*\\'(),", true},
- {"http://www.foobar.com/~foobar", true},
- {"http://www.-foobar.com/", true},
- {"http://www.foo---bar.com/", true},
- {"mailto:someone@example.com", true},
- {"irc://irc.server.org/channel", true},
- {"irc://#channel@network", true},
- {"/abs/test/dir", true},
- {"./rel/test/dir", false},
- }
- for i, test := range tests {
-
- errs := validate.Field(test.param, "uri")
-
- if test.expected {
- if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d URI failed Error: %s", i, errs)
- }
- } else {
- if IsEqual(errs, nil) {
- t.Fatalf("Index: %d URI failed Error: %s", i, errs)
- } else {
- val := errs.(ValidationErrors)[""]
- if val.Tag != "uri" {
- t.Fatalf("Index: %d URI failed Error: %s", i, errs)
- }
- }
- }
- }
-
- i := 1
- PanicMatches(t, func() { validate.Field(i, "uri") }, "Bad field type int")
-}
-
-func TestOrTag(t *testing.T) {
- s := "rgba(0,31,255,0.5)"
- errs := validate.Field(s, "rgb|rgba")
- Equal(t, errs, nil)
-
- s = "rgba(0,31,255,0.5)"
- errs = validate.Field(s, "rgb|rgba|len=18")
- Equal(t, errs, nil)
-
- s = "this ain't right"
- errs = validate.Field(s, "rgb|rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgb|rgba")
-
- s = "this ain't right"
- errs = validate.Field(s, "rgb|rgba|len=10")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgb|rgba|len")
-
- s = "this is right"
- errs = validate.Field(s, "rgb|rgba|len=13")
- Equal(t, errs, nil)
-
- s = ""
- errs = validate.Field(s, "omitempty,rgb|rgba")
- Equal(t, errs, nil)
-
- s = "this is right, but a blank or isn't"
-
- PanicMatches(t, func() { validate.Field(s, "rgb||len=13") }, "Invalid validation tag on field")
- PanicMatches(t, func() { validate.Field(s, "rgb|rgbaa|len=13") }, "Undefined validation function on field")
-}
-
-func TestHsla(t *testing.T) {
-
- s := "hsla(360,100%,100%,1)"
- errs := validate.Field(s, "hsla")
- Equal(t, errs, nil)
-
- s = "hsla(360,100%,100%,0.5)"
- errs = validate.Field(s, "hsla")
- Equal(t, errs, nil)
-
- s = "hsla(0,0%,0%, 0)"
- errs = validate.Field(s, "hsla")
- Equal(t, errs, nil)
-
- s = "hsl(361,100%,50%,1)"
- errs = validate.Field(s, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hsla")
-
- s = "hsl(361,100%,50%)"
- errs = validate.Field(s, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hsla")
-
- s = "hsla(361,100%,50%)"
- errs = validate.Field(s, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hsla")
-
- s = "hsla(360,101%,50%)"
- errs = validate.Field(s, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hsla")
-
- s = "hsla(360,100%,101%)"
- errs = validate.Field(s, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hsla")
-
- i := 1
- validate.Field(i, "hsla")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hsla")
-}
-
-func TestHsl(t *testing.T) {
-
- s := "hsl(360,100%,50%)"
- errs := validate.Field(s, "hsl")
- Equal(t, errs, nil)
-
- s = "hsl(0,0%,0%)"
- errs = validate.Field(s, "hsl")
- Equal(t, errs, nil)
-
- s = "hsl(361,100%,50%)"
- errs = validate.Field(s, "hsl")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hsl")
-
- s = "hsl(361,101%,50%)"
- errs = validate.Field(s, "hsl")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hsl")
-
- s = "hsl(361,100%,101%)"
- errs = validate.Field(s, "hsl")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hsl")
+// errs = validate.Field(t2, "gt")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gt")
- s = "hsl(-10,100%,100%)"
- errs = validate.Field(s, "hsl")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hsl")
-
- i := 1
- errs = validate.Field(i, "hsl")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hsl")
-}
-
-func TestRgba(t *testing.T) {
-
- s := "rgba(0,31,255,0.5)"
- errs := validate.Field(s, "rgba")
- Equal(t, errs, nil)
-
- s = "rgba(0,31,255,0.12)"
- errs = validate.Field(s, "rgba")
- Equal(t, errs, nil)
-
- s = "rgba(12%,55%,100%,0.12)"
- errs = validate.Field(s, "rgba")
- Equal(t, errs, nil)
-
- s = "rgba( 0, 31, 255, 0.5)"
- errs = validate.Field(s, "rgba")
- Equal(t, errs, nil)
-
- s = "rgba(12%,55,100%,0.12)"
- errs = validate.Field(s, "rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgba")
-
- s = "rgb(0, 31, 255)"
- errs = validate.Field(s, "rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgba")
-
- s = "rgb(1,349,275,0.5)"
- errs = validate.Field(s, "rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgba")
-
- s = "rgb(01,31,255,0.5)"
- errs = validate.Field(s, "rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgba")
-
- i := 1
- errs = validate.Field(i, "rgba")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgba")
-}
-
-func TestRgb(t *testing.T) {
-
- s := "rgb(0,31,255)"
- errs := validate.Field(s, "rgb")
- Equal(t, errs, nil)
-
- s = "rgb(0, 31, 255)"
- errs = validate.Field(s, "rgb")
- Equal(t, errs, nil)
-
- s = "rgb(10%, 50%, 100%)"
- errs = validate.Field(s, "rgb")
- Equal(t, errs, nil)
-
- s = "rgb(10%, 50%, 55)"
- errs = validate.Field(s, "rgb")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgb")
-
- s = "rgb(1,349,275)"
- errs = validate.Field(s, "rgb")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgb")
-
- s = "rgb(01,31,255)"
- errs = validate.Field(s, "rgb")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgb")
-
- s = "rgba(0,31,255)"
- errs = validate.Field(s, "rgb")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgb")
-
- i := 1
- errs = validate.Field(i, "rgb")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "rgb")
-}
-
-func TestEmail(t *testing.T) {
-
- s := "test@mail.com"
- errs := validate.Field(s, "email")
- Equal(t, errs, nil)
-
- s = "Dörte@Sörensen.example.com"
- errs = validate.Field(s, "email")
- Equal(t, errs, nil)
-
- s = "θσερ@εχαμπλε.ψομ"
- errs = validate.Field(s, "email")
- Equal(t, errs, nil)
-
- s = "юзер@екзампл.ком"
- errs = validate.Field(s, "email")
- Equal(t, errs, nil)
-
- s = "उपयोगकर्ता@उदाहरण.कॉम"
- errs = validate.Field(s, "email")
- Equal(t, errs, nil)
-
- s = "用户@例子.广告"
- errs = validate.Field(s, "email")
- Equal(t, errs, nil)
-
- s = ""
- errs = validate.Field(s, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "email")
-
- s = "test@email"
- errs = validate.Field(s, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "email")
-
- s = "test@email."
- errs = validate.Field(s, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "email")
-
- s = "@email.com"
- errs = validate.Field(s, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "email")
-
- i := true
- errs = validate.Field(i, "email")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "email")
-}
-
-func TestHexColor(t *testing.T) {
-
- s := "#fff"
- errs := validate.Field(s, "hexcolor")
- Equal(t, errs, nil)
-
- s = "#c2c2c2"
- errs = validate.Field(s, "hexcolor")
- Equal(t, errs, nil)
-
- s = "fff"
- errs = validate.Field(s, "hexcolor")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hexcolor")
-
- s = "fffFF"
- errs = validate.Field(s, "hexcolor")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hexcolor")
-
- i := true
- errs = validate.Field(i, "hexcolor")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hexcolor")
-}
-
-func TestHexadecimal(t *testing.T) {
-
- s := "ff0044"
- errs := validate.Field(s, "hexadecimal")
- Equal(t, errs, nil)
-
- s = "abcdefg"
- errs = validate.Field(s, "hexadecimal")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hexadecimal")
-
- i := true
- errs = validate.Field(i, "hexadecimal")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "hexadecimal")
-}
-
-func TestNumber(t *testing.T) {
-
- s := "1"
- errs := validate.Field(s, "number")
- Equal(t, errs, nil)
-
- s = "+1"
- errs = validate.Field(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "number")
-
- s = "-1"
- errs = validate.Field(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "number")
-
- s = "1.12"
- errs = validate.Field(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "number")
-
- s = "+1.12"
- errs = validate.Field(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "number")
-
- s = "-1.12"
- errs = validate.Field(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "number")
-
- s = "1."
- errs = validate.Field(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "number")
-
- s = "1.o"
- errs = validate.Field(s, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "number")
-
- i := 1
- errs = validate.Field(i, "number")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "number")
-}
-
-func TestNumeric(t *testing.T) {
-
- s := "1"
- errs := validate.Field(s, "numeric")
- Equal(t, errs, nil)
-
- s = "+1"
- errs = validate.Field(s, "numeric")
- Equal(t, errs, nil)
-
- s = "-1"
- errs = validate.Field(s, "numeric")
- Equal(t, errs, nil)
-
- s = "1.12"
- errs = validate.Field(s, "numeric")
- Equal(t, errs, nil)
+// type Test struct {
+// Now *time.Time `validate:"gt"`
+// }
+// s := &Test{
+// Now: &tm,
+// }
- s = "+1.12"
- errs = validate.Field(s, "numeric")
- Equal(t, errs, nil)
+// errs = validate.Struct(s)
+// Equal(t, errs, nil)
- s = "-1.12"
- errs = validate.Field(s, "numeric")
- Equal(t, errs, nil)
+// s = &Test{
+// Now: &t2,
+// }
- s = "1."
- errs = validate.Field(s, "numeric")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "numeric")
+// errs = validate.Struct(s)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.Now", "Now", "gt")
+// }
- s = "1.o"
- errs = validate.Field(s, "numeric")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "numeric")
+// func TestIsGte(t *testing.T) {
- i := 1
- errs = validate.Field(i, "numeric")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "numeric")
-}
+// i := true
+// PanicMatches(t, func() { validate.Field(i, "gte") }, "Bad field type bool")
-func TestAlphaNumeric(t *testing.T) {
+// t1 := time.Now().UTC()
+// t1 = t1.Add(time.Hour * 24)
- s := "abcd123"
- errs := validate.Field(s, "alphanum")
- Equal(t, errs, nil)
+// errs := validate.Field(t1, "gte")
+// Equal(t, errs, nil)
- s = "abc!23"
- errs = validate.Field(s, "alphanum")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "alphanum")
+// t2 := time.Now().UTC()
- errs = validate.Field(1, "alphanum")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "alphanum")
-}
+// errs = validate.Field(t2, "gte")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "gte")
-func TestAlpha(t *testing.T) {
+// type Test struct {
+// Now *time.Time `validate:"gte"`
+// }
+// s := &Test{
+// Now: &t1,
+// }
- s := "abcd"
- errs := validate.Field(s, "alpha")
- Equal(t, errs, nil)
+// errs = validate.Struct(s)
+// Equal(t, errs, nil)
- s = "abc®"
- errs = validate.Field(s, "alpha")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "alpha")
+// s = &Test{
+// Now: &t2,
+// }
- s = "abc÷"
- errs = validate.Field(s, "alpha")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "alpha")
+// errs = validate.Struct(s)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.Now", "Now", "gte")
+// }
- s = "abc1"
- errs = validate.Field(s, "alpha")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "alpha")
+// func TestIsLt(t *testing.T) {
- errs = validate.Field(1, "alpha")
- NotEqual(t, errs, nil)
- AssertError(t, errs, "", "", "alpha")
+// myMap := map[string]string{}
+// errs := validate.Field(myMap, "lt=0")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "lt")
-}
+// f := 1.23
+// errs = validate.Field(f, "lt=0")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "lt")
-func TestStructStringValidation(t *testing.T) {
-
- tSuccess := &TestString{
- Required: "Required",
- Len: "length==10",
- Min: "min=1",
- Max: "1234567890",
- MinMax: "12345",
- Lt: "012345678",
- Lte: "0123456789",
- Gt: "01234567890",
- Gte: "0123456789",
- OmitEmpty: "",
- Sub: &SubTest{
- Test: "1",
- },
- SubIgnore: &SubTest{
- Test: "",
- },
- Anonymous: struct {
- A string `validate:"required"`
- }{
- A: "1",
- },
- Iface: &Impl{
- F: "123",
- },
- }
+// var ui uint = 5
+// errs = validate.Field(ui, "lt=0")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "lt")
+
+// i := true
+// PanicMatches(t, func() { validate.Field(i, "lt") }, "Bad field type bool")
+
+// t1 := time.Now().UTC()
+
+// errs = validate.Field(t1, "lt")
+// Equal(t, errs, nil)
+
+// t2 := time.Now().UTC()
+// t2 = t2.Add(time.Hour * 24)
+
+// errs = validate.Field(t2, "lt")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "lt")
+
+// type Test struct {
+// Now *time.Time `validate:"lt"`
+// }
+
+// s := &Test{
+// Now: &t1,
+// }
+
+// errs = validate.Struct(s)
+// Equal(t, errs, nil)
+
+// s = &Test{
+// Now: &t2,
+// }
+
+// errs = validate.Struct(s)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.Now", "Now", "lt")
+// }
+
+// func TestIsLte(t *testing.T) {
+
+// i := true
+// PanicMatches(t, func() { validate.Field(i, "lte") }, "Bad field type bool")
+
+// t1 := time.Now().UTC()
+
+// errs := validate.Field(t1, "lte")
+// Equal(t, errs, nil)
+
+// t2 := time.Now().UTC()
+// t2 = t2.Add(time.Hour * 24)
+
+// errs = validate.Field(t2, "lte")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "lte")
+
+// type Test struct {
+// Now *time.Time `validate:"lte"`
+// }
+
+// s := &Test{
+// Now: &t1,
+// }
+
+// errs = validate.Struct(s)
+// Equal(t, errs, nil)
+
+// s = &Test{
+// Now: &t2,
+// }
+
+// errs = validate.Struct(s)
+// NotEqual(t, errs, nil)
+// }
+
+// func TestUrl(t *testing.T) {
+
+// var tests = []struct {
+// param string
+// expected bool
+// }{
+// {"http://foo.bar#com", true},
+// {"http://foobar.com", true},
+// {"https://foobar.com", true},
+// {"foobar.com", false},
+// {"http://foobar.coffee/", true},
+// {"http://foobar.中文网/", true},
+// {"http://foobar.org/", true},
+// {"http://foobar.org:8080/", true},
+// {"ftp://foobar.ru/", true},
+// {"http://user:pass@www.foobar.com/", true},
+// {"http://127.0.0.1/", true},
+// {"http://duckduckgo.com/?q=%2F", true},
+// {"http://localhost:3000/", true},
+// {"http://foobar.com/?foo=bar#baz=qux", true},
+// {"http://foobar.com?foo=bar", true},
+// {"http://www.xn--froschgrn-x9a.net/", true},
+// {"", false},
+// {"xyz://foobar.com", true},
+// {"invalid.", false},
+// {".com", false},
+// {"rtmp://foobar.com", true},
+// {"http://www.foo_bar.com/", true},
+// {"http://localhost:3000/", true},
+// {"http://foobar.com/#baz", true},
+// {"http://foobar.com#baz=qux", true},
+// {"http://foobar.com/t$-_.+!*\\'(),", true},
+// {"http://www.foobar.com/~foobar", true},
+// {"http://www.-foobar.com/", true},
+// {"http://www.foo---bar.com/", true},
+// {"mailto:someone@example.com", true},
+// {"irc://irc.server.org/channel", true},
+// {"irc://#channel@network", true},
+// {"/abs/test/dir", false},
+// {"./rel/test/dir", false},
+// }
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "url")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d URL failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d URL failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "url" {
+// t.Fatalf("Index: %d URL failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+
+// i := 1
+// PanicMatches(t, func() { validate.Field(i, "url") }, "Bad field type int")
+// }
+
+// func TestUri(t *testing.T) {
+
+// var tests = []struct {
+// param string
+// expected bool
+// }{
+// {"http://foo.bar#com", true},
+// {"http://foobar.com", true},
+// {"https://foobar.com", true},
+// {"foobar.com", false},
+// {"http://foobar.coffee/", true},
+// {"http://foobar.中文网/", true},
+// {"http://foobar.org/", true},
+// {"http://foobar.org:8080/", true},
+// {"ftp://foobar.ru/", true},
+// {"http://user:pass@www.foobar.com/", true},
+// {"http://127.0.0.1/", true},
+// {"http://duckduckgo.com/?q=%2F", true},
+// {"http://localhost:3000/", true},
+// {"http://foobar.com/?foo=bar#baz=qux", true},
+// {"http://foobar.com?foo=bar", true},
+// {"http://www.xn--froschgrn-x9a.net/", true},
+// {"", false},
+// {"xyz://foobar.com", true},
+// {"invalid.", false},
+// {".com", false},
+// {"rtmp://foobar.com", true},
+// {"http://www.foo_bar.com/", true},
+// {"http://localhost:3000/", true},
+// {"http://foobar.com#baz=qux", true},
+// {"http://foobar.com/t$-_.+!*\\'(),", true},
+// {"http://www.foobar.com/~foobar", true},
+// {"http://www.-foobar.com/", true},
+// {"http://www.foo---bar.com/", true},
+// {"mailto:someone@example.com", true},
+// {"irc://irc.server.org/channel", true},
+// {"irc://#channel@network", true},
+// {"/abs/test/dir", true},
+// {"./rel/test/dir", false},
+// }
+// for i, test := range tests {
+
+// errs := validate.Field(test.param, "uri")
+
+// if test.expected {
+// if !IsEqual(errs, nil) {
+// t.Fatalf("Index: %d URI failed Error: %s", i, errs)
+// }
+// } else {
+// if IsEqual(errs, nil) {
+// t.Fatalf("Index: %d URI failed Error: %s", i, errs)
+// } else {
+// val := errs.(ValidationErrors)[""]
+// if val.Tag != "uri" {
+// t.Fatalf("Index: %d URI failed Error: %s", i, errs)
+// }
+// }
+// }
+// }
+
+// i := 1
+// PanicMatches(t, func() { validate.Field(i, "uri") }, "Bad field type int")
+// }
+
+// func TestOrTag(t *testing.T) {
+// s := "rgba(0,31,255,0.5)"
+// errs := validate.Field(s, "rgb|rgba")
+// Equal(t, errs, nil)
+
+// s = "rgba(0,31,255,0.5)"
+// errs = validate.Field(s, "rgb|rgba|len=18")
+// Equal(t, errs, nil)
+
+// s = "this ain't right"
+// errs = validate.Field(s, "rgb|rgba")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgb|rgba")
+
+// s = "this ain't right"
+// errs = validate.Field(s, "rgb|rgba|len=10")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgb|rgba|len")
+
+// s = "this is right"
+// errs = validate.Field(s, "rgb|rgba|len=13")
+// Equal(t, errs, nil)
+
+// s = ""
+// errs = validate.Field(s, "omitempty,rgb|rgba")
+// Equal(t, errs, nil)
+
+// s = "this is right, but a blank or isn't"
+
+// PanicMatches(t, func() { validate.Field(s, "rgb||len=13") }, "Invalid validation tag on field")
+// PanicMatches(t, func() { validate.Field(s, "rgb|rgbaa|len=13") }, "Undefined validation function on field")
+// }
+
+// func TestHsla(t *testing.T) {
+
+// s := "hsla(360,100%,100%,1)"
+// errs := validate.Field(s, "hsla")
+// Equal(t, errs, nil)
+
+// s = "hsla(360,100%,100%,0.5)"
+// errs = validate.Field(s, "hsla")
+// Equal(t, errs, nil)
+
+// s = "hsla(0,0%,0%, 0)"
+// errs = validate.Field(s, "hsla")
+// Equal(t, errs, nil)
+
+// s = "hsl(361,100%,50%,1)"
+// errs = validate.Field(s, "hsla")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hsla")
+
+// s = "hsl(361,100%,50%)"
+// errs = validate.Field(s, "hsla")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hsla")
+
+// s = "hsla(361,100%,50%)"
+// errs = validate.Field(s, "hsla")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hsla")
+
+// s = "hsla(360,101%,50%)"
+// errs = validate.Field(s, "hsla")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hsla")
+
+// s = "hsla(360,100%,101%)"
+// errs = validate.Field(s, "hsla")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hsla")
+
+// i := 1
+// validate.Field(i, "hsla")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hsla")
+// }
+
+// func TestHsl(t *testing.T) {
+
+// s := "hsl(360,100%,50%)"
+// errs := validate.Field(s, "hsl")
+// Equal(t, errs, nil)
+
+// s = "hsl(0,0%,0%)"
+// errs = validate.Field(s, "hsl")
+// Equal(t, errs, nil)
+
+// s = "hsl(361,100%,50%)"
+// errs = validate.Field(s, "hsl")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hsl")
+
+// s = "hsl(361,101%,50%)"
+// errs = validate.Field(s, "hsl")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hsl")
+
+// s = "hsl(361,100%,101%)"
+// errs = validate.Field(s, "hsl")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hsl")
+
+// s = "hsl(-10,100%,100%)"
+// errs = validate.Field(s, "hsl")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hsl")
+
+// i := 1
+// errs = validate.Field(i, "hsl")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hsl")
+// }
+
+// func TestRgba(t *testing.T) {
+
+// s := "rgba(0,31,255,0.5)"
+// errs := validate.Field(s, "rgba")
+// Equal(t, errs, nil)
+
+// s = "rgba(0,31,255,0.12)"
+// errs = validate.Field(s, "rgba")
+// Equal(t, errs, nil)
+
+// s = "rgba(12%,55%,100%,0.12)"
+// errs = validate.Field(s, "rgba")
+// Equal(t, errs, nil)
+
+// s = "rgba( 0, 31, 255, 0.5)"
+// errs = validate.Field(s, "rgba")
+// Equal(t, errs, nil)
+
+// s = "rgba(12%,55,100%,0.12)"
+// errs = validate.Field(s, "rgba")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgba")
+
+// s = "rgb(0, 31, 255)"
+// errs = validate.Field(s, "rgba")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgba")
+
+// s = "rgb(1,349,275,0.5)"
+// errs = validate.Field(s, "rgba")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgba")
+
+// s = "rgb(01,31,255,0.5)"
+// errs = validate.Field(s, "rgba")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgba")
+
+// i := 1
+// errs = validate.Field(i, "rgba")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgba")
+// }
+
+// func TestRgb(t *testing.T) {
+
+// s := "rgb(0,31,255)"
+// errs := validate.Field(s, "rgb")
+// Equal(t, errs, nil)
+
+// s = "rgb(0, 31, 255)"
+// errs = validate.Field(s, "rgb")
+// Equal(t, errs, nil)
+
+// s = "rgb(10%, 50%, 100%)"
+// errs = validate.Field(s, "rgb")
+// Equal(t, errs, nil)
+
+// s = "rgb(10%, 50%, 55)"
+// errs = validate.Field(s, "rgb")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgb")
+
+// s = "rgb(1,349,275)"
+// errs = validate.Field(s, "rgb")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgb")
+
+// s = "rgb(01,31,255)"
+// errs = validate.Field(s, "rgb")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgb")
+
+// s = "rgba(0,31,255)"
+// errs = validate.Field(s, "rgb")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgb")
+
+// i := 1
+// errs = validate.Field(i, "rgb")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "rgb")
+// }
+
+// func TestEmail(t *testing.T) {
+
+// s := "test@mail.com"
+// errs := validate.Field(s, "email")
+// Equal(t, errs, nil)
+
+// s = "Dörte@Sörensen.example.com"
+// errs = validate.Field(s, "email")
+// Equal(t, errs, nil)
+
+// s = "θσερ@εχαμπλε.ψομ"
+// errs = validate.Field(s, "email")
+// Equal(t, errs, nil)
+
+// s = "юзер@екзампл.ком"
+// errs = validate.Field(s, "email")
+// Equal(t, errs, nil)
+
+// s = "उपयोगकर्ता@उदाहरण.कॉम"
+// errs = validate.Field(s, "email")
+// Equal(t, errs, nil)
+
+// s = "用户@例子.广告"
+// errs = validate.Field(s, "email")
+// Equal(t, errs, nil)
+
+// s = ""
+// errs = validate.Field(s, "email")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "email")
+
+// s = "test@email"
+// errs = validate.Field(s, "email")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "email")
+
+// s = "test@email."
+// errs = validate.Field(s, "email")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "email")
+
+// s = "@email.com"
+// errs = validate.Field(s, "email")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "email")
+
+// i := true
+// errs = validate.Field(i, "email")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "email")
+// }
+
+// func TestHexColor(t *testing.T) {
+
+// s := "#fff"
+// errs := validate.Field(s, "hexcolor")
+// Equal(t, errs, nil)
+
+// s = "#c2c2c2"
+// errs = validate.Field(s, "hexcolor")
+// Equal(t, errs, nil)
+
+// s = "fff"
+// errs = validate.Field(s, "hexcolor")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hexcolor")
+
+// s = "fffFF"
+// errs = validate.Field(s, "hexcolor")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hexcolor")
+
+// i := true
+// errs = validate.Field(i, "hexcolor")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hexcolor")
+// }
+
+// func TestHexadecimal(t *testing.T) {
+
+// s := "ff0044"
+// errs := validate.Field(s, "hexadecimal")
+// Equal(t, errs, nil)
+
+// s = "abcdefg"
+// errs = validate.Field(s, "hexadecimal")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hexadecimal")
+
+// i := true
+// errs = validate.Field(i, "hexadecimal")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "hexadecimal")
+// }
+
+// func TestNumber(t *testing.T) {
+
+// s := "1"
+// errs := validate.Field(s, "number")
+// Equal(t, errs, nil)
+
+// s = "+1"
+// errs = validate.Field(s, "number")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "number")
+
+// s = "-1"
+// errs = validate.Field(s, "number")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "number")
+
+// s = "1.12"
+// errs = validate.Field(s, "number")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "number")
+
+// s = "+1.12"
+// errs = validate.Field(s, "number")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "number")
+
+// s = "-1.12"
+// errs = validate.Field(s, "number")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "number")
+
+// s = "1."
+// errs = validate.Field(s, "number")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "number")
+
+// s = "1.o"
+// errs = validate.Field(s, "number")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "number")
+
+// i := 1
+// errs = validate.Field(i, "number")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "number")
+// }
+
+// func TestNumeric(t *testing.T) {
+
+// s := "1"
+// errs := validate.Field(s, "numeric")
+// Equal(t, errs, nil)
+
+// s = "+1"
+// errs = validate.Field(s, "numeric")
+// Equal(t, errs, nil)
+
+// s = "-1"
+// errs = validate.Field(s, "numeric")
+// Equal(t, errs, nil)
+
+// s = "1.12"
+// errs = validate.Field(s, "numeric")
+// Equal(t, errs, nil)
+
+// s = "+1.12"
+// errs = validate.Field(s, "numeric")
+// Equal(t, errs, nil)
+
+// s = "-1.12"
+// errs = validate.Field(s, "numeric")
+// Equal(t, errs, nil)
+
+// s = "1."
+// errs = validate.Field(s, "numeric")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "numeric")
+
+// s = "1.o"
+// errs = validate.Field(s, "numeric")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "numeric")
+
+// i := 1
+// errs = validate.Field(i, "numeric")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "numeric")
+// }
+
+// func TestAlphaNumeric(t *testing.T) {
+
+// s := "abcd123"
+// errs := validate.Field(s, "alphanum")
+// Equal(t, errs, nil)
+
+// s = "abc!23"
+// errs = validate.Field(s, "alphanum")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "alphanum")
+
+// errs = validate.Field(1, "alphanum")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "alphanum")
+// }
+
+// func TestAlpha(t *testing.T) {
+
+// s := "abcd"
+// errs := validate.Field(s, "alpha")
+// Equal(t, errs, nil)
+
+// s = "abc®"
+// errs = validate.Field(s, "alpha")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "alpha")
+
+// s = "abc÷"
+// errs = validate.Field(s, "alpha")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "alpha")
+
+// s = "abc1"
+// errs = validate.Field(s, "alpha")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "alpha")
+
+// errs = validate.Field(1, "alpha")
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "", "", "alpha")
+
+// }
+
+// func TestStructStringValidation(t *testing.T) {
+
+// tSuccess := &TestString{
+// Required: "Required",
+// Len: "length==10",
+// Min: "min=1",
+// Max: "1234567890",
+// MinMax: "12345",
+// Lt: "012345678",
+// Lte: "0123456789",
+// Gt: "01234567890",
+// Gte: "0123456789",
+// OmitEmpty: "",
+// Sub: &SubTest{
+// Test: "1",
+// },
+// SubIgnore: &SubTest{
+// Test: "",
+// },
+// Anonymous: struct {
+// A string `validate:"required"`
+// }{
+// A: "1",
+// },
+// Iface: &Impl{
+// F: "123",
+// },
+// }
+
+// errs := validate.Struct(tSuccess)
+// Equal(t, errs, nil)
+
+// tFail := &TestString{
+// Required: "",
+// Len: "",
+// Min: "",
+// Max: "12345678901",
+// MinMax: "",
+// Lt: "0123456789",
+// Lte: "01234567890",
+// Gt: "1",
+// Gte: "1",
+// OmitEmpty: "12345678901",
+// Sub: &SubTest{
+// Test: "",
+// },
+// Anonymous: struct {
+// A string `validate:"required"`
+// }{
+// A: "",
+// },
+// Iface: &Impl{
+// F: "12",
+// },
+// }
+
+// errs = validate.Struct(tFail)
+
+// // Assert Top Level
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 13)
+
+// // Assert Fields
+// AssertError(t, errs, "TestString.Required", "Required", "required")
+// AssertError(t, errs, "TestString.Len", "Len", "len")
+// AssertError(t, errs, "TestString.Min", "Min", "min")
+// AssertError(t, errs, "TestString.Max", "Max", "max")
+// AssertError(t, errs, "TestString.MinMax", "MinMax", "min")
+// AssertError(t, errs, "TestString.Lt", "Lt", "lt")
+// AssertError(t, errs, "TestString.Lte", "Lte", "lte")
+// AssertError(t, errs, "TestString.Gt", "Gt", "gt")
+// AssertError(t, errs, "TestString.Gte", "Gte", "gte")
+// AssertError(t, errs, "TestString.OmitEmpty", "OmitEmpty", "max")
+
+// // Nested Struct Field Errs
+// AssertError(t, errs, "TestString.Anonymous.A", "A", "required")
+// AssertError(t, errs, "TestString.Sub.Test", "Test", "required")
+// AssertError(t, errs, "TestString.Iface.F", "F", "len")
+// }
- errs := validate.Struct(tSuccess)
- Equal(t, errs, nil)
+func TestStructInt32Validation(t *testing.T) {
- tFail := &TestString{
- Required: "",
- Len: "",
- Min: "",
- Max: "12345678901",
- MinMax: "",
- Lt: "0123456789",
- Lte: "01234567890",
- Gt: "1",
- Gte: "1",
- OmitEmpty: "12345678901",
- Sub: &SubTest{
- Test: "",
- },
- Anonymous: struct {
- A string `validate:"required"`
- }{
- A: "",
- },
- Iface: &Impl{
- F: "12",
- },
+ type TestInt32 struct {
+ Required int `validate:"required"`
+ Len int `validate:"len=10"`
+ Min int `validate:"min=1"`
+ Max int `validate:"max=10"`
+ MinMax int `validate:"min=1,max=10"`
+ Lt int `validate:"lt=10"`
+ Lte int `validate:"lte=10"`
+ Gt int `validate:"gt=10"`
+ Gte int `validate:"gte=10"`
+ OmitEmpty int `validate:"omitempty,min=1,max=10"`
}
- errs = validate.Struct(tFail)
-
- // Assert Top Level
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 13)
-
- // Assert Fields
- AssertError(t, errs, "TestString.Required", "Required", "required")
- AssertError(t, errs, "TestString.Len", "Len", "len")
- AssertError(t, errs, "TestString.Min", "Min", "min")
- AssertError(t, errs, "TestString.Max", "Max", "max")
- AssertError(t, errs, "TestString.MinMax", "MinMax", "min")
- AssertError(t, errs, "TestString.Lt", "Lt", "lt")
- AssertError(t, errs, "TestString.Lte", "Lte", "lte")
- AssertError(t, errs, "TestString.Gt", "Gt", "gt")
- AssertError(t, errs, "TestString.Gte", "Gte", "gte")
- AssertError(t, errs, "TestString.OmitEmpty", "OmitEmpty", "max")
-
- // Nested Struct Field Errs
- AssertError(t, errs, "TestString.Anonymous.A", "A", "required")
- AssertError(t, errs, "TestString.Sub.Test", "Test", "required")
- AssertError(t, errs, "TestString.Iface.F", "F", "len")
-}
-
-func TestStructInt32Validation(t *testing.T) {
-
tSuccess := &TestInt32{
Required: 1,
Len: 10,
@@ -5637,6 +5643,7 @@ func TestStructInt32Validation(t *testing.T) {
OmitEmpty: 0,
}
+ validate := New()
errs := validate.Struct(tSuccess)
Equal(t, errs, nil)
@@ -5672,229 +5679,229 @@ func TestStructInt32Validation(t *testing.T) {
AssertError(t, errs, "TestInt32.OmitEmpty", "OmitEmpty", "max")
}
-func TestStructUint64Validation(t *testing.T) {
-
- tSuccess := &TestUint64{
- Required: 1,
- Len: 10,
- Min: 1,
- Max: 10,
- MinMax: 5,
- OmitEmpty: 0,
- }
-
- errs := validate.Struct(tSuccess)
- Equal(t, errs, nil)
-
- tFail := &TestUint64{
- Required: 0,
- Len: 11,
- Min: 0,
- Max: 11,
- MinMax: 0,
- OmitEmpty: 11,
- }
-
- errs = validate.Struct(tFail)
-
- // Assert Top Level
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 6)
-
- // Assert Fields
- AssertError(t, errs, "TestUint64.Required", "Required", "required")
- AssertError(t, errs, "TestUint64.Len", "Len", "len")
- AssertError(t, errs, "TestUint64.Min", "Min", "min")
- AssertError(t, errs, "TestUint64.Max", "Max", "max")
- AssertError(t, errs, "TestUint64.MinMax", "MinMax", "min")
- AssertError(t, errs, "TestUint64.OmitEmpty", "OmitEmpty", "max")
-}
-
-func TestStructFloat64Validation(t *testing.T) {
-
- tSuccess := &TestFloat64{
- Required: 1,
- Len: 10,
- Min: 1,
- Max: 10,
- MinMax: 5,
- OmitEmpty: 0,
- }
-
- errs := validate.Struct(tSuccess)
- Equal(t, errs, nil)
-
- tFail := &TestFloat64{
- Required: 0,
- Len: 11,
- Min: 0,
- Max: 11,
- MinMax: 0,
- OmitEmpty: 11,
- }
-
- errs = validate.Struct(tFail)
-
- // Assert Top Level
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 6)
-
- // Assert Fields
- AssertError(t, errs, "TestFloat64.Required", "Required", "required")
- AssertError(t, errs, "TestFloat64.Len", "Len", "len")
- AssertError(t, errs, "TestFloat64.Min", "Min", "min")
- AssertError(t, errs, "TestFloat64.Max", "Max", "max")
- AssertError(t, errs, "TestFloat64.MinMax", "MinMax", "min")
- AssertError(t, errs, "TestFloat64.OmitEmpty", "OmitEmpty", "max")
-}
-
-func TestStructSliceValidation(t *testing.T) {
-
- tSuccess := &TestSlice{
- Required: []int{1},
- Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
- Min: []int{1, 2},
- Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
- MinMax: []int{1, 2, 3, 4, 5},
- OmitEmpty: nil,
- }
-
- errs := validate.Struct(tSuccess)
- Equal(t, errs, nil)
-
- tFail := &TestSlice{
- 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},
- MinMax: []int{},
- OmitEmpty: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
- }
-
- errs = validate.Struct(tFail)
- NotEqual(t, errs, nil)
- Equal(t, len(errs.(ValidationErrors)), 6)
-
- // Assert Field Errors
- AssertError(t, errs, "TestSlice.Required", "Required", "required")
- AssertError(t, errs, "TestSlice.Len", "Len", "len")
- AssertError(t, errs, "TestSlice.Min", "Min", "min")
- AssertError(t, errs, "TestSlice.Max", "Max", "max")
- AssertError(t, errs, "TestSlice.MinMax", "MinMax", "min")
- AssertError(t, errs, "TestSlice.OmitEmpty", "OmitEmpty", "max")
-}
-
-func TestInvalidStruct(t *testing.T) {
- s := &SubTest{
- Test: "1",
- }
-
- PanicMatches(t, func() { validate.Struct(s.Test) }, "value passed for validation is not a struct")
-}
-
-func TestInvalidValidatorFunction(t *testing.T) {
- s := &SubTest{
- Test: "1",
- }
-
- PanicMatches(t, func() { validate.Field(s.Test, "zzxxBadFunction") }, "Undefined validation function on field")
-}
-
-func TestCustomFieldName(t *testing.T) {
- type A struct {
- B string `schema:"b" validate:"required"`
- C string `schema:"c" validate:"required"`
- D []bool `schema:"d" validate:"required"`
- E string `schema:"-" validate:"required"`
- }
-
- a := &A{}
-
- errs := New(&Config{TagName: "validate", FieldNameTag: "schema"}).Struct(a).(ValidationErrors)
- NotEqual(t, errs, nil)
- Equal(t, len(errs), 4)
- Equal(t, errs["A.B"].Name, "b")
- Equal(t, errs["A.C"].Name, "c")
- Equal(t, errs["A.D"].Name, "d")
- Equal(t, errs["A.E"].Name, "E")
-
- errs = New(&Config{TagName: "validate"}).Struct(a).(ValidationErrors)
- NotEqual(t, errs, nil)
- Equal(t, len(errs), 4)
- Equal(t, errs["A.B"].Name, "B")
- Equal(t, errs["A.C"].Name, "C")
- Equal(t, errs["A.D"].Name, "D")
- Equal(t, errs["A.E"].Name, "E")
-}
-
-func TestMutipleRecursiveExtractStructCache(t *testing.T) {
-
- type Recursive struct {
- Field *string `validate:"exists,required,len=5,ne=string"`
- }
-
- var test Recursive
-
- current := reflect.ValueOf(test)
- name := "Recursive"
- proceed := make(chan struct{})
-
- sc := validate.extractStructCache(current, name)
- ptr := fmt.Sprintf("%p", sc)
-
- for i := 0; i < 100; i++ {
-
- go func() {
- <-proceed
- sc := validate.extractStructCache(current, name)
- Equal(t, ptr, fmt.Sprintf("%p", sc))
- }()
- }
-
- close(proceed)
-}
-
-// Thanks @robbrockbank, see https://github.com/go-playground/validator/issues/249
-func TestPointerAndOmitEmpty(t *testing.T) {
-
- type Test struct {
- MyInt *int `validate:"omitempty,gte=2,lte=255"`
- }
-
- val1 := 0
- val2 := 256
-
- t1 := Test{MyInt: &val1} // This should fail validation on gte because value is 0
- t2 := Test{MyInt: &val2} // This should fail validate on lte because value is 256
- t3 := Test{MyInt: nil} // This should succeed validation because pointer is nil
-
- errs := validate.Struct(t1)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.MyInt", "MyInt", "gte")
-
- errs = validate.Struct(t2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "Test.MyInt", "MyInt", "lte")
-
- errs = validate.Struct(t3)
- Equal(t, errs, nil)
-
- type TestIface struct {
- MyInt interface{} `validate:"omitempty,gte=2,lte=255"`
- }
-
- ti1 := TestIface{MyInt: &val1} // This should fail validation on gte because value is 0
- ti2 := TestIface{MyInt: &val2} // This should fail validate on lte because value is 256
- ti3 := TestIface{MyInt: nil} // This should succeed validation because pointer is nil
-
- errs = validate.Struct(ti1)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestIface.MyInt", "MyInt", "gte")
-
- errs = validate.Struct(ti2)
- NotEqual(t, errs, nil)
- AssertError(t, errs, "TestIface.MyInt", "MyInt", "lte")
-
- errs = validate.Struct(ti3)
- Equal(t, errs, nil)
-}
+// func TestStructUint64Validation(t *testing.T) {
+
+// tSuccess := &TestUint64{
+// Required: 1,
+// Len: 10,
+// Min: 1,
+// Max: 10,
+// MinMax: 5,
+// OmitEmpty: 0,
+// }
+
+// errs := validate.Struct(tSuccess)
+// Equal(t, errs, nil)
+
+// tFail := &TestUint64{
+// Required: 0,
+// Len: 11,
+// Min: 0,
+// Max: 11,
+// MinMax: 0,
+// OmitEmpty: 11,
+// }
+
+// errs = validate.Struct(tFail)
+
+// // Assert Top Level
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 6)
+
+// // Assert Fields
+// AssertError(t, errs, "TestUint64.Required", "Required", "required")
+// AssertError(t, errs, "TestUint64.Len", "Len", "len")
+// AssertError(t, errs, "TestUint64.Min", "Min", "min")
+// AssertError(t, errs, "TestUint64.Max", "Max", "max")
+// AssertError(t, errs, "TestUint64.MinMax", "MinMax", "min")
+// AssertError(t, errs, "TestUint64.OmitEmpty", "OmitEmpty", "max")
+// }
+
+// func TestStructFloat64Validation(t *testing.T) {
+
+// tSuccess := &TestFloat64{
+// Required: 1,
+// Len: 10,
+// Min: 1,
+// Max: 10,
+// MinMax: 5,
+// OmitEmpty: 0,
+// }
+
+// errs := validate.Struct(tSuccess)
+// Equal(t, errs, nil)
+
+// tFail := &TestFloat64{
+// Required: 0,
+// Len: 11,
+// Min: 0,
+// Max: 11,
+// MinMax: 0,
+// OmitEmpty: 11,
+// }
+
+// errs = validate.Struct(tFail)
+
+// // Assert Top Level
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 6)
+
+// // Assert Fields
+// AssertError(t, errs, "TestFloat64.Required", "Required", "required")
+// AssertError(t, errs, "TestFloat64.Len", "Len", "len")
+// AssertError(t, errs, "TestFloat64.Min", "Min", "min")
+// AssertError(t, errs, "TestFloat64.Max", "Max", "max")
+// AssertError(t, errs, "TestFloat64.MinMax", "MinMax", "min")
+// AssertError(t, errs, "TestFloat64.OmitEmpty", "OmitEmpty", "max")
+// }
+
+// func TestStructSliceValidation(t *testing.T) {
+
+// tSuccess := &TestSlice{
+// Required: []int{1},
+// Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
+// Min: []int{1, 2},
+// Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
+// MinMax: []int{1, 2, 3, 4, 5},
+// OmitEmpty: nil,
+// }
+
+// errs := validate.Struct(tSuccess)
+// Equal(t, errs, nil)
+
+// tFail := &TestSlice{
+// 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},
+// MinMax: []int{},
+// OmitEmpty: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
+// }
+
+// errs = validate.Struct(tFail)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs.(ValidationErrors)), 6)
+
+// // Assert Field Errors
+// AssertError(t, errs, "TestSlice.Required", "Required", "required")
+// AssertError(t, errs, "TestSlice.Len", "Len", "len")
+// AssertError(t, errs, "TestSlice.Min", "Min", "min")
+// AssertError(t, errs, "TestSlice.Max", "Max", "max")
+// AssertError(t, errs, "TestSlice.MinMax", "MinMax", "min")
+// AssertError(t, errs, "TestSlice.OmitEmpty", "OmitEmpty", "max")
+// }
+
+// func TestInvalidStruct(t *testing.T) {
+// s := &SubTest{
+// Test: "1",
+// }
+
+// PanicMatches(t, func() { validate.Struct(s.Test) }, "value passed for validation is not a struct")
+// }
+
+// func TestInvalidValidatorFunction(t *testing.T) {
+// s := &SubTest{
+// Test: "1",
+// }
+
+// PanicMatches(t, func() { validate.Field(s.Test, "zzxxBadFunction") }, "Undefined validation function on field")
+// }
+
+// func TestCustomFieldName(t *testing.T) {
+// type A struct {
+// B string `schema:"b" validate:"required"`
+// C string `schema:"c" validate:"required"`
+// D []bool `schema:"d" validate:"required"`
+// E string `schema:"-" validate:"required"`
+// }
+
+// a := &A{}
+
+// errs := New(&Config{TagName: "validate", FieldNameTag: "schema"}).Struct(a).(ValidationErrors)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs), 4)
+// Equal(t, errs["A.B"].Name, "b")
+// Equal(t, errs["A.C"].Name, "c")
+// Equal(t, errs["A.D"].Name, "d")
+// Equal(t, errs["A.E"].Name, "E")
+
+// errs = New(&Config{TagName: "validate"}).Struct(a).(ValidationErrors)
+// NotEqual(t, errs, nil)
+// Equal(t, len(errs), 4)
+// Equal(t, errs["A.B"].Name, "B")
+// Equal(t, errs["A.C"].Name, "C")
+// Equal(t, errs["A.D"].Name, "D")
+// Equal(t, errs["A.E"].Name, "E")
+// }
+
+// func TestMutipleRecursiveExtractStructCache(t *testing.T) {
+
+// type Recursive struct {
+// Field *string `validate:"exists,required,len=5,ne=string"`
+// }
+
+// var test Recursive
+
+// current := reflect.ValueOf(test)
+// name := "Recursive"
+// proceed := make(chan struct{})
+
+// sc := validate.extractStructCache(current, name)
+// ptr := fmt.Sprintf("%p", sc)
+
+// for i := 0; i < 100; i++ {
+
+// go func() {
+// <-proceed
+// sc := validate.extractStructCache(current, name)
+// Equal(t, ptr, fmt.Sprintf("%p", sc))
+// }()
+// }
+
+// close(proceed)
+// }
+
+// // Thanks @robbrockbank, see https://github.com/go-playground/validator/issues/249
+// func TestPointerAndOmitEmpty(t *testing.T) {
+
+// type Test struct {
+// MyInt *int `validate:"omitempty,gte=2,lte=255"`
+// }
+
+// val1 := 0
+// val2 := 256
+
+// t1 := Test{MyInt: &val1} // This should fail validation on gte because value is 0
+// t2 := Test{MyInt: &val2} // This should fail validate on lte because value is 256
+// t3 := Test{MyInt: nil} // This should succeed validation because pointer is nil
+
+// errs := validate.Struct(t1)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.MyInt", "MyInt", "gte")
+
+// errs = validate.Struct(t2)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "Test.MyInt", "MyInt", "lte")
+
+// errs = validate.Struct(t3)
+// Equal(t, errs, nil)
+
+// type TestIface struct {
+// MyInt interface{} `validate:"omitempty,gte=2,lte=255"`
+// }
+
+// ti1 := TestIface{MyInt: &val1} // This should fail validation on gte because value is 0
+// ti2 := TestIface{MyInt: &val2} // This should fail validate on lte because value is 256
+// ti3 := TestIface{MyInt: nil} // This should succeed validation because pointer is nil
+
+// errs = validate.Struct(ti1)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestIface.MyInt", "MyInt", "gte")
+
+// errs = validate.Struct(ti2)
+// NotEqual(t, errs, nil)
+// AssertError(t, errs, "TestIface.MyInt", "MyInt", "lte")
+
+// errs = validate.Struct(ti3)
+// Equal(t, errs, nil)
+// }