From dac7298ca769c6eaad6c2e09429fb4a9cc8b9ecc Mon Sep 17 00:00:00 2001 From: Onur Cinar Date: Thu, 26 Dec 2024 18:46:58 -0800 Subject: [PATCH] Add FQDN validation checker and tests to v2. (#135) # Describe Request Add FQDN validation checker and tests to v2. # Change Type New code. --- v2/fqdn.go | 43 ++++++++++++++++++++++++++++ v2/fqdn_test.go | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ v2/maker.go | 1 + 3 files changed, 120 insertions(+) create mode 100644 v2/fqdn.go create mode 100644 v2/fqdn_test.go diff --git a/v2/fqdn.go b/v2/fqdn.go new file mode 100644 index 0000000..899edec --- /dev/null +++ b/v2/fqdn.go @@ -0,0 +1,43 @@ +// Copyright (c) 2023-2024 Onur Cinar. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. +// https://github.com/cinar/checker + +package v2 + +import ( + "reflect" + "regexp" +) + +const ( + // nameFQDN is the name of the FQDN check. + nameFQDN = "fqdn" +) + +var ( + // ErrNotFQDN indicates that the given value is not a valid FQDN. + ErrNotFQDN = NewCheckError("FQDN") + + // fqdnRegex is the regular expression for validating FQDN. + fqdnRegex = regexp.MustCompile(`^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$`) +) + +// IsFQDN checks if the value is a valid fully qualified domain name (FQDN). +func IsFQDN(value string) (string, error) { + if !fqdnRegex.MatchString(value) { + return value, ErrNotFQDN + } + return value, nil +} + +// checkFQDN checks if the value is a valid fully qualified domain name (FQDN). +func checkFQDN(value reflect.Value) (reflect.Value, error) { + _, err := IsFQDN(value.Interface().(string)) + return value, err +} + +// makeFQDN makes a checker function for the FQDN checker. +func makeFQDN(_ string) CheckFunc[reflect.Value] { + return checkFQDN +} \ No newline at end of file diff --git a/v2/fqdn_test.go b/v2/fqdn_test.go new file mode 100644 index 0000000..8ffc8ed --- /dev/null +++ b/v2/fqdn_test.go @@ -0,0 +1,76 @@ +// Copyright (c) 2023-2024 Onur Cinar. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. +// https://github.com/cinar/checker + +package v2_test + +import ( + "fmt" + "testing" + + v2 "github.com/cinar/checker/v2" +) + +func ExampleIsFQDN() { + _, err := v2.IsFQDN("example.com") + if err != nil { + fmt.Println(err) + } +} + +func TestIsFQDNInvalid(t *testing.T) { + _, err := v2.IsFQDN("invalid_fqdn") + if err == nil { + t.Fatal("expected error") + } +} + +func TestIsFQDNValid(t *testing.T) { + _, err := v2.IsFQDN("example.com") + if err != nil { + t.Fatal(err) + } +} + +func TestCheckFQDNNonString(t *testing.T) { + defer FailIfNoPanic(t, "expected panic") + + type Domain struct { + Name int `checkers:"fqdn"` + } + + domain := &Domain{} + + v2.CheckStruct(domain) +} + +func TestCheckFQDNInvalid(t *testing.T) { + type Domain struct { + Name string `checkers:"fqdn"` + } + + domain := &Domain{ + Name: "invalid_fqdn", + } + + _, ok := v2.CheckStruct(domain) + if ok { + t.Fatal("expected error") + } +} + +func TestCheckFQDNValid(t *testing.T) { + type Domain struct { + Name string `checkers:"fqdn"` + } + + domain := &Domain{ + Name: "example.com", + } + + _, ok := v2.CheckStruct(domain) + if !ok { + t.Fatal("expected valid") + } +} diff --git a/v2/maker.go b/v2/maker.go index 6841aea..e4df7fb 100644 --- a/v2/maker.go +++ b/v2/maker.go @@ -21,6 +21,7 @@ var makers = map[string]MakeCheckFunc{ nameCIDR: makeCIDR, nameDigits: makeDigits, nameEmail: makeEmail, + nameFQDN: makeFQDN, nameMaxLen: makeMaxLen, nameMinLen: makeMinLen, nameRequired: makeRequired,