Skip to content

Commit

Permalink
validation: add StringIsEmpty, StringIsBase64, GUID, GUIDOrEmpty
Browse files Browse the repository at this point in the history
  • Loading branch information
katbyte committed Jan 14, 2020
1 parent 08371e8 commit cbd4193
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/terraform-plugin-sdk.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions helper/validation/guid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package validation

import (
"fmt"
"regexp"

"github.com/hashicorp/go-uuid"
)

var GUIDRegExp = regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")

func GUID(i interface{}, k string) (warnings []string, errors []error) {
v, ok := i.(string)
if !ok {
errors = append(errors, fmt.Errorf("expected type of %q to be string", k))
return
}

if _, err := uuid.ParseUUID(v); err != nil {
errors = append(errors, fmt.Errorf("%q isn't a valid UUID (%q): %+v", k, v, err))
}

return warnings, errors
}

func GUIDOrEmpty(i interface{}, k string) (warnings []string, errors []error) {
v, ok := i.(string)
if !ok {
errors = append(errors, fmt.Errorf("expected type of %q to be string", k))
return
}

if v == "" {
return
}

return GUID(i, k)
}
85 changes: 85 additions & 0 deletions helper/validation/guid_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package validation

import (
"testing"
)

func TestGUID(t *testing.T) {
cases := map[string]struct {
Value interface{}
Error bool
}{
"NotString": {
Value: 7,
Error: true,
},
"Empty": {
Value: "",
Error: true,
},
"InvalidGuid": {
Value: "00000000-0000-123-0000-000000000000",
Error: true,
},
"ValidGuidWithOutDashs": {
Value: "12345678123412341234123456789012",
Error: true,
},
"ValidGuid": {
Value: "00000000-0000-0000-0000-000000000000",
Error: false,
},
}

for tn, tc := range cases {
t.Run(tn, func(t *testing.T) {
_, errors := StringIsBase64(tc.Value, tn)

if len(errors) > 0 && !tc.Error {
t.Errorf("%s: GUID(%s) produced an unexpected error", tn, errors)
} else if len(errors) == 0 && tc.Error {
t.Errorf("%s: GUID(%s) did not error", tn, errors)
}
})
}
}

func TestGUIDorEmpty(t *testing.T) {
cases := map[string]struct {
Value interface{}
Error bool
}{
"NotString": {
Value: 7,
Error: false,
},
"Empty": {
Value: "",
Error: true,
},
"InvalidGuid": {
Value: "00000000-0000-123-0000-000000000000",
Error: true,
},
"ValidGuidWithOutDashs": {
Value: "12345678123412341234123456789012",
Error: true,
},
"ValidGuid": {
Value: "00000000-0000-0000-0000-000000000000",
Error: false,
},
}

for tn, tc := range cases {
t.Run(tn, func(t *testing.T) {
_, errors := StringIsBase64(tc.Value, tn)

if len(errors) > 0 && !tc.Error {
t.Errorf("%s: GUIDOrEmpty(%s) produced an unexpected error", tn, errors)
} else if len(errors) == 0 && tc.Error {
t.Errorf("%s: GUIDOrEmpty(%s) did not error", tn, errors)
}
})
}
}
36 changes: 36 additions & 0 deletions helper/validation/strings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package validation

import (
"encoding/base64"
"fmt"
"strings"
)

// NoEmptyStrings validates that the string is not just whitespace characters (equal to [\r\n\t\f\v ])
func StringIsNotEmpty(i interface{}, k string) ([]string, []error) {
v, ok := i.(string)
if !ok {
return nil, []error{fmt.Errorf("expected type of %q to be string", k)}
}

if strings.TrimSpace(v) == "" {
return nil, []error{fmt.Errorf("expected %q it not be an empty string (whitespace not allowed)", k)}
}

return nil, nil
}

func StringIsBase64(i interface{}, k string) (warnings []string, errors []error) {
// Empty string is not allowed
if warnings, errors = StringIsNotEmpty(i, k); len(errors) > 0 {
return
}

// NoEmptyStrings checks it is a string
v, _ := i.(string)
if _, err := base64.StdEncoding.DecodeString(v); err != nil {
errors = append(errors, fmt.Errorf("expected %w to be a base64 string, got %v", k, v))
}

return
}
118 changes: 118 additions & 0 deletions helper/validation/strings_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package validation

import (
"testing"
)

func TestStringIsNotEmpty(t *testing.T) {
cases := map[string]struct {
Value interface{}
Error bool
}{
"NotString": {
Value: 7,
Error: true,
},
"Empty": {
Value: "",
Error: true,
},
"SingleSpace": {
Value: " ",
Error: true,
},
"MultipleSpaces": {
Value: " ",
Error: true,
},
"CarriageReturn": {
Value: "\r",
Error: true,
},
"NewLine": {
Value: "\n",
Error: true,
},
"Tab": {
Value: "\t",
Error: true,
},
"FormFeed": {
Value: "\f",
Error: true,
},
"VerticalTab": {
Value: "\v",
Error: true,
},
"SingleChar": {
Value: "\v",
Error: true,
},
"MultipleChars": {
Value: "-_-",
Error: false,
},
"Sentence": {
Value: "Hello kt's sentence.",
Error: false,
},

"StartsWithWhitespace": {
Value: " 7",
Error: false,
},
"EndsWithWhitespace": {
Value: "7 ",
Error: false,
},
}

for tn, tc := range cases {
t.Run(tn, func(t *testing.T) {
_, errors := StringIsNotEmpty(tc.Value, tn)

if len(errors) > 0 && !tc.Error {
t.Errorf("%s: StringIsNotEmpty(%s) produced an unexpected error", tn, errors)
} else if len(errors) == 0 && tc.Error {
t.Errorf("%s: StringIsNotEmpty(%s) did not error", tn, errors)
}
})
}
}

func TestStringIsBase64(t *testing.T) {
cases := map[string]struct {
Value interface{}
Error bool
}{
"NotString": {
Value: 7,
Error: true,
},
"Empty": {
Value: "",
Error: true,
},
"NotBase64": {
Value: "Do'h!",
Error: true,
},
"Base64": {
Value: "RG8naCE=",
Error: false,
},
}

for tn, tc := range cases {
t.Run(tn, func(t *testing.T) {
_, errors := StringIsBase64(tc.Value, tn)

if len(errors) > 0 && !tc.Error {
t.Errorf("%s: StringIsBase64(%s) produced an unexpected error", tn, errors)
} else if len(errors) == 0 && tc.Error {
t.Errorf("%s: StringIsBase64(%s) did not error", tn, errors)
}
})
}
}

0 comments on commit cbd4193

Please sign in to comment.