Including regex version validation (#831)

pull/875/head
jtseng-godaddy 3 years ago committed by GitHub
parent 8fe074c546
commit 06ec79d987
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      README.md
  2. 8
      baked_in.go
  3. 6
      doc.go
  4. 2
      regexes.go
  5. 78
      validator_test.go

@ -189,6 +189,7 @@ Baked-in Validations
| uuid5 | Universally Unique Identifier UUID v5 | | uuid5 | Universally Unique Identifier UUID v5 |
| uuid5_rfc4122 | Universally Unique Identifier UUID v5 RFC4122 | | uuid5_rfc4122 | Universally Unique Identifier UUID v5 RFC4122 |
| uuid_rfc4122 | Universally Unique Identifier UUID RFC4122 | | uuid_rfc4122 | Universally Unique Identifier UUID RFC4122 |
| semver | Semantic Versioning 2.0.0 |
| ulid | Universally Unique Lexicographically Sortable Identifier ULID | | ulid | Universally Unique Lexicographically Sortable Identifier ULID |
### Comparisons: ### Comparisons:

@ -199,6 +199,7 @@ var (
"postcode_iso3166_alpha2": isPostcodeByIso3166Alpha2, "postcode_iso3166_alpha2": isPostcodeByIso3166Alpha2,
"postcode_iso3166_alpha2_field": isPostcodeByIso3166Alpha2Field, "postcode_iso3166_alpha2_field": isPostcodeByIso3166Alpha2Field,
"bic": isIsoBicFormat, "bic": isIsoBicFormat,
"semver": isSemverFormat,
"dns_rfc1035_label": isDnsRFC1035LabelFormat, "dns_rfc1035_label": isDnsRFC1035LabelFormat,
} }
) )
@ -2421,6 +2422,13 @@ func isIsoBicFormat(fl FieldLevel) bool {
return bicRegex.MatchString(bicString) return bicRegex.MatchString(bicString)
} }
// isSemverFormat is the validation function for validating if the current field's value is a valid semver version, defined in Semantic Versioning 2.0.0
func isSemverFormat(fl FieldLevel) bool {
semverString := fl.Field().String()
return semverRegex.MatchString(semverString)
}
// isDnsRFC1035LabelFormat is the validation function // isDnsRFC1035LabelFormat is the validation function
// for validating if the current field's value is // for validating if the current field's value is
// a valid dns RFC 1035 label, defined in RFC 1035. // a valid dns RFC 1035 label, defined in RFC 1035.

@ -1276,6 +1276,12 @@ More information on https://golang.org/pkg/time/#LoadLocation
Usage: timezone Usage: timezone
Semantic Version
This validates that a string value is a valid semver version, defined in Semantic Versioning 2.0.0.
More information on https://semver.org/
Usage: semver
Alias Validators and Tags Alias Validators and Tags

@ -52,6 +52,7 @@ const (
jWTRegexString = "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$" jWTRegexString = "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$"
splitParamsRegexString = `'[^']*'|\S+` splitParamsRegexString = `'[^']*'|\S+`
bicRegexString = `^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$` bicRegexString = `^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$`
semverRegexString = `^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$` // numbered capture groups https://semver.org/
dnsRegexStringRFC1035Label = "^[a-z]([-a-z0-9]*[a-z0-9]){0,62}$" dnsRegexStringRFC1035Label = "^[a-z]([-a-z0-9]*[a-z0-9]){0,62}$"
) )
@ -105,5 +106,6 @@ var (
jWTRegex = regexp.MustCompile(jWTRegexString) jWTRegex = regexp.MustCompile(jWTRegexString)
splitParamsRegex = regexp.MustCompile(splitParamsRegexString) splitParamsRegex = regexp.MustCompile(splitParamsRegexString)
bicRegex = regexp.MustCompile(bicRegexString) bicRegex = regexp.MustCompile(bicRegexString)
semverRegex = regexp.MustCompile(semverRegexString)
dnsRegexRFC1035Label = regexp.MustCompile(dnsRegexStringRFC1035Label) dnsRegexRFC1035Label = regexp.MustCompile(dnsRegexStringRFC1035Label)
) )

@ -11383,6 +11383,84 @@ func TestBicIsoFormatValidation(t *testing.T) {
} }
} }
func TestSemverFormatValidation(t *testing.T) {
tests := []struct {
value string `validate:"semver"`
tag string
expected bool
}{
{"1.2.3", "semver", true},
{"10.20.30", "semver", true},
{"1.1.2-prerelease+meta", "semver", true},
{"1.1.2+meta", "semver", true},
{"1.1.2+meta-valid", "semver", true},
{"1.0.0-alpha", "semver", true},
{"1.0.0-alpha.1", "semver", true},
{"1.0.0-alpha.beta", "semver", true},
{"1.0.0-alpha.beta.1", "semver", true},
{"1.0.0-alpha0.valid", "semver", true},
{"1.0.0-alpha.0valid", "semver", true},
{"1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay", "semver", true},
{"1.0.0-rc.1+build.1", "semver", true},
{"1.0.0-rc.1+build.123", "semver", true},
{"1.2.3-beta", "semver", true},
{"1.2.3-DEV-SNAPSHOT", "semver", true},
{"1.2.3-SNAPSHOT-123", "semver", true},
{"2.0.0+build.1848", "semver", true},
{"2.0.1-alpha.1227", "semver", true},
{"1.0.0-alpha+beta", "semver", true},
{"1.2.3----RC-SNAPSHOT.12.9.1--.12+788", "semver", true},
{"1.2.3----R-S.12.9.1--.12+meta", "semver", true},
{"1.2.3----RC-SNAPSHOT.12.9.1--.12", "semver", true},
{"1.0.0+0.build.1-rc.10000aaa-kk-0.1", "semver", true},
{"99999999999999999999999.999999999999999999.99999999999999999", "semver", true},
{"1.0.0-0A.is.legal", "semver", true},
{"1", "semver", false},
{"1.2", "semver", false},
{"1.2.3-0123", "semver", false},
{"1.2.3-0123.0123", "semver", false},
{"1.1.2+.123", "semver", false},
{"+invalid", "semver", false},
{"-invalid", "semver", false},
{"-invalid+invalid", "semver", false},
{"alpha", "semver", false},
{"alpha.beta.1", "semver", false},
{"alpha.1", "semver", false},
{"1.0.0-alpha_beta", "semver", false},
{"1.0.0-alpha_beta", "semver", false},
{"1.0.0-alpha...1", "semver", false},
{"01.1.1", "semver", false},
{"1.01.1", "semver", false},
{"1.1.01", "semver", false},
{"1.2", "semver", false},
{"1.2.Dev", "semver", false},
{"1.2.3.Dev", "semver", false},
{"1.2-SNAPSHOT", "semver", 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 semver failed Error: %s", i, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d semver failed Error: %s", i, errs)
} else {
val := getError(errs, "", "")
if val.Tag() != "semver" {
t.Fatalf("Index: %d semver failed Error: %s", i, errs)
}
}
}
}
}
func TestRFC1035LabelFormatValidation(t *testing.T) { func TestRFC1035LabelFormatValidation(t *testing.T) {
tests := []struct { tests := []struct {
value string `validate:"dns_rfc1035_label"` value string `validate:"dns_rfc1035_label"`

Loading…
Cancel
Save