mirror of
https://github.com/romdo/go-validate.git
synced 2026-02-19 08:06:40 +00:00
wip(helpers): unfinished addition of various helpers
This commit is contained in:
180
helpers.go
180
helpers.go
@@ -1,7 +1,9 @@
|
|||||||
package validate
|
package validate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RequireField returns a Error type for the given field if provided value is
|
// RequireField returns a Error type for the given field if provided value is
|
||||||
@@ -34,3 +36,181 @@ func RequireField(field string, value interface{}) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func InRange(field string, value interface{}, min, max float64) error {
|
||||||
|
if value == nil {
|
||||||
|
return &Error{Field: field, Msg: "cannot be nil"}
|
||||||
|
}
|
||||||
|
|
||||||
|
kind := reflect.TypeOf(value).Kind()
|
||||||
|
var floatValue float64
|
||||||
|
|
||||||
|
switch kind { //nolint:exhaustive
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
floatValue = float64(reflect.ValueOf(value).Int())
|
||||||
|
case reflect.Uint,
|
||||||
|
reflect.Uint8,
|
||||||
|
reflect.Uint16,
|
||||||
|
reflect.Uint32,
|
||||||
|
reflect.Uint64:
|
||||||
|
floatValue = float64(reflect.ValueOf(value).Uint())
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
floatValue = reflect.ValueOf(value).Float()
|
||||||
|
default:
|
||||||
|
return &Error{
|
||||||
|
Field: field,
|
||||||
|
Msg: fmt.Sprintf("unsupported type %T for InRange", value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if floatValue < min || floatValue > max {
|
||||||
|
return &Error{
|
||||||
|
Field: field,
|
||||||
|
Msg: fmt.Sprintf("must be in range [%.6f, %.6f]", min, max),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MinLength(field string, value interface{}, minLength int) error {
|
||||||
|
if value == nil {
|
||||||
|
return &Error{Field: field, Msg: "cannot be nil"}
|
||||||
|
}
|
||||||
|
|
||||||
|
if minLength < 0 {
|
||||||
|
return &Error{Field: field, Msg: "minLength must be non-negative"}
|
||||||
|
}
|
||||||
|
|
||||||
|
kind := reflect.TypeOf(value).Kind()
|
||||||
|
var length int
|
||||||
|
|
||||||
|
switch kind { //nolint:exhaustive
|
||||||
|
case reflect.String:
|
||||||
|
length = len(reflect.ValueOf(value).String())
|
||||||
|
case reflect.Slice, reflect.Array, reflect.Map:
|
||||||
|
length = reflect.ValueOf(value).Len()
|
||||||
|
default:
|
||||||
|
return &Error{
|
||||||
|
Field: field,
|
||||||
|
Msg: fmt.Sprintf("unsupported type %T for MinLength", value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if length < minLength {
|
||||||
|
return &Error{
|
||||||
|
Field: field,
|
||||||
|
Msg: fmt.Sprintf("must have a minimum length of %d", minLength),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MaxLength(field string, value interface{}, maxLength int) error {
|
||||||
|
if value == nil {
|
||||||
|
return &Error{Field: field, Msg: "cannot be nil"}
|
||||||
|
}
|
||||||
|
|
||||||
|
if maxLength < 0 {
|
||||||
|
return &Error{Field: field, Msg: "maxLength must be non-negative"}
|
||||||
|
}
|
||||||
|
|
||||||
|
kind := reflect.TypeOf(value).Kind()
|
||||||
|
var length int
|
||||||
|
|
||||||
|
switch kind { //nolint:exhaustive
|
||||||
|
case reflect.String:
|
||||||
|
length = len(reflect.ValueOf(value).String())
|
||||||
|
case reflect.Slice, reflect.Array, reflect.Map:
|
||||||
|
length = reflect.ValueOf(value).Len()
|
||||||
|
default:
|
||||||
|
return &Error{
|
||||||
|
Field: field,
|
||||||
|
Msg: fmt.Sprintf("unsupported type %T for MaxLength", value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if length > maxLength {
|
||||||
|
return &Error{
|
||||||
|
Field: field,
|
||||||
|
Msg: fmt.Sprintf("must have a maximum length of %d", maxLength),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchesRegexp checks if the value of a field matches the specified regular
|
||||||
|
// expression. It returns an error if the value doesn't match the pattern.
|
||||||
|
func MatchRegexp(
|
||||||
|
field string,
|
||||||
|
value interface{},
|
||||||
|
pattern *regexp.Regexp,
|
||||||
|
) error {
|
||||||
|
if pattern == nil {
|
||||||
|
return &Error{Field: field, Msg: "pattern cannot be nil"}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v := value.(type) {
|
||||||
|
case string:
|
||||||
|
if !pattern.MatchString(v) {
|
||||||
|
return &Error{
|
||||||
|
Field: field,
|
||||||
|
Msg: fmt.Sprintf(
|
||||||
|
"does not match pattern '%s': '%s'", pattern, v,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case []byte:
|
||||||
|
if !pattern.Match(v) {
|
||||||
|
return &Error{
|
||||||
|
Field: field,
|
||||||
|
Msg: fmt.Sprintf(
|
||||||
|
"does not match pattern '%s': '%s'", pattern, string(v),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return &Error{
|
||||||
|
Field: field,
|
||||||
|
Msg: fmt.Sprintf(
|
||||||
|
"unsupported type %T for MatchRegexp", value,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NotNil(field string, value interface{}) error {
|
||||||
|
val := reflect.ValueOf(value)
|
||||||
|
kind := val.Kind()
|
||||||
|
isNil := false
|
||||||
|
|
||||||
|
if kind == reflect.Ptr && !val.IsNil() {
|
||||||
|
val = val.Elem()
|
||||||
|
kind = val.Kind()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch kind { //nolint:exhaustive
|
||||||
|
case reflect.Chan,
|
||||||
|
reflect.Func,
|
||||||
|
reflect.Interface,
|
||||||
|
reflect.Map,
|
||||||
|
reflect.Slice,
|
||||||
|
reflect.Ptr:
|
||||||
|
if val.IsNil() {
|
||||||
|
isNil = true
|
||||||
|
}
|
||||||
|
case reflect.Invalid:
|
||||||
|
isNil = true
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
if isNil {
|
||||||
|
return &Error{Field: field, Msg: "must not be nil"}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
560
helpers_test.go
560
helpers_test.go
@@ -1,6 +1,9 @@
|
|||||||
package validate
|
package validate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -404,3 +407,560 @@ func TestRequireField(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInRange(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
field string
|
||||||
|
value interface{}
|
||||||
|
min float64
|
||||||
|
max float64
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "int in range",
|
||||||
|
args: args{
|
||||||
|
field: "Age",
|
||||||
|
value: int(25),
|
||||||
|
min: 18,
|
||||||
|
max: 65,
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "int below range",
|
||||||
|
args: args{
|
||||||
|
field: "Age",
|
||||||
|
value: int(15),
|
||||||
|
min: 18,
|
||||||
|
max: 65,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Age",
|
||||||
|
Msg: "must be in range [18.000000, 65.000000]",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "int above range",
|
||||||
|
args: args{
|
||||||
|
field: "Age",
|
||||||
|
value: int(70),
|
||||||
|
min: 18,
|
||||||
|
max: 65,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Age",
|
||||||
|
Msg: "must be in range [18.000000, 65.000000]",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "float in range",
|
||||||
|
args: args{
|
||||||
|
field: "Rating",
|
||||||
|
value: float64(4.5),
|
||||||
|
min: 1,
|
||||||
|
max: 5,
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "float below range",
|
||||||
|
args: args{
|
||||||
|
field: "Rating",
|
||||||
|
value: float64(0.5),
|
||||||
|
min: 1,
|
||||||
|
max: 5,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Rating",
|
||||||
|
Msg: "must be in range [1.000000, 5.000000]",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "float above range",
|
||||||
|
args: args{
|
||||||
|
field: "Rating",
|
||||||
|
value: float64(5.5),
|
||||||
|
min: 1,
|
||||||
|
max: 5,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Rating",
|
||||||
|
Msg: "must be in range [1.000000, 5.000000]",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unsupported type",
|
||||||
|
args: args{
|
||||||
|
field: "Tags",
|
||||||
|
value: []string{"tag1", "tag2"},
|
||||||
|
min: 1,
|
||||||
|
max: 5,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Tags",
|
||||||
|
Msg: "unsupported type []string for InRange",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := InRange(
|
||||||
|
tt.args.field,
|
||||||
|
tt.args.value,
|
||||||
|
tt.args.min,
|
||||||
|
tt.args.max,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMinLength(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
field string
|
||||||
|
value interface{}
|
||||||
|
minLength int
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil",
|
||||||
|
args: args{
|
||||||
|
field: "Title",
|
||||||
|
value: nil,
|
||||||
|
minLength: 5,
|
||||||
|
},
|
||||||
|
want: &Error{Field: "Title", Msg: "cannot be nil"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "negative minLength",
|
||||||
|
args: args{
|
||||||
|
field: "Title",
|
||||||
|
value: "hello",
|
||||||
|
minLength: -1,
|
||||||
|
},
|
||||||
|
want: &Error{Field: "Title", Msg: "minLength must be non-negative"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "string valid",
|
||||||
|
args: args{
|
||||||
|
field: "Title",
|
||||||
|
value: "hello",
|
||||||
|
minLength: 5,
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "string invalid",
|
||||||
|
args: args{
|
||||||
|
field: "Title",
|
||||||
|
value: "hello",
|
||||||
|
minLength: 6,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Title",
|
||||||
|
Msg: "must have a minimum length of 6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "slice valid",
|
||||||
|
args: args{
|
||||||
|
field: "Tags",
|
||||||
|
value: []string{"tag1", "tag2"},
|
||||||
|
minLength: 1,
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "slice invalid",
|
||||||
|
args: args{
|
||||||
|
field: "Tags",
|
||||||
|
value: []string{"tag1", "tag2"},
|
||||||
|
minLength: 3,
|
||||||
|
},
|
||||||
|
want: &Error{Field: "Tags", Msg: "must have a minimum length of 3"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "map valid",
|
||||||
|
args: args{
|
||||||
|
field: "Lookup",
|
||||||
|
value: map[string]string{"foo": "bar"},
|
||||||
|
minLength: 1,
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "map invalid",
|
||||||
|
args: args{
|
||||||
|
field: "Lookup",
|
||||||
|
value: map[string]string{"foo": "bar"},
|
||||||
|
minLength: 2,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Lookup",
|
||||||
|
Msg: "must have a minimum length of 2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unsupported type",
|
||||||
|
args: args{
|
||||||
|
field: "Number",
|
||||||
|
value: 123,
|
||||||
|
minLength: 2,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Number",
|
||||||
|
Msg: "unsupported type int for MinLength",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := MinLength(tt.args.field, tt.args.value, tt.args.minLength)
|
||||||
|
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMaxLength(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
field string
|
||||||
|
value interface{}
|
||||||
|
maxLength int
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil",
|
||||||
|
args: args{
|
||||||
|
field: "Title",
|
||||||
|
value: nil,
|
||||||
|
maxLength: 5,
|
||||||
|
},
|
||||||
|
want: &Error{Field: "Title", Msg: "cannot be nil"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "negative maxLength",
|
||||||
|
args: args{
|
||||||
|
field: "Title",
|
||||||
|
value: "hello",
|
||||||
|
maxLength: -1,
|
||||||
|
},
|
||||||
|
want: &Error{Field: "Title", Msg: "maxLength must be non-negative"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "string valid",
|
||||||
|
args: args{
|
||||||
|
field: "Title",
|
||||||
|
value: "hello",
|
||||||
|
maxLength: 5,
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "string invalid",
|
||||||
|
args: args{
|
||||||
|
field: "Title",
|
||||||
|
value: "hello",
|
||||||
|
maxLength: 4,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Title",
|
||||||
|
Msg: "must have a maximum length of 4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "slice valid",
|
||||||
|
args: args{
|
||||||
|
field: "Tags",
|
||||||
|
value: []string{"tag1", "tag2"},
|
||||||
|
maxLength: 2,
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "slice invalid",
|
||||||
|
args: args{
|
||||||
|
field: "Tags",
|
||||||
|
value: []string{"tag1", "tag2"},
|
||||||
|
maxLength: 1,
|
||||||
|
},
|
||||||
|
want: &Error{Field: "Tags", Msg: "must have a maximum length of 1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "map valid",
|
||||||
|
args: args{
|
||||||
|
field: "Lookup",
|
||||||
|
value: map[string]string{"foo": "bar"},
|
||||||
|
maxLength: 1,
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "map invalid",
|
||||||
|
args: args{
|
||||||
|
field: "Lookup",
|
||||||
|
value: map[string]string{"foo": "bar"},
|
||||||
|
maxLength: 0,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Lookup",
|
||||||
|
Msg: "must have a maximum length of 0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unsupported type",
|
||||||
|
args: args{
|
||||||
|
field: "Number",
|
||||||
|
value: 42,
|
||||||
|
maxLength: 5,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Number",
|
||||||
|
Msg: "unsupported type int for MaxLength",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := MaxLength(tt.args.field, tt.args.value, tt.args.maxLength)
|
||||||
|
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMatchRegexp(t *testing.T) {
|
||||||
|
usernameRegexp := regexp.MustCompile(`^[a-z]+\d+$`)
|
||||||
|
passwordRegexp := regexp.MustCompile(`^.*[A-Z]+.*$`)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
field string
|
||||||
|
value interface{}
|
||||||
|
pattern *regexp.Regexp
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "string matches pattern",
|
||||||
|
args: args{
|
||||||
|
field: "username",
|
||||||
|
value: "johndoe123",
|
||||||
|
pattern: usernameRegexp,
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "string does not match pattern",
|
||||||
|
args: args{
|
||||||
|
field: "username",
|
||||||
|
value: "JohnDoe123",
|
||||||
|
pattern: usernameRegexp,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "username",
|
||||||
|
Msg: "does not match pattern '^[a-z]+\\d+$': 'JohnDoe123'",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "byte slice matches pattern",
|
||||||
|
args: args{
|
||||||
|
field: "username",
|
||||||
|
value: []byte("johndoe123"),
|
||||||
|
pattern: usernameRegexp,
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "byte slice does not match pattern",
|
||||||
|
args: args{
|
||||||
|
field: "username",
|
||||||
|
value: []byte("JohnDoe123"),
|
||||||
|
pattern: usernameRegexp,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "username",
|
||||||
|
Msg: "does not match pattern '^[a-z]+\\d+$': 'JohnDoe123'",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unsupported type",
|
||||||
|
args: args{
|
||||||
|
field: "password",
|
||||||
|
value: 123456,
|
||||||
|
pattern: passwordRegexp,
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "password",
|
||||||
|
Msg: "unsupported type int for MatchRegexp",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := MatchRegexp(tt.args.field, tt.args.value, tt.args.pattern)
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotNil(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
field string
|
||||||
|
value interface{}
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil pointer",
|
||||||
|
args: args{
|
||||||
|
field: "Name",
|
||||||
|
value: (*string)(nil),
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Name",
|
||||||
|
Msg: "must not be nil",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-nil pointer",
|
||||||
|
args: args{
|
||||||
|
field: "Name",
|
||||||
|
value: new(string),
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil slice",
|
||||||
|
args: args{
|
||||||
|
field: "Tags",
|
||||||
|
value: []string(nil),
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Tags",
|
||||||
|
Msg: "must not be nil",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-nil slice",
|
||||||
|
args: args{
|
||||||
|
field: "Tags",
|
||||||
|
value: []string{},
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil map",
|
||||||
|
args: args{
|
||||||
|
field: "Metadata",
|
||||||
|
value: map[string]string(nil),
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Metadata",
|
||||||
|
Msg: "must not be nil",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-nil map",
|
||||||
|
args: args{
|
||||||
|
field: "Metadata",
|
||||||
|
value: map[string]string{},
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil interface",
|
||||||
|
args: args{
|
||||||
|
field: "Data",
|
||||||
|
value: fmt.Stringer(nil),
|
||||||
|
},
|
||||||
|
want: &Error{Field: "Data", Msg: "must not be nil"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-nil interface",
|
||||||
|
args: args{
|
||||||
|
field: "Data",
|
||||||
|
// Using *bytes.Buffer as an example of a non-nil fmt.Stringer.
|
||||||
|
value: fmt.Stringer(bytes.NewBuffer(nil)),
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil function",
|
||||||
|
args: args{
|
||||||
|
field: "Callback",
|
||||||
|
value: (func())(nil),
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Callback",
|
||||||
|
Msg: "must not be nil",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-nil function",
|
||||||
|
args: args{
|
||||||
|
field: "Callback",
|
||||||
|
value: func() {},
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-nil struct",
|
||||||
|
args: args{
|
||||||
|
field: "Person",
|
||||||
|
value: struct{ Name string }{Name: "Alice"},
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pointer to nil pointer",
|
||||||
|
args: args{
|
||||||
|
field: "Data",
|
||||||
|
value: pointerToPointer(nil),
|
||||||
|
},
|
||||||
|
want: &Error{
|
||||||
|
Field: "Data",
|
||||||
|
Msg: "must not be nil",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pointer to non-nil pointer",
|
||||||
|
args: args{
|
||||||
|
field: "Data",
|
||||||
|
value: pointerToPointer(new(int)),
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := NotNil(tt.args.field, tt.args.value)
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pointerToPointer(v *int) **int {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user