Skip to content

Commit

Permalink
Including regex version validation (#831)
Browse files Browse the repository at this point in the history
  • Loading branch information
jtseng-godaddy authored Jan 2, 2022
1 parent 8fe074c commit 06ec79d
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ Baked-in Validations
| uuid5 | Universally Unique Identifier UUID v5 |
| uuid5_rfc4122 | Universally Unique Identifier UUID v5 RFC4122 |
| uuid_rfc4122 | Universally Unique Identifier UUID RFC4122 |
| semver | Semantic Versioning 2.0.0 |
| ulid | Universally Unique Lexicographically Sortable Identifier ULID |

### Comparisons:
Expand Down
8 changes: 8 additions & 0 deletions baked_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ var (
"postcode_iso3166_alpha2": isPostcodeByIso3166Alpha2,
"postcode_iso3166_alpha2_field": isPostcodeByIso3166Alpha2Field,
"bic": isIsoBicFormat,
"semver": isSemverFormat,
"dns_rfc1035_label": isDnsRFC1035LabelFormat,
}
)
Expand Down Expand Up @@ -2421,6 +2422,13 @@ func isIsoBicFormat(fl FieldLevel) bool {
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
// for validating if the current field's value is
// a valid dns RFC 1035 label, defined in RFC 1035.
Expand Down
6 changes: 6 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,12 @@ More information on https://golang.org/pkg/time/#LoadLocation
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
Expand Down
2 changes: 2 additions & 0 deletions regexes.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const (
jWTRegexString = "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$"
splitParamsRegexString = `'[^']*'|\S+`
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}$"
)

Expand Down Expand Up @@ -105,5 +106,6 @@ var (
jWTRegex = regexp.MustCompile(jWTRegexString)
splitParamsRegex = regexp.MustCompile(splitParamsRegexString)
bicRegex = regexp.MustCompile(bicRegexString)
semverRegex = regexp.MustCompile(semverRegexString)
dnsRegexRFC1035Label = regexp.MustCompile(dnsRegexStringRFC1035Label)
)
78 changes: 78 additions & 0 deletions validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
tests := []struct {
value string `validate:"dns_rfc1035_label"`
Expand Down

0 comments on commit 06ec79d

Please sign in to comment.