Postcode validator for value and field (#759)

* Postcode validator for value and field

* Add translation for postcode rules

Co-authored-by: Dean Karn <Dean.Karn@gmail.com>
pull/767/head
ѵµσɳɠ 4 years ago committed by GitHub
parent c2066206fe
commit a53d64fc35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 291
      baked_in.go
  2. 173
      postcode_regexes.go
  3. 84
      translations/en/en.go
  4. 13
      translations/en/en_test.go
  5. 299
      validator_test.go

@ -68,129 +68,131 @@ var (
// 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,
"required_if": requiredIf,
"required_unless": requiredUnless,
"required_with": requiredWith,
"required_with_all": requiredWithAll,
"required_without": requiredWithout,
"required_without_all": requiredWithoutAll,
"excluded_with": excludedWith,
"excluded_with_all": excludedWithAll,
"excluded_without": excludedWithout,
"excluded_without_all": excludedWithoutAll,
"isdefault": isDefault,
"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,
"fieldcontains": fieldContains,
"fieldexcludes": fieldExcludes,
"alpha": isAlpha,
"alphanum": isAlphanum,
"alphaunicode": isAlphaUnicode,
"alphanumunicode": isAlphanumUnicode,
"numeric": isNumeric,
"number": isNumber,
"hexadecimal": isHexadecimal,
"hexcolor": isHEXColor,
"rgb": isRGB,
"rgba": isRGBA,
"hsl": isHSL,
"hsla": isHSLA,
"e164": isE164,
"email": isEmail,
"url": isURL,
"uri": isURI,
"urn_rfc2141": isUrnRFC2141, // RFC 2141
"file": isFile,
"base64": isBase64,
"base64url": isBase64URL,
"contains": contains,
"containsany": containsAny,
"containsrune": containsRune,
"excludes": excludes,
"excludesall": excludesAll,
"excludesrune": excludesRune,
"startswith": startsWith,
"endswith": endsWith,
"startsnotwith": startsNotWith,
"endsnotwith": endsNotWith,
"isbn": isISBN,
"isbn10": isISBN10,
"isbn13": isISBN13,
"eth_addr": isEthereumAddress,
"btc_addr": isBitcoinAddress,
"btc_addr_bech32": isBitcoinBech32Address,
"uuid": isUUID,
"uuid3": isUUID3,
"uuid4": isUUID4,
"uuid5": isUUID5,
"uuid_rfc4122": isUUIDRFC4122,
"uuid3_rfc4122": isUUID3RFC4122,
"uuid4_rfc4122": isUUID4RFC4122,
"uuid5_rfc4122": isUUID5RFC4122,
"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,
"hostname": isHostnameRFC952, // RFC 952
"hostname_rfc1123": isHostnameRFC1123, // RFC 1123
"fqdn": isFQDN,
"unique": isUnique,
"oneof": isOneOf,
"html": isHTML,
"html_encoded": isHTMLEncoded,
"url_encoded": isURLEncoded,
"dir": isDir,
"json": isJSON,
"hostname_port": isHostnamePort,
"lowercase": isLowercase,
"uppercase": isUppercase,
"datetime": isDatetime,
"timezone": isTimeZone,
"iso3166_1_alpha2": isIso3166Alpha2,
"iso3166_1_alpha3": isIso3166Alpha3,
"iso3166_1_alpha_numeric": isIso3166AlphaNumeric,
"bcp47_language_tag": isBCP47LanguageTag,
"bic": isIsoBicFormat,
"required": hasValue,
"required_if": requiredIf,
"required_unless": requiredUnless,
"required_with": requiredWith,
"required_with_all": requiredWithAll,
"required_without": requiredWithout,
"required_without_all": requiredWithoutAll,
"excluded_with": excludedWith,
"excluded_with_all": excludedWithAll,
"excluded_without": excludedWithout,
"excluded_without_all": excludedWithoutAll,
"isdefault": isDefault,
"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,
"fieldcontains": fieldContains,
"fieldexcludes": fieldExcludes,
"alpha": isAlpha,
"alphanum": isAlphanum,
"alphaunicode": isAlphaUnicode,
"alphanumunicode": isAlphanumUnicode,
"numeric": isNumeric,
"number": isNumber,
"hexadecimal": isHexadecimal,
"hexcolor": isHEXColor,
"rgb": isRGB,
"rgba": isRGBA,
"hsl": isHSL,
"hsla": isHSLA,
"e164": isE164,
"email": isEmail,
"url": isURL,
"uri": isURI,
"urn_rfc2141": isUrnRFC2141, // RFC 2141
"file": isFile,
"base64": isBase64,
"base64url": isBase64URL,
"contains": contains,
"containsany": containsAny,
"containsrune": containsRune,
"excludes": excludes,
"excludesall": excludesAll,
"excludesrune": excludesRune,
"startswith": startsWith,
"endswith": endsWith,
"startsnotwith": startsNotWith,
"endsnotwith": endsNotWith,
"isbn": isISBN,
"isbn10": isISBN10,
"isbn13": isISBN13,
"eth_addr": isEthereumAddress,
"btc_addr": isBitcoinAddress,
"btc_addr_bech32": isBitcoinBech32Address,
"uuid": isUUID,
"uuid3": isUUID3,
"uuid4": isUUID4,
"uuid5": isUUID5,
"uuid_rfc4122": isUUIDRFC4122,
"uuid3_rfc4122": isUUID3RFC4122,
"uuid4_rfc4122": isUUID4RFC4122,
"uuid5_rfc4122": isUUID5RFC4122,
"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,
"hostname": isHostnameRFC952, // RFC 952
"hostname_rfc1123": isHostnameRFC1123, // RFC 1123
"fqdn": isFQDN,
"unique": isUnique,
"oneof": isOneOf,
"html": isHTML,
"html_encoded": isHTMLEncoded,
"url_encoded": isURLEncoded,
"dir": isDir,
"json": isJSON,
"hostname_port": isHostnamePort,
"lowercase": isLowercase,
"uppercase": isUppercase,
"datetime": isDatetime,
"timezone": isTimeZone,
"iso3166_1_alpha2": isIso3166Alpha2,
"iso3166_1_alpha3": isIso3166Alpha3,
"iso3166_1_alpha_numeric": isIso3166AlphaNumeric,
"bcp47_language_tag": isBCP47LanguageTag,
"postcode_iso3166_alpha2": isPostcodeByIso3166Alpha2,
"postcode_iso3166_alpha2_field": isPostcodeByIso3166Alpha2Field,
"bic": isIsoBicFormat,
}
)
@ -1205,6 +1207,49 @@ func isEq(fl FieldLevel) bool {
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}
// isPostcodeByIso3166Alpha2 validates by value which is country code in iso 3166 alpha 2
// example: `postcode_iso3166_alpha2=US`
func isPostcodeByIso3166Alpha2(fl FieldLevel) bool {
field := fl.Field()
param := fl.Param()
reg, found := postCodeRegexDict[param]
if !found {
return false
}
return reg.MatchString(field.String())
}
// isPostcodeByIso3166Alpha2 validates by field which represents for a value of country code in iso 3166 alpha 2
// example: `postcode_iso3166_alpha2_field=CountryCode`
func isPostcodeByIso3166Alpha2Field(fl FieldLevel) bool {
field := fl.Field()
kind := field.Kind()
params := parseOneOfParam2(fl.Param())
if len(params) != 1 {
return false
}
currentField, kind, _, found := fl.GetStructFieldOKAdvanced2(fl.Parent(), params[0])
if !found {
return false
}
if kind != reflect.String {
panic(fmt.Sprintf("Bad field type %T", currentField.Interface()))
}
reg, found := postCodeRegexDict[currentField.String()]
if !found {
return false
}
return reg.MatchString(field.String())
}
// IsBase64 is the validation function for validating if the current field's value is a valid base 64.
func isBase64(fl FieldLevel) bool {
return base64Regex.MatchString(fl.Field().String())

@ -0,0 +1,173 @@
package validator
import "regexp"
var postCodePatternDict = map[string]string{
"GB": `^GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}$`,
"JE": `^JE\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
"GG": `^GY\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
"IM": `^IM\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
"US": `^\d{5}([ \-]\d{4})?$`,
"CA": `^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ ]?\d[ABCEGHJ-NPRSTV-Z]\d$`,
"DE": `^\d{5}$`,
"JP": `^\d{3}-\d{4}$`,
"FR": `^\d{2}[ ]?\d{3}$`,
"AU": `^\d{4}$`,
"IT": `^\d{5}$`,
"CH": `^\d{4}$`,
"AT": `^\d{4}$`,
"ES": `^\d{5}$`,
"NL": `^\d{4}[ ]?[A-Z]{2}$`,
"BE": `^\d{4}$`,
"DK": `^\d{4}$`,
"SE": `^\d{3}[ ]?\d{2}$`,
"NO": `^\d{4}$`,
"BR": `^\d{5}[\-]?\d{3}$`,
"PT": `^\d{4}([\-]\d{3})?$`,
"FI": `^\d{5}$`,
"AX": `^22\d{3}$`,
"KR": `^\d{3}[\-]\d{3}$`,
"CN": `^\d{6}$`,
"TW": `^\d{3}(\d{2})?$`,
"SG": `^\d{6}$`,
"DZ": `^\d{5}$`,
"AD": `^AD\d{3}$`,
"AR": `^([A-HJ-NP-Z])?\d{4}([A-Z]{3})?$`,
"AM": `^(37)?\d{4}$`,
"AZ": `^\d{4}$`,
"BH": `^((1[0-2]|[2-9])\d{2})?$`,
"BD": `^\d{4}$`,
"BB": `^(BB\d{5})?$`,
"BY": `^\d{6}$`,
"BM": `^[A-Z]{2}[ ]?[A-Z0-9]{2}$`,
"BA": `^\d{5}$`,
"IO": `^BBND 1ZZ$`,
"BN": `^[A-Z]{2}[ ]?\d{4}$`,
"BG": `^\d{4}$`,
"KH": `^\d{5}$`,
"CV": `^\d{4}$`,
"CL": `^\d{7}$`,
"CR": `^\d{4,5}|\d{3}-\d{4}$`,
"HR": `^\d{5}$`,
"CY": `^\d{4}$`,
"CZ": `^\d{3}[ ]?\d{2}$`,
"DO": `^\d{5}$`,
"EC": `^([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?$`,
"EG": `^\d{5}$`,
"EE": `^\d{5}$`,
"FO": `^\d{3}$`,
"GE": `^\d{4}$`,
"GR": `^\d{3}[ ]?\d{2}$`,
"GL": `^39\d{2}$`,
"GT": `^\d{5}$`,
"HT": `^\d{4}$`,
"HN": `^(?:\d{5})?$`,
"HU": `^\d{4}$`,
"IS": `^\d{3}$`,
"IN": `^\d{6}$`,
"ID": `^\d{5}$`,
"IL": `^\d{5}$`,
"JO": `^\d{5}$`,
"KZ": `^\d{6}$`,
"KE": `^\d{5}$`,
"KW": `^\d{5}$`,
"LA": `^\d{5}$`,
"LV": `^\d{4}$`,
"LB": `^(\d{4}([ ]?\d{4})?)?$`,
"LI": `^(948[5-9])|(949[0-7])$`,
"LT": `^\d{5}$`,
"LU": `^\d{4}$`,
"MK": `^\d{4}$`,
"MY": `^\d{5}$`,
"MV": `^\d{5}$`,
"MT": `^[A-Z]{3}[ ]?\d{2,4}$`,
"MU": `^(\d{3}[A-Z]{2}\d{3})?$`,
"MX": `^\d{5}$`,
"MD": `^\d{4}$`,
"MC": `^980\d{2}$`,
"MA": `^\d{5}$`,
"NP": `^\d{5}$`,
"NZ": `^\d{4}$`,
"NI": `^((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?$`,
"NG": `^(\d{6})?$`,
"OM": `^(PC )?\d{3}$`,
"PK": `^\d{5}$`,
"PY": `^\d{4}$`,
"PH": `^\d{4}$`,
"PL": `^\d{2}-\d{3}$`,
"PR": `^00[679]\d{2}([ \-]\d{4})?$`,
"RO": `^\d{6}$`,
"RU": `^\d{6}$`,
"SM": `^4789\d$`,
"SA": `^\d{5}$`,
"SN": `^\d{5}$`,
"SK": `^\d{3}[ ]?\d{2}$`,
"SI": `^\d{4}$`,
"ZA": `^\d{4}$`,
"LK": `^\d{5}$`,
"TJ": `^\d{6}$`,
"TH": `^\d{5}$`,
"TN": `^\d{4}$`,
"TR": `^\d{5}$`,
"TM": `^\d{6}$`,
"UA": `^\d{5}$`,
"UY": `^\d{5}$`,
"UZ": `^\d{6}$`,
"VA": `^00120$`,
"VE": `^\d{4}$`,
"ZM": `^\d{5}$`,
"AS": `^96799$`,
"CC": `^6799$`,
"CK": `^\d{4}$`,
"RS": `^\d{6}$`,
"ME": `^8\d{4}$`,
"CS": `^\d{5}$`,
"YU": `^\d{5}$`,
"CX": `^6798$`,
"ET": `^\d{4}$`,
"FK": `^FIQQ 1ZZ$`,
"NF": `^2899$`,
"FM": `^(9694[1-4])([ \-]\d{4})?$`,
"GF": `^9[78]3\d{2}$`,
"GN": `^\d{3}$`,
"GP": `^9[78][01]\d{2}$`,
"GS": `^SIQQ 1ZZ$`,
"GU": `^969[123]\d([ \-]\d{4})?$`,
"GW": `^\d{4}$`,
"HM": `^\d{4}$`,
"IQ": `^\d{5}$`,
"KG": `^\d{6}$`,
"LR": `^\d{4}$`,
"LS": `^\d{3}$`,
"MG": `^\d{3}$`,
"MH": `^969[67]\d([ \-]\d{4})?$`,
"MN": `^\d{6}$`,
"MP": `^9695[012]([ \-]\d{4})?$`,
"MQ": `^9[78]2\d{2}$`,
"NC": `^988\d{2}$`,
"NE": `^\d{4}$`,
"VI": `^008(([0-4]\d)|(5[01]))([ \-]\d{4})?$`,
"VN": `^[0-9]{1,6}$`,
"PF": `^987\d{2}$`,
"PG": `^\d{3}$`,
"PM": `^9[78]5\d{2}$`,
"PN": `^PCRN 1ZZ$`,
"PW": `^96940$`,
"RE": `^9[78]4\d{2}$`,
"SH": `^(ASCN|STHL) 1ZZ$`,
"SJ": `^\d{4}$`,
"SO": `^\d{5}$`,
"SZ": `^[HLMS]\d{3}$`,
"TC": `^TKCA 1ZZ$`,
"WF": `^986\d{2}$`,
"XK": `^\d{5}$`,
"YT": `^976\d{2}$`,
}
var postCodeRegexDict = map[string]*regexp.Regexp{}
func init() {
for countryCode, pattern := range postCodePatternDict {
postCodeRegexDict[countryCode] = regexp.MustCompile(pattern)
}
}

@ -16,7 +16,6 @@ import (
// RegisterDefaultTranslations registers a set of default translations
// for all built in tag's in validator; you may add your own as desired.
func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) {
translations := []struct {
tag string
translation string
@ -32,7 +31,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
{
tag: "len",
customRegisFunc: func(ut ut.Translator) (err error) {
if err = ut.Add("len-string", "{0} must be {1} in length", false); err != nil {
return
}
@ -61,10 +59,8 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
}
return
},
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
var err error
var t string
@ -123,7 +119,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
{
tag: "min",
customRegisFunc: func(ut ut.Translator) (err error) {
if err = ut.Add("min-string", "{0} must be at least {1} in length", false); err != nil {
return
}
@ -152,10 +147,8 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
}
return
},
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
var err error
var t string
@ -214,7 +207,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
{
tag: "max",
customRegisFunc: func(ut ut.Translator) (err error) {
if err = ut.Add("max-string", "{0} must be a maximum of {1} in length", false); err != nil {
return
}
@ -243,10 +235,8 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
}
return
},
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
var err error
var t string
@ -307,7 +297,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} is not equal to {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
fmt.Printf("warning: error translating FieldError: %#v", fe)
@ -322,7 +311,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} should not be equal to {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
fmt.Printf("warning: error translating FieldError: %#v", fe)
@ -335,7 +323,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
{
tag: "lt",
customRegisFunc: func(ut ut.Translator) (err error) {
if err = ut.Add("lt-string", "{0} must be less than {1} in length", false); err != nil {
return
}
@ -369,10 +356,8 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
}
return
},
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
var err error
var t string
var f64 float64
@ -380,7 +365,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
var kind reflect.Kind
fn := func() (err error) {
if idx := strings.Index(fe.Param(), "."); idx != -1 {
digits = uint64(len(fe.Param()[idx+1:]))
}
@ -456,7 +440,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
{
tag: "lte",
customRegisFunc: func(ut ut.Translator) (err error) {
if err = ut.Add("lte-string", "{0} must be at maximum {1} in length", false); err != nil {
return
}
@ -492,7 +475,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return
},
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
var err error
var t string
var f64 float64
@ -500,7 +482,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
var kind reflect.Kind
fn := func() (err error) {
if idx := strings.Index(fe.Param(), "."); idx != -1 {
digits = uint64(len(fe.Param()[idx+1:]))
}
@ -576,7 +557,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
{
tag: "gt",
customRegisFunc: func(ut ut.Translator) (err error) {
if err = ut.Add("gt-string", "{0} must be greater than {1} in length", false); err != nil {
return
}
@ -612,7 +592,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return
},
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
var err error
var t string
var f64 float64
@ -620,7 +599,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
var kind reflect.Kind
fn := func() (err error) {
if idx := strings.Index(fe.Param(), "."); idx != -1 {
digits = uint64(len(fe.Param()[idx+1:]))
}
@ -696,7 +674,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
{
tag: "gte",
customRegisFunc: func(ut ut.Translator) (err error) {
if err = ut.Add("gte-string", "{0} must be at least {1} in length", false); err != nil {
return
}
@ -732,7 +709,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return
},
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
var err error
var t string
var f64 float64
@ -740,7 +716,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
var kind reflect.Kind
fn := func() (err error) {
if idx := strings.Index(fe.Param(), "."); idx != -1 {
digits = uint64(len(fe.Param()[idx+1:]))
}
@ -818,7 +793,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be equal to {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -833,7 +807,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be equal to {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -848,7 +821,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} cannot be equal to {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -863,7 +835,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be greater than {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -878,7 +849,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be greater than or equal to {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -893,7 +863,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be less than {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -908,7 +877,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be less than or equal to {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -923,7 +891,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} cannot be equal to {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -938,7 +905,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be greater than {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -953,7 +919,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be greater than or equal to {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -968,7 +933,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be less than {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -983,7 +947,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be less than or equal to {1}",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -1073,7 +1036,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must contain the text '{1}'",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -1088,7 +1050,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must contain at least one of the following characters '{1}'",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -1103,7 +1064,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} cannot contain the text '{1}'",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -1118,7 +1078,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} cannot contain any of the following characters '{1}'",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -1133,7 +1092,6 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} cannot contain the following '{1}'",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -1325,8 +1283,8 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
tag: "json",
translation: "{0} must be a valid json string",
override: false,
},
{
},
{
tag: "lowercase",
translation: "{0} must be a lowercase string",
override: false,
@ -1341,7 +1299,34 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} does not match the {1} format",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
return fe.(error).Error()
}
return t
},
},
{
tag: "postcode_iso3166_alpha2",
translation: "{0} does not match postcode format of {1} country",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
return fe.(error).Error()
}
return t
},
},
{
tag: "postcode_iso3166_alpha2_field",
translation: "{0} does not match postcode format of country in {1} field",
override: false,
customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)
@ -1356,17 +1341,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
for _, t := range translations {
if t.customTransFunc != nil && t.customRegisFunc != nil {
err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc)
} else if t.customTransFunc != nil && t.customRegisFunc == nil {
err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc)
} else if t.customTransFunc == nil && t.customRegisFunc != nil {
err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc)
} else {
err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc)
}
@ -1380,21 +1359,16 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
}
func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc {
return func(ut ut.Translator) (err error) {
if err = ut.Add(tag, translation, override); err != nil {
return
}
return
}
}
func translateFunc(ut ut.Translator, fe validator.FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field())
if err != nil {
log.Printf("warning: error translating FieldError: %#v", fe)

@ -11,7 +11,6 @@ import (
)
func TestTranslations(t *testing.T) {
eng := english.New()
uni := ut.New(eng, eng)
trans, _ := uni.GetTranslator("en")
@ -145,6 +144,9 @@ func TestTranslations(t *testing.T) {
LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"`
PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
}
var test Test
@ -656,6 +658,14 @@ func TestTranslations(t *testing.T) {
ns: "Test.Datetime",
expected: "Datetime does not match the 2006-01-02 format",
},
{
ns: "Test.PostCode",
expected: "PostCode does not match postcode format of SG country",
},
{
ns: "Test.PostCodeByField",
expected: "PostCodeByField does not match postcode format of country in PostCodeCountry field",
},
}
for _, tt := range tests {
@ -672,5 +682,4 @@ func TestTranslations(t *testing.T) {
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

@ -14,6 +14,7 @@ import (
"testing"
"time"
"github.com/go-playground/assert/v2"
. "github.com/go-playground/assert/v2"
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/fr"
@ -108,7 +109,6 @@ type TestSlice struct {
}
func AssertError(t *testing.T, err error, nsKey, structNsKey, field, structField, expectedTag string) {
errs := err.(ValidationErrors)
found := false
@ -150,7 +150,6 @@ func AssertDeepError(t *testing.T, err error, nsKey, structNsKey, field, structF
}
func getError(err error, nsKey, structNsKey string) FieldError {
errs := err.(ValidationErrors)
var fe FieldError
@ -170,7 +169,6 @@ type valuer struct {
}
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")
@ -189,7 +187,6 @@ type MadeUpCustomType struct {
}
func ValidateCustomType(field reflect.Value) interface{} {
if cust, ok := field.Interface().(MadeUpCustomType); ok {
if len(cust.FirstName) == 0 || len(cust.LastName) == 0 {
@ -203,7 +200,6 @@ func ValidateCustomType(field reflect.Value) interface{} {
}
func OverrideIntTypeForSomeReason(field reflect.Value) interface{} {
if i, ok := field.Interface().(int); ok {
if i == 1 {
return "1"
@ -223,7 +219,6 @@ type CustomMadeUpStruct struct {
}
func ValidateValuerType(field reflect.Value) interface{} {
if valuer, ok := field.Interface().(driver.Valuer); ok {
val, err := valuer.Value()
@ -261,7 +256,6 @@ type TestStruct struct {
}
func StructValidationTestStructSuccess(sl StructLevel) {
st := sl.Current().Interface().(TestStruct)
if st.String != "good value" {
@ -270,7 +264,6 @@ func StructValidationTestStructSuccess(sl StructLevel) {
}
func StructValidationTestStruct(sl StructLevel) {
st := sl.Current().Interface().(TestStruct)
if st.String != "bad value" {
@ -279,7 +272,6 @@ func StructValidationTestStruct(sl StructLevel) {
}
func StructValidationNoTestStructCustomName(sl StructLevel) {
st := sl.Current().Interface().(TestStruct)
if st.String != "bad value" {
@ -288,7 +280,6 @@ func StructValidationNoTestStructCustomName(sl StructLevel) {
}
func StructValidationTestStructInvalid(sl StructLevel) {
st := sl.Current().Interface().(TestStruct)
if st.String != "bad value" {
@ -297,7 +288,6 @@ func StructValidationTestStructInvalid(sl StructLevel) {
}
func StructValidationTestStructReturnValidationErrors(sl StructLevel) {
s := sl.Current().Interface().(TestStructReturnValidationErrors)
errs := sl.Validator().Struct(s.Inner1.Inner2)
@ -309,7 +299,6 @@ func StructValidationTestStructReturnValidationErrors(sl StructLevel) {
}
func StructValidationTestStructReturnValidationErrors2(sl StructLevel) {
s := sl.Current().Interface().(TestStructReturnValidationErrors)
errs := sl.Validator().Struct(s.Inner1.Inner2)
@ -337,7 +326,6 @@ type StructLevelInvalidErr struct {
}
func StructLevelInvalidError(sl StructLevel) {
top := sl.Top().Interface().(StructLevelInvalidErr)
s := sl.Current().Interface().(StructLevelInvalidErr)
@ -359,7 +347,6 @@ func float64Ptr(v float64) *float64 {
}
func TestStructLevelInvalidError(t *testing.T) {
validate := New()
validate.RegisterStructValidation(StructLevelInvalidError, StructLevelInvalidErr{})
@ -383,7 +370,6 @@ func TestStructLevelInvalidError(t *testing.T) {
}
func TestNameNamespace(t *testing.T) {
type Inner2Namespace struct {
String []string `validate:"dive,required" json:"JSONString"`
}
@ -432,7 +418,6 @@ func TestNameNamespace(t *testing.T) {
}
func TestAnonymous(t *testing.T) {
validate := New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@ -500,7 +485,6 @@ func TestAnonymous(t *testing.T) {
}
func TestAnonymousSameStructDifferentTags(t *testing.T) {
validate := New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@ -545,7 +529,6 @@ func TestAnonymousSameStructDifferentTags(t *testing.T) {
}
func TestStructLevelReturnValidationErrors(t *testing.T) {
validate := New()
validate.RegisterStructValidation(StructValidationTestStructReturnValidationErrors, TestStructReturnValidationErrors{})
@ -575,7 +558,6 @@ func TestStructLevelReturnValidationErrors(t *testing.T) {
}
func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) {
validate := New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@ -632,7 +614,6 @@ func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) {
}
func TestStructLevelValidations(t *testing.T) {
v1 := New()
v1.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
@ -666,7 +647,6 @@ func TestStructLevelValidations(t *testing.T) {
}
func TestAliasTags(t *testing.T) {
validate := New()
validate.RegisterAlias("iscoloralias", "hexcolor|rgb|rgba|hsl|hsla")
@ -714,7 +694,6 @@ func TestAliasTags(t *testing.T) {
}
func TestNilValidator(t *testing.T) {
type TestStruct struct {
Test string `validate:"required"`
}
@ -724,7 +703,6 @@ func TestNilValidator(t *testing.T) {
var val *Validate
fn := func(fl FieldLevel) bool {
return fl.Parent().String() == fl.Field().String()
}
@ -1971,7 +1949,6 @@ func TestCrossStructEqFieldValidation(t *testing.T) {
}
func TestCrossNamespaceFieldValidation(t *testing.T) {
type SliceStruct struct {
Name string
}
@ -2209,7 +2186,6 @@ func TestCrossNamespaceFieldValidation(t *testing.T) {
}
func TestExistsValidation(t *testing.T) {
jsonText := "{ \"truthiness2\": true }"
type Thing struct {
@ -2240,7 +2216,6 @@ func TestExistsValidation(t *testing.T) {
}
func TestSQLValue2Validation(t *testing.T) {
validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, valuer{}, (*driver.Valuer)(nil), sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
@ -2291,7 +2266,6 @@ func TestSQLValue2Validation(t *testing.T) {
}
func TestSQLValueValidation(t *testing.T) {
validate := New()
validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{})
validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
@ -2969,7 +2943,6 @@ func TestUnixAddrValidation(t *testing.T) {
}
func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {
validate := New()
var m map[string]string
@ -3047,7 +3020,6 @@ func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {
}
func TestDatePtrValidationIssueValidation(t *testing.T) {
type Test struct {
LastViewed *time.Time
Reminder *time.Time
@ -3099,7 +3071,6 @@ func TestBadKeyValidation(t *testing.T) {
}
func TestInterfaceErrValidation(t *testing.T) {
var v2 interface{} = 1
var v1 interface{} = v2
@ -3273,7 +3244,6 @@ func TestInterfaceErrValidation(t *testing.T) {
}
func TestMapDiveValidation(t *testing.T) {
validate := New()
n := map[int]interface{}{0: nil}
@ -3396,7 +3366,6 @@ func TestMapDiveValidation(t *testing.T) {
}
func TestArrayDiveValidation(t *testing.T) {
validate := New()
arr := []string{"ok", "", "ok"}
@ -4405,7 +4374,6 @@ func TestISBN10Validation(t *testing.T) {
}
func TestExcludesRuneValidation(t *testing.T) {
tests := []struct {
Value string `validate:"excludesrune=☻"`
Tag string
@ -4433,7 +4401,6 @@ func TestExcludesRuneValidation(t *testing.T) {
}
func TestExcludesAllValidation(t *testing.T) {
tests := []struct {
Value string `validate:"excludesall=@!{}[]"`
Tag string
@ -4479,7 +4446,6 @@ func TestExcludesAllValidation(t *testing.T) {
}
func TestExcludesValidation(t *testing.T) {
tests := []struct {
Value string `validate:"excludes=@"`
Tag string
@ -4507,7 +4473,6 @@ func TestExcludesValidation(t *testing.T) {
}
func TestContainsRuneValidation(t *testing.T) {
tests := []struct {
Value string `validate:"containsrune=☻"`
Tag string
@ -4535,7 +4500,6 @@ func TestContainsRuneValidation(t *testing.T) {
}
func TestContainsAnyValidation(t *testing.T) {
tests := []struct {
Value string `validate:"containsany=@!{}[]"`
Tag string
@ -4563,7 +4527,6 @@ func TestContainsAnyValidation(t *testing.T) {
}
func TestContainsValidation(t *testing.T) {
tests := []struct {
Value string `validate:"contains=@"`
Tag string
@ -5149,7 +5112,6 @@ func TestOneOfValidation(t *testing.T) {
}
func TestBase64Validation(t *testing.T) {
validate := New()
s := "dW5pY29ybg=="
@ -5253,7 +5215,6 @@ func TestFileValidation(t *testing.T) {
}
func TestEthereumAddressValidation(t *testing.T) {
validate := New()
tests := []struct {
@ -5307,7 +5268,6 @@ func TestEthereumAddressValidation(t *testing.T) {
}
func TestBitcoinAddressValidation(t *testing.T) {
validate := New()
tests := []struct {
@ -5417,7 +5377,6 @@ func TestBitcoinAddressValidation(t *testing.T) {
}
func TestBitcoinBech32AddressValidation(t *testing.T) {
validate := New()
tests := []struct {
@ -5468,7 +5427,6 @@ func TestBitcoinBech32AddressValidation(t *testing.T) {
}
func TestNoStructLevelValidation(t *testing.T) {
type Inner struct {
Test string `validate:"len=5"`
}
@ -5500,7 +5458,6 @@ func TestNoStructLevelValidation(t *testing.T) {
}
func TestStructOnlyValidation(t *testing.T) {
type Inner struct {
Test string `validate:"len=5"`
}
@ -6566,7 +6523,6 @@ func TestValidateByTagAndValue(t *testing.T) {
Equal(t, errs, nil)
fn := func(fl FieldLevel) bool {
return fl.Parent().String() == fl.Field().String()
}
@ -6584,9 +6540,7 @@ func TestValidateByTagAndValue(t *testing.T) {
}
func TestAddFunctions(t *testing.T) {
fn := func(fl FieldLevel) bool {
return true
}
@ -6615,7 +6569,6 @@ func TestAddFunctions(t *testing.T) {
}
func TestChangeTag(t *testing.T) {
validate := New()
validate.SetTagName("val")
@ -7262,8 +7215,7 @@ func TestIsLte(t *testing.T) {
}
func TestUrnRFC2141(t *testing.T) {
var tests = []struct {
tests := []struct {
param string
expected bool
}{
@ -7339,8 +7291,7 @@ func TestUrnRFC2141(t *testing.T) {
}
func TestUrl(t *testing.T) {
var tests = []struct {
tests := []struct {
param string
expected bool
}{
@ -7407,8 +7358,7 @@ func TestUrl(t *testing.T) {
}
func TestUri(t *testing.T) {
var tests = []struct {
tests := []struct {
param string
expected bool
}{
@ -7474,7 +7424,6 @@ func TestUri(t *testing.T) {
}
func TestOrTag(t *testing.T) {
validate := New()
s := "rgba(0,31,255,0.5)"
@ -7504,7 +7453,7 @@ func TestOrTag(t *testing.T) {
Equal(t, errs, nil)
s = "green"
errs = validate.Var(s, "eq=|eq=blue,rgb|rgba") //should fail on first validation block
errs = validate.Var(s, "eq=|eq=blue,rgb|rgba") // should fail on first validation block
NotEqual(t, errs, nil)
ve := errs.(ValidationErrors)
Equal(t, len(ve), 1)
@ -7517,7 +7466,6 @@ func TestOrTag(t *testing.T) {
v2 := New()
v2.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
@ -7542,7 +7490,6 @@ func TestOrTag(t *testing.T) {
}
func TestHsla(t *testing.T) {
validate := New()
s := "hsla(360,100%,100%,1)"
@ -7589,7 +7536,6 @@ func TestHsla(t *testing.T) {
}
func TestHsl(t *testing.T) {
validate := New()
s := "hsl(360,100%,50%)"
@ -7627,7 +7573,6 @@ func TestHsl(t *testing.T) {
}
func TestRgba(t *testing.T) {
validate := New()
s := "rgba(0,31,255,0.5)"
@ -7673,7 +7618,6 @@ func TestRgba(t *testing.T) {
}
func TestRgb(t *testing.T) {
validate := New()
s := "rgb(0,31,255)"
@ -7715,7 +7659,6 @@ func TestRgb(t *testing.T) {
}
func TestEmail(t *testing.T) {
validate := New()
s := "test@mail.com"
@ -7783,7 +7726,6 @@ func TestEmail(t *testing.T) {
}
func TestHexColor(t *testing.T) {
validate := New()
s := "#fff"
@ -7811,7 +7753,6 @@ func TestHexColor(t *testing.T) {
}
func TestHexadecimal(t *testing.T) {
validate := New()
s := "ff0044"
@ -7838,7 +7779,6 @@ func TestHexadecimal(t *testing.T) {
}
func TestNumber(t *testing.T) {
validate := New()
s := "1"
@ -7886,7 +7826,6 @@ func TestNumber(t *testing.T) {
}
func TestNumeric(t *testing.T) {
validate := New()
s := "1"
@ -7929,7 +7868,6 @@ func TestNumeric(t *testing.T) {
}
func TestAlphaNumeric(t *testing.T) {
validate := New()
s := "abcd123"
@ -7947,7 +7885,6 @@ func TestAlphaNumeric(t *testing.T) {
}
func TestAlpha(t *testing.T) {
validate := New()
s := "abcd"
@ -7977,11 +7914,9 @@ func TestAlpha(t *testing.T) {
errs = validate.Var(1, "alpha")
NotEqual(t, errs, nil)
AssertError(t, errs, "", "", "", "", "alpha")
}
func TestStructStringValidation(t *testing.T) {
validate := New()
tSuccess := &TestString{
@ -8063,7 +7998,6 @@ func TestStructStringValidation(t *testing.T) {
}
func TestStructInt32Validation(t *testing.T) {
type TestInt32 struct {
Required int `validate:"required"`
Len int `validate:"len=10"`
@ -8127,7 +8061,6 @@ func TestStructInt32Validation(t *testing.T) {
}
func TestStructUint64Validation(t *testing.T) {
validate := New()
tSuccess := &TestUint64{
@ -8167,7 +8100,6 @@ func TestStructUint64Validation(t *testing.T) {
}
func TestStructFloat64Validation(t *testing.T) {
validate := New()
tSuccess := &TestFloat64{
@ -8207,7 +8139,6 @@ func TestStructFloat64Validation(t *testing.T) {
}
func TestStructSliceValidation(t *testing.T) {
validate := New()
tSuccess := &TestSlice{
@ -8257,11 +8188,9 @@ func TestStructSliceValidation(t *testing.T) {
_, ok := fe.Value().([]int)
Equal(t, ok, true)
}
func TestInvalidStruct(t *testing.T) {
validate := New()
s := &SubTest{
@ -8286,7 +8215,6 @@ func TestInvalidStruct(t *testing.T) {
}
func TestInvalidValidatorFunction(t *testing.T) {
validate := New()
s := &SubTest{
@ -8297,7 +8225,6 @@ func TestInvalidValidatorFunction(t *testing.T) {
}
func TestCustomFieldName(t *testing.T) {
validate := New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("schema"), ",", 2)[0]
@ -8341,7 +8268,6 @@ func TestCustomFieldName(t *testing.T) {
}
func TestMutipleRecursiveExtractStructCache(t *testing.T) {
validate := New()
type Recursive struct {
@ -8358,7 +8284,6 @@ func TestMutipleRecursiveExtractStructCache(t *testing.T) {
ptr := fmt.Sprintf("%p", sc)
for i := 0; i < 100; i++ {
go func() {
<-proceed
sc := validate.extractStructCache(current, name)
@ -8371,7 +8296,6 @@ func TestMutipleRecursiveExtractStructCache(t *testing.T) {
// Thanks @robbrockbank, see https://github.com/go-playground/validator/issues/249
func TestPointerAndOmitEmpty(t *testing.T) {
validate := New()
type Test struct {
@ -8417,7 +8341,6 @@ func TestPointerAndOmitEmpty(t *testing.T) {
}
func TestRequired(t *testing.T) {
validate := New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@ -8441,7 +8364,6 @@ func TestRequired(t *testing.T) {
}
func TestBoolEqual(t *testing.T) {
validate := New()
type Test struct {
@ -8469,16 +8391,13 @@ func TestTranslations(t *testing.T) {
validate := New()
err := validate.RegisterTranslation("required", trans,
func(ut ut.Translator) (err error) {
// using this stype because multiple translation may have to be added for the full translation
if err = ut.Add("required", "{0} is a required field", false); err != nil {
return
}
return
}, func(ut ut.Translator, fe FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field())
if err != nil {
fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
@ -8491,16 +8410,13 @@ func TestTranslations(t *testing.T) {
err = validate.RegisterTranslation("required", fr,
func(ut ut.Translator) (err error) {
// using this stype because multiple translation may have to be added for the full translation
if err = ut.Add("required", "{0} est un champ obligatoire", false); err != nil {
return
}
return
}, func(ut ut.Translator, fe FieldError) string {
t, transErr := ut.T(fe.Tag(), fe.Field())
if transErr != nil {
fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
@ -8578,16 +8494,13 @@ func TestTranslationErrors(t *testing.T) {
validate := New()
err = validate.RegisterTranslation("required", trans,
func(ut ut.Translator) (err error) {
// using this stype because multiple translation may have to be added for the full translation
if err = ut.Add("required", "{0} is a required field", false); err != nil {
return
}
return
}, func(ut ut.Translator, fe FieldError) string {
t, err := ut.T(fe.Tag(), fe.Field())
if err != nil {
fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
@ -8602,7 +8515,6 @@ func TestTranslationErrors(t *testing.T) {
}
func TestStructFiltered(t *testing.T) {
p1 := func(ns []byte) bool {
if bytes.HasSuffix(ns, []byte("NoTag")) || bytes.HasSuffix(ns, []byte("Required")) {
return false
@ -8768,7 +8680,6 @@ func TestStructFiltered(t *testing.T) {
}
func TestRequiredPtr(t *testing.T) {
type Test struct {
Bool *bool `validate:"required"`
}
@ -8902,7 +8813,6 @@ func TestAlphaUnicodeValidation(t *testing.T) {
}
func TestAlphanumericUnicodeValidation(t *testing.T) {
tests := []struct {
param string
expected bool
@ -8945,7 +8855,6 @@ func TestAlphanumericUnicodeValidation(t *testing.T) {
}
func TestArrayStructNamespace(t *testing.T) {
validate := New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@ -8974,7 +8883,6 @@ func TestArrayStructNamespace(t *testing.T) {
}
func TestMapStructNamespace(t *testing.T) {
validate := New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@ -9655,7 +9563,6 @@ func TestURLEncodedValidation(t *testing.T) {
}
func TestKeys(t *testing.T) {
type Test struct {
Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey,endkeys,eq=testval" json:"test1"`
Test2 map[int]int `validate:"gt=0,dive,keys,eq=3,endkeys,eq=4" json:"test2"`
@ -9824,7 +9731,6 @@ func TestKeysCustomValidation(t *testing.T) {
}
func TestKeyOrs(t *testing.T) {
type Test struct {
Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey|eq=testkeyok,endkeys,eq=testval" json:"test1"`
}
@ -10602,7 +10508,6 @@ func TestRequiredWithAll(t *testing.T) {
}
func TestRequiredWithout(t *testing.T) {
type Inner struct {
Field *string
}
@ -10668,7 +10573,6 @@ func TestRequiredWithout(t *testing.T) {
}
func TestRequiredWithoutAll(t *testing.T) {
fieldVal := "test"
test := struct {
Field1 string `validate:"omitempty" json:"field_1"`
@ -10725,7 +10629,6 @@ func TestLookup(t *testing.T) {
}
func TestAbilityToValidateNils(t *testing.T) {
type TestStruct struct {
Test *string `validate:"nil"`
}
@ -10867,7 +10770,6 @@ func TestJSONValidation(t *testing.T) {
}
func Test_hostnameport_validator(t *testing.T) {
type Host struct {
Addr string `validate:"hostname_port"`
}
@ -10969,7 +10871,6 @@ func TestUppercaseValidation(t *testing.T) {
PanicMatches(t, func() {
_ = validate.Var(2, "uppercase")
}, "Bad field type int")
}
func TestDatetimeValidation(t *testing.T) {
@ -11225,42 +11126,154 @@ func TestBCP47LanguageTagValidation(t *testing.T) {
}
func TestBicIsoFormatValidation(t *testing.T) {
tests := []struct {
value string `validate:"bic"`
tag string
expected bool
}{
{"SBICKEN1345", "bic", true},
{"SBICKEN1", "bic", true},
{"SBICKENY", "bic", true},
{"SBICKEN1YYP", "bic", true},
{"SBIC23NXXX", "bic", false},
{"S23CKENXXXX", "bic", false},
{"SBICKENXX", "bic", false},
{"SBICKENXX9", "bic", false},
{"SBICKEN13458", "bic", false},
{"SBICKEN", "bic", false},
}
validate := New()
for i, test := range tests {
errs := validate.Var(test.value, test.tag)
if test.expected {
if !IsEqual(errs, nil) {
t.Fatalf("Index: %d bic failed Error: %s", i, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d bic failed Error: %s", i, errs)
} else {
val := getError(errs, "", "")
if val.Tag() != "bic" {
t.Fatalf("Index: %d bic failed Error: %s", i, errs)
}
}
}
}
}
tests := []struct {
value string `validate:"bic"`
tag string
expected bool
}{
{"SBICKEN1345", "bic", true},
{"SBICKEN1", "bic", true},
{"SBICKENY", "bic", true},
{"SBICKEN1YYP", "bic", true},
{"SBIC23NXXX", "bic", false},
{"S23CKENXXXX", "bic", false},
{"SBICKENXX", "bic", false},
{"SBICKENXX9", "bic", false},
{"SBICKEN13458", "bic", false},
{"SBICKEN", "bic", false},
}
validate := New()
for i, test := range tests {
errs := validate.Var(test.value, test.tag)
if test.expected {
if !IsEqual(errs, nil) {
t.Fatalf("Index: %d bic failed Error: %s", i, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d bic failed Error: %s", i, errs)
} else {
val := getError(errs, "", "")
if val.Tag() != "bic" {
t.Fatalf("Index: %d bic failed Error: %s", i, errs)
}
}
}
}
}
func TestPostCodeByIso3166Alpha2(t *testing.T) {
tests := map[string][]struct {
value string
expected bool
}{
"VN": {
{"ABC", false},
{"700000", true},
{"A1", false},
},
"GB": {
{"EC1A 1BB", true},
{"CF10 1B1H", false},
},
"VI": {
{"00803", true},
{"1234567", false},
},
"LC": { // not support regexp for post code
{"123456", false},
},
"XX": { // not support country
{"123456", false},
},
}
validate := New()
for cc, ccTests := range tests {
for i, test := range ccTests {
errs := validate.Var(test.value, fmt.Sprintf("postcode_iso3166_alpha2=%s", cc))
if test.expected {
if !IsEqual(errs, nil) {
t.Fatalf("Index: %d postcode_iso3166_alpha2=%s failed Error: %s", i, cc, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d postcode_iso3166_alpha2=%s failed Error: %s", i, cc, errs)
}
}
}
}
}
func TestPostCodeByIso3166Alpha2Field(t *testing.T) {
tests := []struct {
Value string `validate:"postcode_iso3166_alpha2_field=CountryCode"`
CountryCode interface{}
expected bool
}{
{"ABC", "VN", false},
{"700000", "VN", true},
{"A1", "VN", false},
{"EC1A 1BB", "GB", true},
{"CF10 1B1H", "GB", false},
{"00803", "VI", true},
{"1234567", "VI", false},
{"123456", "LC", false}, // not support regexp for post code
{"123456", "XX", false}, // not support country
}
validate := New()
for i, test := range tests {
errs := validate.Struct(test)
if test.expected {
if !IsEqual(errs, nil) {
t.Fatalf("Index: %d postcode_iso3166_alpha2_field=CountryCode failed Error: %s", i, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d postcode_iso3166_alpha2_field=CountryCode failed Error: %s", i, errs)
}
}
}
}
func TestPostCodeByIso3166Alpha2Field_WrongField(t *testing.T) {
type test struct {
Value string `validate:"postcode_iso3166_alpha2_field=CountryCode"`
CountryCode1 interface{}
expected bool
}
errs := New().Struct(test{"ABC", "VN", false})
assert.NotEqual(t, nil, errs)
}
func TestPostCodeByIso3166Alpha2Field_MissingParam(t *testing.T) {
type test struct {
Value string `validate:"postcode_iso3166_alpha2_field="`
CountryCode1 interface{}
expected bool
}
errs := New().Struct(test{"ABC", "VN", false})
assert.NotEqual(t, nil, errs)
}
func TestPostCodeByIso3166Alpha2Field_InvalidKind(t *testing.T) {
type test struct {
Value string `validate:"postcode_iso3166_alpha2_field=CountryCode"`
CountryCode interface{}
expected bool
}
defer func() { recover() }()
_ = New().Struct(test{"ABC", 123, false})
t.Errorf("Didn't panic as expected")
}

Loading…
Cancel
Save