5901 lines
139 KiB
Go
5901 lines
139 KiB
Go
|
package validator
|
|||
|
|
|||
|
import (
|
|||
|
"database/sql"
|
|||
|
"database/sql/driver"
|
|||
|
"encoding/json"
|
|||
|
"fmt"
|
|||
|
"reflect"
|
|||
|
"testing"
|
|||
|
"time"
|
|||
|
|
|||
|
. "gopkg.in/go-playground/assert.v1"
|
|||
|
)
|
|||
|
|
|||
|
// NOTES:
|
|||
|
// - Run "go test" to run tests
|
|||
|
// - Run "gocov test | gocov report" to report on test converage by file
|
|||
|
// - Run "gocov test | gocov annotate -" to report on all code and functions, those ,marked with "MISS" were never called
|
|||
|
//
|
|||
|
// or
|
|||
|
//
|
|||
|
// -- may be a good idea to change to output path to somewherelike /tmp
|
|||
|
// go test -coverprofile cover.out && go tool cover -html=cover.out -o cover.html
|
|||
|
//
|
|||
|
//
|
|||
|
// go test -cpuprofile cpu.out
|
|||
|
// ./validator.test -test.bench=. -test.cpuprofile=cpu.prof
|
|||
|
// go tool pprof validator.test cpu.prof
|
|||
|
//
|
|||
|
//
|
|||
|
// go test -memprofile mem.out
|
|||
|
|
|||
|
type I interface {
|
|||
|
Foo() string
|
|||
|
}
|
|||
|
|
|||
|
type Impl struct {
|
|||
|
F string `validate:"len=3"`
|
|||
|
}
|
|||
|
|
|||
|
func (i *Impl) Foo() string {
|
|||
|
return i.F
|
|||
|
}
|
|||
|
|
|||
|
type SubTest struct {
|
|||
|
Test string `validate:"required"`
|
|||
|
}
|
|||
|
|
|||
|
type TestInterface struct {
|
|||
|
Iface I
|
|||
|
}
|
|||
|
|
|||
|
type TestString struct {
|
|||
|
BlankTag string `validate:""`
|
|||
|
Required string `validate:"required"`
|
|||
|
Len string `validate:"len=10"`
|
|||
|
Min string `validate:"min=1"`
|
|||
|
Max string `validate:"max=10"`
|
|||
|
MinMax string `validate:"min=1,max=10"`
|
|||
|
Lt string `validate:"lt=10"`
|
|||
|
Lte string `validate:"lte=10"`
|
|||
|
Gt string `validate:"gt=10"`
|
|||
|
Gte string `validate:"gte=10"`
|
|||
|
OmitEmpty string `validate:"omitempty,min=1,max=10"`
|
|||
|
Sub *SubTest
|
|||
|
SubIgnore *SubTest `validate:"-"`
|
|||
|
Anonymous struct {
|
|||
|
A string `validate:"required"`
|
|||
|
}
|
|||
|
Iface I
|
|||
|
}
|
|||
|
|
|||
|
type TestInt32 struct {
|
|||
|
Required int `validate:"required"`
|
|||
|
Len int `validate:"len=10"`
|
|||
|
Min int `validate:"min=1"`
|
|||
|
Max int `validate:"max=10"`
|
|||
|
MinMax int `validate:"min=1,max=10"`
|
|||
|
Lt int `validate:"lt=10"`
|
|||
|
Lte int `validate:"lte=10"`
|
|||
|
Gt int `validate:"gt=10"`
|
|||
|
Gte int `validate:"gte=10"`
|
|||
|
OmitEmpty int `validate:"omitempty,min=1,max=10"`
|
|||
|
}
|
|||
|
|
|||
|
type TestUint64 struct {
|
|||
|
Required uint64 `validate:"required"`
|
|||
|
Len uint64 `validate:"len=10"`
|
|||
|
Min uint64 `validate:"min=1"`
|
|||
|
Max uint64 `validate:"max=10"`
|
|||
|
MinMax uint64 `validate:"min=1,max=10"`
|
|||
|
OmitEmpty uint64 `validate:"omitempty,min=1,max=10"`
|
|||
|
}
|
|||
|
|
|||
|
type TestFloat64 struct {
|
|||
|
Required float64 `validate:"required"`
|
|||
|
Len float64 `validate:"len=10"`
|
|||
|
Min float64 `validate:"min=1"`
|
|||
|
Max float64 `validate:"max=10"`
|
|||
|
MinMax float64 `validate:"min=1,max=10"`
|
|||
|
Lte float64 `validate:"lte=10"`
|
|||
|
OmitEmpty float64 `validate:"omitempty,min=1,max=10"`
|
|||
|
}
|
|||
|
|
|||
|
type TestSlice struct {
|
|||
|
Required []int `validate:"required"`
|
|||
|
Len []int `validate:"len=10"`
|
|||
|
Min []int `validate:"min=1"`
|
|||
|
Max []int `validate:"max=10"`
|
|||
|
MinMax []int `validate:"min=1,max=10"`
|
|||
|
OmitEmpty []int `validate:"omitempty,min=1,max=10"`
|
|||
|
}
|
|||
|
|
|||
|
var validate = New(&Config{TagName: "validate"})
|
|||
|
|
|||
|
func AssertError(t *testing.T, err error, key, field, expectedTag string) {
|
|||
|
|
|||
|
errs := err.(ValidationErrors)
|
|||
|
|
|||
|
val, ok := errs[key]
|
|||
|
EqualSkip(t, 2, ok, true)
|
|||
|
NotEqualSkip(t, 2, val, nil)
|
|||
|
EqualSkip(t, 2, val.Field, field)
|
|||
|
EqualSkip(t, 2, val.Tag, expectedTag)
|
|||
|
}
|
|||
|
|
|||
|
type valuer struct {
|
|||
|
Name string
|
|||
|
}
|
|||
|
|
|||
|
func (v valuer) Value() (driver.Value, error) {
|
|||
|
|
|||
|
if v.Name == "errorme" {
|
|||
|
panic("SQL Driver Valuer error: some kind of error")
|
|||
|
// return nil, errors.New("some kind of error")
|
|||
|
}
|
|||
|
|
|||
|
if len(v.Name) == 0 {
|
|||
|
return nil, nil
|
|||
|
}
|
|||
|
|
|||
|
return v.Name, nil
|
|||
|
}
|
|||
|
|
|||
|
type MadeUpCustomType struct {
|
|||
|
FirstName string
|
|||
|
LastName string
|
|||
|
}
|
|||
|
|
|||
|
func ValidateCustomType(field reflect.Value) interface{} {
|
|||
|
if cust, ok := field.Interface().(MadeUpCustomType); ok {
|
|||
|
|
|||
|
if len(cust.FirstName) == 0 || len(cust.LastName) == 0 {
|
|||
|
return ""
|
|||
|
}
|
|||
|
|
|||
|
return cust.FirstName + " " + cust.LastName
|
|||
|
}
|
|||
|
|
|||
|
return ""
|
|||
|
}
|
|||
|
|
|||
|
func OverrideIntTypeForSomeReason(field reflect.Value) interface{} {
|
|||
|
|
|||
|
if i, ok := field.Interface().(int); ok {
|
|||
|
if i == 1 {
|
|||
|
return "1"
|
|||
|
}
|
|||
|
|
|||
|
if i == 2 {
|
|||
|
return "12"
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ""
|
|||
|
}
|
|||
|
|
|||
|
type CustomMadeUpStruct struct {
|
|||
|
MadeUp MadeUpCustomType `validate:"required"`
|
|||
|
OverriddenInt int `validate:"gt=1"`
|
|||
|
}
|
|||
|
|
|||
|
func ValidateValuerType(field reflect.Value) interface{} {
|
|||
|
|
|||
|
if valuer, ok := field.Interface().(driver.Valuer); ok {
|
|||
|
|
|||
|
val, err := valuer.Value()
|
|||
|
if err != nil {
|
|||
|
// handle the error how you want
|
|||
|
return nil
|
|||
|
}
|
|||
|
|
|||
|
return val
|
|||
|
}
|
|||
|
|
|||
|
return nil
|
|||
|
}
|
|||
|
|
|||
|
type TestPartial struct {
|
|||
|
NoTag string
|
|||
|
BlankTag string `validate:""`
|
|||
|
Required string `validate:"required"`
|
|||
|
SubSlice []*SubTest `validate:"required,dive"`
|
|||
|
Sub *SubTest
|
|||
|
SubIgnore *SubTest `validate:"-"`
|
|||
|
Anonymous struct {
|
|||
|
A string `validate:"required"`
|
|||
|
ASubSlice []*SubTest `validate:"required,dive"`
|
|||
|
|
|||
|
SubAnonStruct []struct {
|
|||
|
Test string `validate:"required"`
|
|||
|
OtherTest string `validate:"required"`
|
|||
|
} `validate:"required,dive"`
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
type TestStruct struct {
|
|||
|
String string `validate:"required" json:"StringVal"`
|
|||
|
}
|
|||
|
|
|||
|
func StructValidationTestStructSuccess(v *Validate, structLevel *StructLevel) {
|
|||
|
|
|||
|
st := structLevel.CurrentStruct.Interface().(TestStruct)
|
|||
|
|
|||
|
if st.String != "good value" {
|
|||
|
structLevel.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "badvalueteststruct")
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func StructValidationTestStruct(v *Validate, structLevel *StructLevel) {
|
|||
|
|
|||
|
st := structLevel.CurrentStruct.Interface().(TestStruct)
|
|||
|
|
|||
|
if st.String != "bad value" {
|
|||
|
structLevel.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "badvalueteststruct")
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func StructValidationBadTestStructFieldName(v *Validate, structLevel *StructLevel) {
|
|||
|
|
|||
|
st := structLevel.CurrentStruct.Interface().(TestStruct)
|
|||
|
|
|||
|
if st.String != "bad value" {
|
|||
|
structLevel.ReportError(reflect.ValueOf(st.String), "", "StringVal", "badvalueteststruct")
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func StructValidationBadTestStructTag(v *Validate, structLevel *StructLevel) {
|
|||
|
|
|||
|
st := structLevel.CurrentStruct.Interface().(TestStruct)
|
|||
|
|
|||
|
if st.String != "bad value" {
|
|||
|
structLevel.ReportError(reflect.ValueOf(st.String), "String", "StringVal", "")
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func StructValidationNoTestStructCustomName(v *Validate, structLevel *StructLevel) {
|
|||
|
|
|||
|
st := structLevel.CurrentStruct.Interface().(TestStruct)
|
|||
|
|
|||
|
if st.String != "bad value" {
|
|||
|
structLevel.ReportError(reflect.ValueOf(st.String), "String", "", "badvalueteststruct")
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func StructValidationTestStructInvalid(v *Validate, structLevel *StructLevel) {
|
|||
|
|
|||
|
st := structLevel.CurrentStruct.Interface().(TestStruct)
|
|||
|
|
|||
|
if st.String != "bad value" {
|
|||
|
structLevel.ReportError(reflect.ValueOf(nil), "String", "StringVal", "badvalueteststruct")
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func StructValidationTestStructReturnValidationErrors(v *Validate, structLevel *StructLevel) {
|
|||
|
|
|||
|
s := structLevel.CurrentStruct.Interface().(TestStructReturnValidationErrors)
|
|||
|
|
|||
|
errs := v.Struct(s.Inner1.Inner2)
|
|||
|
if errs == nil {
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
structLevel.ReportValidationErrors("Inner1.", errs.(ValidationErrors))
|
|||
|
}
|
|||
|
|
|||
|
func StructValidationTestStructReturnValidationErrors2(v *Validate, structLevel *StructLevel) {
|
|||
|
|
|||
|
s := structLevel.CurrentStruct.Interface().(TestStructReturnValidationErrors)
|
|||
|
|
|||
|
errs := v.Struct(s.Inner1.Inner2)
|
|||
|
if errs == nil {
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
structLevel.ReportValidationErrors("Inner1.|Inner1JSON.", errs.(ValidationErrors))
|
|||
|
}
|
|||
|
|
|||
|
type TestStructReturnValidationErrorsInner2 struct {
|
|||
|
String string `validate:"required" json:"JSONString"`
|
|||
|
}
|
|||
|
|
|||
|
type TestStructReturnValidationErrorsInner1 struct {
|
|||
|
Inner2 *TestStructReturnValidationErrorsInner2
|
|||
|
}
|
|||
|
|
|||
|
type TestStructReturnValidationErrors struct {
|
|||
|
Inner1 *TestStructReturnValidationErrorsInner1 `json:"Inner1JSON"`
|
|||
|
}
|
|||
|
|
|||
|
type Inner2Namespace struct {
|
|||
|
String []string `validate:"dive,required" json:"JSONString"`
|
|||
|
}
|
|||
|
|
|||
|
type Inner1Namespace struct {
|
|||
|
Inner2 *Inner2Namespace `json:"Inner2JSON"`
|
|||
|
}
|
|||
|
|
|||
|
type Namespace struct {
|
|||
|
Inner1 *Inner1Namespace `json:"Inner1JSON"`
|
|||
|
}
|
|||
|
|
|||
|
func TestNameNamespace(t *testing.T) {
|
|||
|
|
|||
|
config := &Config{
|
|||
|
TagName: "validate",
|
|||
|
FieldNameTag: "json",
|
|||
|
}
|
|||
|
|
|||
|
v1 := New(config)
|
|||
|
i2 := &Inner2Namespace{String: []string{"ok", "ok", "ok"}}
|
|||
|
i1 := &Inner1Namespace{Inner2: i2}
|
|||
|
ns := &Namespace{Inner1: i1}
|
|||
|
|
|||
|
errs := v1.Struct(ns)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
i2.String[1] = ""
|
|||
|
|
|||
|
errs = v1.Struct(ns)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
|
|||
|
ve := errs.(ValidationErrors)
|
|||
|
Equal(t, len(ve), 1)
|
|||
|
AssertError(t, errs, "Namespace.Inner1.Inner2.String[1]", "String[1]", "required")
|
|||
|
|
|||
|
fe, ok := ve["Namespace.Inner1.Inner2.String[1]"]
|
|||
|
Equal(t, ok, true)
|
|||
|
|
|||
|
Equal(t, fe.Field, "String[1]")
|
|||
|
Equal(t, fe.FieldNamespace, "Namespace.Inner1.Inner2.String[1]")
|
|||
|
Equal(t, fe.Name, "JSONString[1]")
|
|||
|
Equal(t, fe.NameNamespace, "Namespace.Inner1JSON.Inner2JSON.JSONString[1]")
|
|||
|
}
|
|||
|
|
|||
|
func TestAnonymous(t *testing.T) {
|
|||
|
|
|||
|
v2 := New(&Config{TagName: "validate", FieldNameTag: "json"})
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Anonymous struct {
|
|||
|
A string `validate:"required" json:"EH"`
|
|||
|
}
|
|||
|
AnonymousB struct {
|
|||
|
B string `validate:"required" json:"BEE"`
|
|||
|
}
|
|||
|
anonymousC struct {
|
|||
|
c string `validate:"required"`
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
tst := &Test{
|
|||
|
Anonymous: struct {
|
|||
|
A string `validate:"required" json:"EH"`
|
|||
|
}{
|
|||
|
A: "1",
|
|||
|
},
|
|||
|
AnonymousB: struct {
|
|||
|
B string `validate:"required" json:"BEE"`
|
|||
|
}{
|
|||
|
B: "",
|
|||
|
},
|
|||
|
anonymousC: struct {
|
|||
|
c string `validate:"required"`
|
|||
|
}{
|
|||
|
c: "",
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
err := v2.Struct(tst)
|
|||
|
NotEqual(t, err, nil)
|
|||
|
|
|||
|
errs := err.(ValidationErrors)
|
|||
|
|
|||
|
Equal(t, len(errs), 1)
|
|||
|
AssertError(t, errs, "Test.AnonymousB.B", "B", "required")
|
|||
|
Equal(t, errs["Test.AnonymousB.B"].Field, "B")
|
|||
|
Equal(t, errs["Test.AnonymousB.B"].Name, "BEE")
|
|||
|
|
|||
|
s := struct {
|
|||
|
c string `validate:"required"`
|
|||
|
}{
|
|||
|
c: "",
|
|||
|
}
|
|||
|
|
|||
|
err = v2.Struct(s)
|
|||
|
Equal(t, err, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestAnonymousSameStructDifferentTags(t *testing.T) {
|
|||
|
|
|||
|
v2 := New(&Config{TagName: "validate", FieldNameTag: "json"})
|
|||
|
|
|||
|
type Test struct {
|
|||
|
A interface{}
|
|||
|
}
|
|||
|
|
|||
|
tst := &Test{
|
|||
|
A: struct {
|
|||
|
A string `validate:"required"`
|
|||
|
}{
|
|||
|
A: "",
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
err := v2.Struct(tst)
|
|||
|
NotEqual(t, err, nil)
|
|||
|
|
|||
|
errs := err.(ValidationErrors)
|
|||
|
|
|||
|
Equal(t, len(errs), 1)
|
|||
|
AssertError(t, errs, "Test.A.A", "A", "required")
|
|||
|
|
|||
|
tst = &Test{
|
|||
|
A: struct {
|
|||
|
A string `validate:"omitempty,required"`
|
|||
|
}{
|
|||
|
A: "",
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
err = v2.Struct(tst)
|
|||
|
Equal(t, err, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestStructLevelReturnValidationErrors(t *testing.T) {
|
|||
|
config := &Config{
|
|||
|
TagName: "validate",
|
|||
|
}
|
|||
|
|
|||
|
v1 := New(config)
|
|||
|
v1.RegisterStructValidation(StructValidationTestStructReturnValidationErrors, TestStructReturnValidationErrors{})
|
|||
|
|
|||
|
inner2 := &TestStructReturnValidationErrorsInner2{
|
|||
|
String: "I'm HERE",
|
|||
|
}
|
|||
|
|
|||
|
inner1 := &TestStructReturnValidationErrorsInner1{
|
|||
|
Inner2: inner2,
|
|||
|
}
|
|||
|
|
|||
|
val := &TestStructReturnValidationErrors{
|
|||
|
Inner1: inner1,
|
|||
|
}
|
|||
|
|
|||
|
errs := v1.Struct(val)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
inner2.String = ""
|
|||
|
|
|||
|
errs = v1.Struct(val)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 2)
|
|||
|
AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.Inner2.String", "String", "required")
|
|||
|
// this is an extra error reported from struct validation
|
|||
|
AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.String", "String", "required")
|
|||
|
}
|
|||
|
|
|||
|
func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) {
|
|||
|
config := &Config{
|
|||
|
TagName: "validate",
|
|||
|
FieldNameTag: "json",
|
|||
|
}
|
|||
|
|
|||
|
v1 := New(config)
|
|||
|
v1.RegisterStructValidation(StructValidationTestStructReturnValidationErrors2, TestStructReturnValidationErrors{})
|
|||
|
|
|||
|
inner2 := &TestStructReturnValidationErrorsInner2{
|
|||
|
String: "I'm HERE",
|
|||
|
}
|
|||
|
|
|||
|
inner1 := &TestStructReturnValidationErrorsInner1{
|
|||
|
Inner2: inner2,
|
|||
|
}
|
|||
|
|
|||
|
val := &TestStructReturnValidationErrors{
|
|||
|
Inner1: inner1,
|
|||
|
}
|
|||
|
|
|||
|
errs := v1.Struct(val)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
inner2.String = ""
|
|||
|
|
|||
|
errs = v1.Struct(val)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 2)
|
|||
|
AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.Inner2.String", "String", "required")
|
|||
|
// this is an extra error reported from struct validation, it's a badly formatted one, but on purpose
|
|||
|
AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.String", "String", "required")
|
|||
|
|
|||
|
fe, ok := errs.(ValidationErrors)["TestStructReturnValidationErrors.Inner1.Inner2.String"]
|
|||
|
Equal(t, ok, true)
|
|||
|
|
|||
|
// check for proper JSON namespace
|
|||
|
Equal(t, fe.Field, "String")
|
|||
|
Equal(t, fe.Name, "JSONString")
|
|||
|
Equal(t, fe.FieldNamespace, "TestStructReturnValidationErrors.Inner1.Inner2.String")
|
|||
|
Equal(t, fe.NameNamespace, "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString")
|
|||
|
|
|||
|
fe, ok = errs.(ValidationErrors)["TestStructReturnValidationErrors.Inner1.String"]
|
|||
|
Equal(t, ok, true)
|
|||
|
|
|||
|
// check for proper JSON namespace
|
|||
|
Equal(t, fe.Field, "String")
|
|||
|
Equal(t, fe.Name, "JSONString")
|
|||
|
Equal(t, fe.FieldNamespace, "TestStructReturnValidationErrors.Inner1.String")
|
|||
|
Equal(t, fe.NameNamespace, "TestStructReturnValidationErrors.Inner1JSON.JSONString")
|
|||
|
}
|
|||
|
|
|||
|
func TestStructLevelValidations(t *testing.T) {
|
|||
|
|
|||
|
config := &Config{
|
|||
|
TagName: "validate",
|
|||
|
}
|
|||
|
|
|||
|
v1 := New(config)
|
|||
|
v1.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
|
|||
|
|
|||
|
tst := &TestStruct{
|
|||
|
String: "good value",
|
|||
|
}
|
|||
|
|
|||
|
errs := v1.Struct(tst)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
|
|||
|
|
|||
|
v2 := New(config)
|
|||
|
v2.RegisterStructValidation(StructValidationBadTestStructFieldName, TestStruct{})
|
|||
|
|
|||
|
PanicMatches(t, func() { v2.Struct(tst) }, fieldNameRequired)
|
|||
|
|
|||
|
v3 := New(config)
|
|||
|
v3.RegisterStructValidation(StructValidationBadTestStructTag, TestStruct{})
|
|||
|
|
|||
|
PanicMatches(t, func() { v3.Struct(tst) }, tagRequired)
|
|||
|
|
|||
|
v4 := New(config)
|
|||
|
v4.RegisterStructValidation(StructValidationNoTestStructCustomName, TestStruct{})
|
|||
|
|
|||
|
errs = v4.Struct(tst)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
|
|||
|
|
|||
|
v5 := New(config)
|
|||
|
v5.RegisterStructValidation(StructValidationTestStructInvalid, TestStruct{})
|
|||
|
|
|||
|
errs = v5.Struct(tst)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestStruct.String", "String", "badvalueteststruct")
|
|||
|
|
|||
|
v6 := New(config)
|
|||
|
v6.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{})
|
|||
|
|
|||
|
errs = v6.Struct(tst)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestAliasTags(t *testing.T) {
|
|||
|
|
|||
|
validate.RegisterAliasValidation("iscolor", "hexcolor|rgb|rgba|hsl|hsla")
|
|||
|
|
|||
|
s := "rgb(255,255,255)"
|
|||
|
errs := validate.Field(s, "iscolor")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = ""
|
|||
|
errs = validate.Field(s, "omitempty,iscolor")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "rgb(255,255,0)"
|
|||
|
errs = validate.Field(s, "iscolor,len=5")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "len")
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Color string `validate:"iscolor"`
|
|||
|
}
|
|||
|
|
|||
|
tst := &Test{
|
|||
|
Color: "#000",
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tst)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
tst.Color = "cfvre"
|
|||
|
errs = validate.Struct(tst)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.Color", "Color", "iscolor")
|
|||
|
Equal(t, errs.(ValidationErrors)["Test.Color"].ActualTag, "hexcolor|rgb|rgba|hsl|hsla")
|
|||
|
|
|||
|
validate.RegisterAliasValidation("req", "required,dive,iscolor")
|
|||
|
arr := []string{"val1", "#fff", "#000"}
|
|||
|
|
|||
|
errs = validate.Field(arr, "req")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "[0]", "[0]", "iscolor")
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.RegisterAliasValidation("exists", "gt=5,lt=10") }, "Alias 'exists' either contains restricted characters or is the same as a restricted tag needed for normal operation")
|
|||
|
}
|
|||
|
|
|||
|
func TestNilValidator(t *testing.T) {
|
|||
|
|
|||
|
type TestStruct struct {
|
|||
|
Test string `validate:"required"`
|
|||
|
}
|
|||
|
|
|||
|
ts := TestStruct{}
|
|||
|
|
|||
|
var val *Validate
|
|||
|
|
|||
|
fn := func(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
|||
|
|
|||
|
return current.String() == field.String()
|
|||
|
}
|
|||
|
|
|||
|
PanicMatches(t, func() { val.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) }, validatorNotInitialized)
|
|||
|
PanicMatches(t, func() { val.RegisterValidation("something", fn) }, validatorNotInitialized)
|
|||
|
PanicMatches(t, func() { val.Field(ts.Test, "required") }, validatorNotInitialized)
|
|||
|
PanicMatches(t, func() { val.FieldWithValue("test", ts.Test, "required") }, validatorNotInitialized)
|
|||
|
PanicMatches(t, func() { val.Struct(ts) }, validatorNotInitialized)
|
|||
|
PanicMatches(t, func() { val.StructExcept(ts, "Test") }, validatorNotInitialized)
|
|||
|
PanicMatches(t, func() { val.StructPartial(ts, "Test") }, validatorNotInitialized)
|
|||
|
}
|
|||
|
|
|||
|
func TestStructPartial(t *testing.T) {
|
|||
|
|
|||
|
p1 := []string{
|
|||
|
"NoTag",
|
|||
|
"Required",
|
|||
|
}
|
|||
|
|
|||
|
p2 := []string{
|
|||
|
"SubSlice[0].Test",
|
|||
|
"Sub",
|
|||
|
"SubIgnore",
|
|||
|
"Anonymous.A",
|
|||
|
}
|
|||
|
|
|||
|
p3 := []string{
|
|||
|
"SubTest.Test",
|
|||
|
}
|
|||
|
|
|||
|
p4 := []string{
|
|||
|
"A",
|
|||
|
}
|
|||
|
|
|||
|
tPartial := &TestPartial{
|
|||
|
NoTag: "NoTag",
|
|||
|
Required: "Required",
|
|||
|
|
|||
|
SubSlice: []*SubTest{
|
|||
|
{
|
|||
|
|
|||
|
Test: "Required",
|
|||
|
},
|
|||
|
{
|
|||
|
|
|||
|
Test: "Required",
|
|||
|
},
|
|||
|
},
|
|||
|
|
|||
|
Sub: &SubTest{
|
|||
|
Test: "1",
|
|||
|
},
|
|||
|
SubIgnore: &SubTest{
|
|||
|
Test: "",
|
|||
|
},
|
|||
|
Anonymous: struct {
|
|||
|
A string `validate:"required"`
|
|||
|
ASubSlice []*SubTest `validate:"required,dive"`
|
|||
|
SubAnonStruct []struct {
|
|||
|
Test string `validate:"required"`
|
|||
|
OtherTest string `validate:"required"`
|
|||
|
} `validate:"required,dive"`
|
|||
|
}{
|
|||
|
A: "1",
|
|||
|
ASubSlice: []*SubTest{
|
|||
|
{
|
|||
|
Test: "Required",
|
|||
|
},
|
|||
|
{
|
|||
|
Test: "Required",
|
|||
|
},
|
|||
|
},
|
|||
|
|
|||
|
SubAnonStruct: []struct {
|
|||
|
Test string `validate:"required"`
|
|||
|
OtherTest string `validate:"required"`
|
|||
|
}{
|
|||
|
{"Required", "RequiredOther"},
|
|||
|
{"Required", "RequiredOther"},
|
|||
|
},
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
// the following should all return no errors as everything is valid in
|
|||
|
// the default state
|
|||
|
errs := validate.StructPartial(tPartial, p1...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.StructPartial(tPartial, p2...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
// this isn't really a robust test, but is ment to illustrate the ANON CASE below
|
|||
|
errs = validate.StructPartial(tPartial.SubSlice[0], p3...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.StructExcept(tPartial, p1...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.StructExcept(tPartial, p2...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
// mod tParial for required feild and re-test making sure invalid fields are NOT required:
|
|||
|
tPartial.Required = ""
|
|||
|
|
|||
|
errs = validate.StructExcept(tPartial, p1...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.StructPartial(tPartial, p2...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
// inversion and retesting Partial to generate failures:
|
|||
|
errs = validate.StructPartial(tPartial, p1...)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestPartial.Required", "Required", "required")
|
|||
|
|
|||
|
errs = validate.StructExcept(tPartial, p2...)
|
|||
|
AssertError(t, errs, "TestPartial.Required", "Required", "required")
|
|||
|
|
|||
|
// reset Required field, and set nested struct
|
|||
|
tPartial.Required = "Required"
|
|||
|
tPartial.Anonymous.A = ""
|
|||
|
|
|||
|
// will pass as unset feilds is not going to be tested
|
|||
|
errs = validate.StructPartial(tPartial, p1...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.StructExcept(tPartial, p2...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
// ANON CASE the response here is strange, it clearly does what it is being told to
|
|||
|
errs = validate.StructExcept(tPartial.Anonymous, p4...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
// will fail as unset feild is tested
|
|||
|
errs = validate.StructPartial(tPartial, p2...)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestPartial.Anonymous.A", "A", "required")
|
|||
|
|
|||
|
errs = validate.StructExcept(tPartial, p1...)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestPartial.Anonymous.A", "A", "required")
|
|||
|
|
|||
|
// reset nested struct and unset struct in slice
|
|||
|
tPartial.Anonymous.A = "Required"
|
|||
|
tPartial.SubSlice[0].Test = ""
|
|||
|
|
|||
|
// these will pass as unset item is NOT tested
|
|||
|
errs = validate.StructPartial(tPartial, p1...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.StructExcept(tPartial, p2...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
// these will fail as unset item IS tested
|
|||
|
errs = validate.StructExcept(tPartial, p1...)
|
|||
|
AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
|
|||
|
errs = validate.StructPartial(tPartial, p2...)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
|
|||
|
// Unset second slice member concurrently to test dive behavior:
|
|||
|
tPartial.SubSlice[1].Test = ""
|
|||
|
|
|||
|
errs = validate.StructPartial(tPartial, p1...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
// NOTE: When specifying nested items, it is still the users responsibility
|
|||
|
// to specify the dive tag, the library does not override this.
|
|||
|
errs = validate.StructExcept(tPartial, p2...)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
|
|||
|
|
|||
|
errs = validate.StructExcept(tPartial, p1...)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 2)
|
|||
|
AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
|
|||
|
AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
|
|||
|
|
|||
|
errs = validate.StructPartial(tPartial, p2...)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "TestPartial.SubSlice[0].Test", "Test", "required")
|
|||
|
|
|||
|
// reset struct in slice, and unset struct in slice in unset posistion
|
|||
|
tPartial.SubSlice[0].Test = "Required"
|
|||
|
|
|||
|
// these will pass as the unset item is NOT tested
|
|||
|
errs = validate.StructPartial(tPartial, p1...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.StructPartial(tPartial, p2...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
// testing for missing item by exception, yes it dives and fails
|
|||
|
errs = validate.StructExcept(tPartial, p1...)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
|
|||
|
|
|||
|
errs = validate.StructExcept(tPartial, p2...)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestPartial.SubSlice[1].Test", "Test", "required")
|
|||
|
|
|||
|
tPartial.SubSlice[1].Test = "Required"
|
|||
|
|
|||
|
tPartial.Anonymous.SubAnonStruct[0].Test = ""
|
|||
|
// these will pass as the unset item is NOT tested
|
|||
|
errs = validate.StructPartial(tPartial, p1...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.StructPartial(tPartial, p2...)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.StructExcept(tPartial, p1...)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "required")
|
|||
|
|
|||
|
errs = validate.StructExcept(tPartial, p2...)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "required")
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
func TestCrossStructLteFieldValidation(t *testing.T) {
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
CreatedAt *time.Time
|
|||
|
String string
|
|||
|
Int int
|
|||
|
Uint uint
|
|||
|
Float float64
|
|||
|
Array []string
|
|||
|
}
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Inner *Inner
|
|||
|
CreatedAt *time.Time `validate:"ltecsfield=Inner.CreatedAt"`
|
|||
|
String string `validate:"ltecsfield=Inner.String"`
|
|||
|
Int int `validate:"ltecsfield=Inner.Int"`
|
|||
|
Uint uint `validate:"ltecsfield=Inner.Uint"`
|
|||
|
Float float64 `validate:"ltecsfield=Inner.Float"`
|
|||
|
Array []string `validate:"ltecsfield=Inner.Array"`
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now().UTC()
|
|||
|
then := now.Add(time.Hour * 5)
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
CreatedAt: &then,
|
|||
|
String: "abcd",
|
|||
|
Int: 13,
|
|||
|
Uint: 13,
|
|||
|
Float: 1.13,
|
|||
|
Array: []string{"val1", "val2"},
|
|||
|
}
|
|||
|
|
|||
|
test := &Test{
|
|||
|
Inner: inner,
|
|||
|
CreatedAt: &now,
|
|||
|
String: "abc",
|
|||
|
Int: 12,
|
|||
|
Uint: 12,
|
|||
|
Float: 1.12,
|
|||
|
Array: []string{"val1"},
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(test)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
test.CreatedAt = &then
|
|||
|
test.String = "abcd"
|
|||
|
test.Int = 13
|
|||
|
test.Uint = 13
|
|||
|
test.Float = 1.13
|
|||
|
test.Array = []string{"val1", "val2"}
|
|||
|
|
|||
|
errs = validate.Struct(test)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
after := now.Add(time.Hour * 10)
|
|||
|
|
|||
|
test.CreatedAt = &after
|
|||
|
test.String = "abce"
|
|||
|
test.Int = 14
|
|||
|
test.Uint = 14
|
|||
|
test.Float = 1.14
|
|||
|
test.Array = []string{"val1", "val2", "val3"}
|
|||
|
|
|||
|
errs = validate.Struct(test)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "ltecsfield")
|
|||
|
AssertError(t, errs, "Test.String", "String", "ltecsfield")
|
|||
|
AssertError(t, errs, "Test.Int", "Int", "ltecsfield")
|
|||
|
AssertError(t, errs, "Test.Uint", "Uint", "ltecsfield")
|
|||
|
AssertError(t, errs, "Test.Float", "Float", "ltecsfield")
|
|||
|
AssertError(t, errs, "Test.Array", "Array", "ltecsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(1, "", "ltecsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltecsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(test, now, "ltecsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltecsfield")
|
|||
|
}
|
|||
|
|
|||
|
func TestCrossStructLtFieldValidation(t *testing.T) {
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
CreatedAt *time.Time
|
|||
|
String string
|
|||
|
Int int
|
|||
|
Uint uint
|
|||
|
Float float64
|
|||
|
Array []string
|
|||
|
}
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Inner *Inner
|
|||
|
CreatedAt *time.Time `validate:"ltcsfield=Inner.CreatedAt"`
|
|||
|
String string `validate:"ltcsfield=Inner.String"`
|
|||
|
Int int `validate:"ltcsfield=Inner.Int"`
|
|||
|
Uint uint `validate:"ltcsfield=Inner.Uint"`
|
|||
|
Float float64 `validate:"ltcsfield=Inner.Float"`
|
|||
|
Array []string `validate:"ltcsfield=Inner.Array"`
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now().UTC()
|
|||
|
then := now.Add(time.Hour * 5)
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
CreatedAt: &then,
|
|||
|
String: "abcd",
|
|||
|
Int: 13,
|
|||
|
Uint: 13,
|
|||
|
Float: 1.13,
|
|||
|
Array: []string{"val1", "val2"},
|
|||
|
}
|
|||
|
|
|||
|
test := &Test{
|
|||
|
Inner: inner,
|
|||
|
CreatedAt: &now,
|
|||
|
String: "abc",
|
|||
|
Int: 12,
|
|||
|
Uint: 12,
|
|||
|
Float: 1.12,
|
|||
|
Array: []string{"val1"},
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(test)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
test.CreatedAt = &then
|
|||
|
test.String = "abcd"
|
|||
|
test.Int = 13
|
|||
|
test.Uint = 13
|
|||
|
test.Float = 1.13
|
|||
|
test.Array = []string{"val1", "val2"}
|
|||
|
|
|||
|
errs = validate.Struct(test)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "ltcsfield")
|
|||
|
AssertError(t, errs, "Test.String", "String", "ltcsfield")
|
|||
|
AssertError(t, errs, "Test.Int", "Int", "ltcsfield")
|
|||
|
AssertError(t, errs, "Test.Uint", "Uint", "ltcsfield")
|
|||
|
AssertError(t, errs, "Test.Float", "Float", "ltcsfield")
|
|||
|
AssertError(t, errs, "Test.Array", "Array", "ltcsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(1, "", "ltcsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltcsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(test, now, "ltcsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltcsfield")
|
|||
|
}
|
|||
|
|
|||
|
func TestCrossStructGteFieldValidation(t *testing.T) {
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
CreatedAt *time.Time
|
|||
|
String string
|
|||
|
Int int
|
|||
|
Uint uint
|
|||
|
Float float64
|
|||
|
Array []string
|
|||
|
}
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Inner *Inner
|
|||
|
CreatedAt *time.Time `validate:"gtecsfield=Inner.CreatedAt"`
|
|||
|
String string `validate:"gtecsfield=Inner.String"`
|
|||
|
Int int `validate:"gtecsfield=Inner.Int"`
|
|||
|
Uint uint `validate:"gtecsfield=Inner.Uint"`
|
|||
|
Float float64 `validate:"gtecsfield=Inner.Float"`
|
|||
|
Array []string `validate:"gtecsfield=Inner.Array"`
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now().UTC()
|
|||
|
then := now.Add(time.Hour * -5)
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
CreatedAt: &then,
|
|||
|
String: "abcd",
|
|||
|
Int: 13,
|
|||
|
Uint: 13,
|
|||
|
Float: 1.13,
|
|||
|
Array: []string{"val1", "val2"},
|
|||
|
}
|
|||
|
|
|||
|
test := &Test{
|
|||
|
Inner: inner,
|
|||
|
CreatedAt: &now,
|
|||
|
String: "abcde",
|
|||
|
Int: 14,
|
|||
|
Uint: 14,
|
|||
|
Float: 1.14,
|
|||
|
Array: []string{"val1", "val2", "val3"},
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(test)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
test.CreatedAt = &then
|
|||
|
test.String = "abcd"
|
|||
|
test.Int = 13
|
|||
|
test.Uint = 13
|
|||
|
test.Float = 1.13
|
|||
|
test.Array = []string{"val1", "val2"}
|
|||
|
|
|||
|
errs = validate.Struct(test)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
before := now.Add(time.Hour * -10)
|
|||
|
|
|||
|
test.CreatedAt = &before
|
|||
|
test.String = "abc"
|
|||
|
test.Int = 12
|
|||
|
test.Uint = 12
|
|||
|
test.Float = 1.12
|
|||
|
test.Array = []string{"val1"}
|
|||
|
|
|||
|
errs = validate.Struct(test)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "gtecsfield")
|
|||
|
AssertError(t, errs, "Test.String", "String", "gtecsfield")
|
|||
|
AssertError(t, errs, "Test.Int", "Int", "gtecsfield")
|
|||
|
AssertError(t, errs, "Test.Uint", "Uint", "gtecsfield")
|
|||
|
AssertError(t, errs, "Test.Float", "Float", "gtecsfield")
|
|||
|
AssertError(t, errs, "Test.Array", "Array", "gtecsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(1, "", "gtecsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtecsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(test, now, "gtecsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtecsfield")
|
|||
|
}
|
|||
|
|
|||
|
func TestCrossStructGtFieldValidation(t *testing.T) {
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
CreatedAt *time.Time
|
|||
|
String string
|
|||
|
Int int
|
|||
|
Uint uint
|
|||
|
Float float64
|
|||
|
Array []string
|
|||
|
}
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Inner *Inner
|
|||
|
CreatedAt *time.Time `validate:"gtcsfield=Inner.CreatedAt"`
|
|||
|
String string `validate:"gtcsfield=Inner.String"`
|
|||
|
Int int `validate:"gtcsfield=Inner.Int"`
|
|||
|
Uint uint `validate:"gtcsfield=Inner.Uint"`
|
|||
|
Float float64 `validate:"gtcsfield=Inner.Float"`
|
|||
|
Array []string `validate:"gtcsfield=Inner.Array"`
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now().UTC()
|
|||
|
then := now.Add(time.Hour * -5)
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
CreatedAt: &then,
|
|||
|
String: "abcd",
|
|||
|
Int: 13,
|
|||
|
Uint: 13,
|
|||
|
Float: 1.13,
|
|||
|
Array: []string{"val1", "val2"},
|
|||
|
}
|
|||
|
|
|||
|
test := &Test{
|
|||
|
Inner: inner,
|
|||
|
CreatedAt: &now,
|
|||
|
String: "abcde",
|
|||
|
Int: 14,
|
|||
|
Uint: 14,
|
|||
|
Float: 1.14,
|
|||
|
Array: []string{"val1", "val2", "val3"},
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(test)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
test.CreatedAt = &then
|
|||
|
test.String = "abcd"
|
|||
|
test.Int = 13
|
|||
|
test.Uint = 13
|
|||
|
test.Float = 1.13
|
|||
|
test.Array = []string{"val1", "val2"}
|
|||
|
|
|||
|
errs = validate.Struct(test)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "gtcsfield")
|
|||
|
AssertError(t, errs, "Test.String", "String", "gtcsfield")
|
|||
|
AssertError(t, errs, "Test.Int", "Int", "gtcsfield")
|
|||
|
AssertError(t, errs, "Test.Uint", "Uint", "gtcsfield")
|
|||
|
AssertError(t, errs, "Test.Float", "Float", "gtcsfield")
|
|||
|
AssertError(t, errs, "Test.Array", "Array", "gtcsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(1, "", "gtcsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtcsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(test, now, "gtcsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtcsfield")
|
|||
|
}
|
|||
|
|
|||
|
func TestCrossStructNeFieldValidation(t *testing.T) {
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
CreatedAt *time.Time
|
|||
|
}
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Inner *Inner
|
|||
|
CreatedAt *time.Time `validate:"necsfield=Inner.CreatedAt"`
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now().UTC()
|
|||
|
then := now.Add(time.Hour * 5)
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
CreatedAt: &then,
|
|||
|
}
|
|||
|
|
|||
|
test := &Test{
|
|||
|
Inner: inner,
|
|||
|
CreatedAt: &now,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(test)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
test.CreatedAt = &then
|
|||
|
|
|||
|
errs = validate.Struct(test)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "necsfield")
|
|||
|
|
|||
|
var j uint64
|
|||
|
var k float64
|
|||
|
var j2 uint64
|
|||
|
var k2 float64
|
|||
|
s := "abcd"
|
|||
|
i := 1
|
|||
|
j = 1
|
|||
|
k = 1.543
|
|||
|
arr := []string{"test"}
|
|||
|
|
|||
|
s2 := "abcd"
|
|||
|
i2 := 1
|
|||
|
j2 = 1
|
|||
|
k2 = 1.543
|
|||
|
arr2 := []string{"test"}
|
|||
|
arr3 := []string{"test", "test2"}
|
|||
|
now2 := now
|
|||
|
|
|||
|
errs = validate.FieldWithValue(s, s2, "necsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "necsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(i2, i, "necsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "necsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(j2, j, "necsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "necsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(k2, k, "necsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "necsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(arr2, arr, "necsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "necsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(now2, now, "necsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "necsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(arr3, arr, "necsfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
type SInner struct {
|
|||
|
Name string
|
|||
|
}
|
|||
|
|
|||
|
type TStruct struct {
|
|||
|
Inner *SInner
|
|||
|
CreatedAt *time.Time `validate:"necsfield=Inner"`
|
|||
|
}
|
|||
|
|
|||
|
sinner := &SInner{
|
|||
|
Name: "NAME",
|
|||
|
}
|
|||
|
|
|||
|
test2 := &TStruct{
|
|||
|
Inner: sinner,
|
|||
|
CreatedAt: &now,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(test2)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
test2.Inner = nil
|
|||
|
errs = validate.Struct(test2)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(nil, 1, "necsfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestCrossStructEqFieldValidation(t *testing.T) {
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
CreatedAt *time.Time
|
|||
|
}
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Inner *Inner
|
|||
|
CreatedAt *time.Time `validate:"eqcsfield=Inner.CreatedAt"`
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now().UTC()
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
CreatedAt: &now,
|
|||
|
}
|
|||
|
|
|||
|
test := &Test{
|
|||
|
Inner: inner,
|
|||
|
CreatedAt: &now,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(test)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
newTime := time.Now().UTC()
|
|||
|
test.CreatedAt = &newTime
|
|||
|
|
|||
|
errs = validate.Struct(test)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.CreatedAt", "CreatedAt", "eqcsfield")
|
|||
|
|
|||
|
var j uint64
|
|||
|
var k float64
|
|||
|
s := "abcd"
|
|||
|
i := 1
|
|||
|
j = 1
|
|||
|
k = 1.543
|
|||
|
arr := []string{"test"}
|
|||
|
|
|||
|
var j2 uint64
|
|||
|
var k2 float64
|
|||
|
s2 := "abcd"
|
|||
|
i2 := 1
|
|||
|
j2 = 1
|
|||
|
k2 = 1.543
|
|||
|
arr2 := []string{"test"}
|
|||
|
arr3 := []string{"test", "test2"}
|
|||
|
now2 := now
|
|||
|
|
|||
|
errs = validate.FieldWithValue(s, s2, "eqcsfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(i2, i, "eqcsfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(j2, j, "eqcsfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(k2, k, "eqcsfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(arr2, arr, "eqcsfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(now2, now, "eqcsfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(arr3, arr, "eqcsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "eqcsfield")
|
|||
|
|
|||
|
type SInner struct {
|
|||
|
Name string
|
|||
|
}
|
|||
|
|
|||
|
type TStruct struct {
|
|||
|
Inner *SInner
|
|||
|
CreatedAt *time.Time `validate:"eqcsfield=Inner"`
|
|||
|
}
|
|||
|
|
|||
|
sinner := &SInner{
|
|||
|
Name: "NAME",
|
|||
|
}
|
|||
|
|
|||
|
test2 := &TStruct{
|
|||
|
Inner: sinner,
|
|||
|
CreatedAt: &now,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(test2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqcsfield")
|
|||
|
|
|||
|
test2.Inner = nil
|
|||
|
errs = validate.Struct(test2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqcsfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(nil, 1, "eqcsfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "eqcsfield")
|
|||
|
}
|
|||
|
|
|||
|
func TestCrossNamespaceFieldValidation(t *testing.T) {
|
|||
|
|
|||
|
type SliceStruct struct {
|
|||
|
Name string
|
|||
|
}
|
|||
|
|
|||
|
type MapStruct struct {
|
|||
|
Name string
|
|||
|
}
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
CreatedAt *time.Time
|
|||
|
Slice []string
|
|||
|
SliceStructs []*SliceStruct
|
|||
|
SliceSlice [][]string
|
|||
|
SliceSliceStruct [][]*SliceStruct
|
|||
|
SliceMap []map[string]string
|
|||
|
Map map[string]string
|
|||
|
MapMap map[string]map[string]string
|
|||
|
MapStructs map[string]*SliceStruct
|
|||
|
MapMapStruct map[string]map[string]*SliceStruct
|
|||
|
MapSlice map[string][]string
|
|||
|
MapInt map[int]string
|
|||
|
MapInt8 map[int8]string
|
|||
|
MapInt16 map[int16]string
|
|||
|
MapInt32 map[int32]string
|
|||
|
MapInt64 map[int64]string
|
|||
|
MapUint map[uint]string
|
|||
|
MapUint8 map[uint8]string
|
|||
|
MapUint16 map[uint16]string
|
|||
|
MapUint32 map[uint32]string
|
|||
|
MapUint64 map[uint64]string
|
|||
|
MapFloat32 map[float32]string
|
|||
|
MapFloat64 map[float64]string
|
|||
|
MapBool map[bool]string
|
|||
|
}
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Inner *Inner
|
|||
|
CreatedAt *time.Time
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now()
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
CreatedAt: &now,
|
|||
|
Slice: []string{"val1", "val2", "val3"},
|
|||
|
SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}},
|
|||
|
SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}},
|
|||
|
SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}},
|
|||
|
SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}},
|
|||
|
Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"},
|
|||
|
MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}},
|
|||
|
MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}},
|
|||
|
MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}},
|
|||
|
MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}},
|
|||
|
MapInt: map[int]string{1: "val1", 2: "val2", 3: "val3"},
|
|||
|
MapInt8: map[int8]string{1: "val1", 2: "val2", 3: "val3"},
|
|||
|
MapInt16: map[int16]string{1: "val1", 2: "val2", 3: "val3"},
|
|||
|
MapInt32: map[int32]string{1: "val1", 2: "val2", 3: "val3"},
|
|||
|
MapInt64: map[int64]string{1: "val1", 2: "val2", 3: "val3"},
|
|||
|
MapUint: map[uint]string{1: "val1", 2: "val2", 3: "val3"},
|
|||
|
MapUint8: map[uint8]string{1: "val1", 2: "val2", 3: "val3"},
|
|||
|
MapUint16: map[uint16]string{1: "val1", 2: "val2", 3: "val3"},
|
|||
|
MapUint32: map[uint32]string{1: "val1", 2: "val2", 3: "val3"},
|
|||
|
MapUint64: map[uint64]string{1: "val1", 2: "val2", 3: "val3"},
|
|||
|
MapFloat32: map[float32]string{1.01: "val1", 2.02: "val2", 3.03: "val3"},
|
|||
|
MapFloat64: map[float64]string{1.01: "val1", 2.02: "val2", 3.03: "val3"},
|
|||
|
MapBool: map[bool]string{true: "val1", false: "val2"},
|
|||
|
}
|
|||
|
|
|||
|
test := &Test{
|
|||
|
Inner: inner,
|
|||
|
CreatedAt: &now,
|
|||
|
}
|
|||
|
|
|||
|
val := reflect.ValueOf(test)
|
|||
|
|
|||
|
current, kind, ok := validate.GetStructFieldOK(val, "Inner.CreatedAt")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.Struct)
|
|||
|
tm, ok := current.Interface().(time.Time)
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, tm, now)
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.Slice[1]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.CrazyNonExistantField")
|
|||
|
Equal(t, ok, false)
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.Slice[101]")
|
|||
|
Equal(t, ok, false)
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.Map[key3]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val3")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapMap[key2][key2-1]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapStructs[key2].Name")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "name2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapMapStruct[key3][key3-1].Name")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "name3")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceSlice[2][0]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "7")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceSliceStruct[2][1].Name")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "name8")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceMap[1][key5]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val5")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapSlice[key3][2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "9")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt[2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt8[2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt16[2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt32[2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapInt64[2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint[2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint8[2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint16[2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint32[2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapUint64[2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapFloat32[3.03]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val3")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapFloat64[2.02]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val2")
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.MapBool[true]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.String)
|
|||
|
Equal(t, current.String(), "val1")
|
|||
|
|
|||
|
inner = &Inner{
|
|||
|
CreatedAt: &now,
|
|||
|
Slice: []string{"val1", "val2", "val3"},
|
|||
|
SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, nil},
|
|||
|
SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}},
|
|||
|
SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}},
|
|||
|
SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}},
|
|||
|
Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"},
|
|||
|
MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}},
|
|||
|
MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}},
|
|||
|
MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}},
|
|||
|
MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}},
|
|||
|
}
|
|||
|
|
|||
|
test = &Test{
|
|||
|
Inner: inner,
|
|||
|
CreatedAt: nil,
|
|||
|
}
|
|||
|
|
|||
|
val = reflect.ValueOf(test)
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceStructs[2]")
|
|||
|
Equal(t, ok, true)
|
|||
|
Equal(t, kind, reflect.Ptr)
|
|||
|
Equal(t, current.String(), "<*validator.SliceStruct Value>")
|
|||
|
Equal(t, current.IsNil(), true)
|
|||
|
|
|||
|
current, kind, ok = validate.GetStructFieldOK(val, "Inner.SliceStructs[2].Name")
|
|||
|
Equal(t, ok, false)
|
|||
|
Equal(t, kind, reflect.Ptr)
|
|||
|
Equal(t, current.String(), "<*validator.SliceStruct Value>")
|
|||
|
Equal(t, current.IsNil(), true)
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.GetStructFieldOK(reflect.ValueOf(1), "crazyinput") }, "Invalid field namespace")
|
|||
|
}
|
|||
|
|
|||
|
func TestExistsValidation(t *testing.T) {
|
|||
|
|
|||
|
jsonText := "{ \"truthiness2\": true }"
|
|||
|
|
|||
|
type Thing struct {
|
|||
|
Truthiness *bool `json:"truthiness" validate:"exists,required"`
|
|||
|
}
|
|||
|
|
|||
|
var ting Thing
|
|||
|
|
|||
|
err := json.Unmarshal([]byte(jsonText), &ting)
|
|||
|
Equal(t, err, nil)
|
|||
|
NotEqual(t, ting, nil)
|
|||
|
Equal(t, ting.Truthiness, nil)
|
|||
|
|
|||
|
errs := validate.Struct(ting)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Thing.Truthiness", "Truthiness", "exists")
|
|||
|
|
|||
|
jsonText = "{ \"truthiness\": true }"
|
|||
|
|
|||
|
err = json.Unmarshal([]byte(jsonText), &ting)
|
|||
|
Equal(t, err, nil)
|
|||
|
NotEqual(t, ting, nil)
|
|||
|
Equal(t, ting.Truthiness, true)
|
|||
|
|
|||
|
errs = validate.Struct(ting)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestSQLValue2Validation(t *testing.T) {
|
|||
|
|
|||
|
config := &Config{
|
|||
|
TagName: "validate",
|
|||
|
}
|
|||
|
|
|||
|
validate := New(config)
|
|||
|
validate.RegisterCustomTypeFunc(ValidateValuerType, valuer{}, (*driver.Valuer)(nil), sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
|
|||
|
validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
|
|||
|
validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1)
|
|||
|
|
|||
|
val := valuer{
|
|||
|
Name: "",
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Field(val, "required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "required")
|
|||
|
|
|||
|
val.Name = "Valid Name"
|
|||
|
errs = validate.Field(val, "required")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
val.Name = "errorme"
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.Field(val, "required") }, "SQL Driver Valuer error: some kind of error")
|
|||
|
|
|||
|
type myValuer valuer
|
|||
|
|
|||
|
myVal := valuer{
|
|||
|
Name: "",
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Field(myVal, "required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "required")
|
|||
|
|
|||
|
cust := MadeUpCustomType{
|
|||
|
FirstName: "Joey",
|
|||
|
LastName: "Bloggs",
|
|||
|
}
|
|||
|
|
|||
|
c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
|
|||
|
|
|||
|
errs = validate.Struct(c)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
c.MadeUp.FirstName = ""
|
|||
|
c.OverriddenInt = 1
|
|||
|
|
|||
|
errs = validate.Struct(c)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 2)
|
|||
|
AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "MadeUp", "required")
|
|||
|
AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "gt")
|
|||
|
}
|
|||
|
|
|||
|
func TestSQLValueValidation(t *testing.T) {
|
|||
|
|
|||
|
validate := New(&Config{TagName: "validate"})
|
|||
|
validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{})
|
|||
|
validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
|
|||
|
validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1)
|
|||
|
|
|||
|
val := valuer{
|
|||
|
Name: "",
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Field(val, "required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "required")
|
|||
|
|
|||
|
val.Name = "Valid Name"
|
|||
|
errs = validate.Field(val, "required")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
val.Name = "errorme"
|
|||
|
|
|||
|
PanicMatches(t, func() { errs = validate.Field(val, "required") }, "SQL Driver Valuer error: some kind of error")
|
|||
|
|
|||
|
type myValuer valuer
|
|||
|
|
|||
|
myVal := valuer{
|
|||
|
Name: "",
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Field(myVal, "required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "required")
|
|||
|
|
|||
|
cust := MadeUpCustomType{
|
|||
|
FirstName: "Joey",
|
|||
|
LastName: "Bloggs",
|
|||
|
}
|
|||
|
|
|||
|
c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2}
|
|||
|
|
|||
|
errs = validate.Struct(c)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
c.MadeUp.FirstName = ""
|
|||
|
c.OverriddenInt = 1
|
|||
|
|
|||
|
errs = validate.Struct(c)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 2)
|
|||
|
AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "MadeUp", "required")
|
|||
|
AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "gt")
|
|||
|
}
|
|||
|
|
|||
|
func TestMACValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"3D:F2:C9:A6:B3:4F", true},
|
|||
|
{"3D-F2-C9-A6-B3:4F", false},
|
|||
|
{"123", false},
|
|||
|
{"", false},
|
|||
|
{"abacaba", false},
|
|||
|
{"00:25:96:FF:FE:12:34:56", true},
|
|||
|
{"0025:96FF:FE12:3456", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "mac")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d mac failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d mac failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "mac" {
|
|||
|
t.Fatalf("Index: %d mac failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestIPValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"10.0.0.1", true},
|
|||
|
{"172.16.0.1", true},
|
|||
|
{"192.168.0.1", true},
|
|||
|
{"192.168.255.254", true},
|
|||
|
{"192.168.255.256", false},
|
|||
|
{"172.16.255.254", true},
|
|||
|
{"172.16.256.255", false},
|
|||
|
{"2001:cdba:0000:0000:0000:0000:3257:9652", true},
|
|||
|
{"2001:cdba:0:0:0:0:3257:9652", true},
|
|||
|
{"2001:cdba::3257:9652", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "ip")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ip failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ip failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "ip" {
|
|||
|
t.Fatalf("Index: %d ip failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestIPv6Validation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"10.0.0.1", false},
|
|||
|
{"172.16.0.1", false},
|
|||
|
{"192.168.0.1", false},
|
|||
|
{"192.168.255.254", false},
|
|||
|
{"192.168.255.256", false},
|
|||
|
{"172.16.255.254", false},
|
|||
|
{"172.16.256.255", false},
|
|||
|
{"2001:cdba:0000:0000:0000:0000:3257:9652", true},
|
|||
|
{"2001:cdba:0:0:0:0:3257:9652", true},
|
|||
|
{"2001:cdba::3257:9652", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "ipv6")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "ipv6" {
|
|||
|
t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestIPv4Validation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"10.0.0.1", true},
|
|||
|
{"172.16.0.1", true},
|
|||
|
{"192.168.0.1", true},
|
|||
|
{"192.168.255.254", true},
|
|||
|
{"192.168.255.256", false},
|
|||
|
{"172.16.255.254", true},
|
|||
|
{"172.16.256.255", false},
|
|||
|
{"2001:cdba:0000:0000:0000:0000:3257:9652", false},
|
|||
|
{"2001:cdba:0:0:0:0:3257:9652", false},
|
|||
|
{"2001:cdba::3257:9652", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "ipv4")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "ipv4" {
|
|||
|
t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestCIDRValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"10.0.0.0/0", true},
|
|||
|
{"10.0.0.1/8", true},
|
|||
|
{"172.16.0.1/16", true},
|
|||
|
{"192.168.0.1/24", true},
|
|||
|
{"192.168.255.254/24", true},
|
|||
|
{"192.168.255.254/48", false},
|
|||
|
{"192.168.255.256/24", false},
|
|||
|
{"172.16.255.254/16", true},
|
|||
|
{"172.16.256.255/16", false},
|
|||
|
{"2001:cdba:0000:0000:0000:0000:3257:9652/64", true},
|
|||
|
{"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
|
|||
|
{"2001:cdba:0:0:0:0:3257:9652/32", true},
|
|||
|
{"2001:cdba::3257:9652/16", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "cidr")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "cidr" {
|
|||
|
t.Fatalf("Index: %d cidr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestCIDRv6Validation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"10.0.0.0/0", false},
|
|||
|
{"10.0.0.1/8", false},
|
|||
|
{"172.16.0.1/16", false},
|
|||
|
{"192.168.0.1/24", false},
|
|||
|
{"192.168.255.254/24", false},
|
|||
|
{"192.168.255.254/48", false},
|
|||
|
{"192.168.255.256/24", false},
|
|||
|
{"172.16.255.254/16", false},
|
|||
|
{"172.16.256.255/16", false},
|
|||
|
{"2001:cdba:0000:0000:0000:0000:3257:9652/64", true},
|
|||
|
{"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
|
|||
|
{"2001:cdba:0:0:0:0:3257:9652/32", true},
|
|||
|
{"2001:cdba::3257:9652/16", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "cidrv6")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "cidrv6" {
|
|||
|
t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestCIDRv4Validation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"10.0.0.0/0", true},
|
|||
|
{"10.0.0.1/8", true},
|
|||
|
{"172.16.0.1/16", true},
|
|||
|
{"192.168.0.1/24", true},
|
|||
|
{"192.168.255.254/24", true},
|
|||
|
{"192.168.255.254/48", false},
|
|||
|
{"192.168.255.256/24", false},
|
|||
|
{"172.16.255.254/16", true},
|
|||
|
{"172.16.256.255/16", false},
|
|||
|
{"2001:cdba:0000:0000:0000:0000:3257:9652/64", false},
|
|||
|
{"2001:cdba:0000:0000:0000:0000:3257:9652/256", false},
|
|||
|
{"2001:cdba:0:0:0:0:3257:9652/32", false},
|
|||
|
{"2001:cdba::3257:9652/16", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "cidrv4")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "cidrv4" {
|
|||
|
t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestTCPAddrValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{":80", false},
|
|||
|
{"127.0.0.1:80", true},
|
|||
|
{"[::1]:80", true},
|
|||
|
{"256.0.0.0:1", false},
|
|||
|
{"[::1]", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
errs := validate.Field(test.param, "tcp_addr")
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "tcp_addr" {
|
|||
|
t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestTCP6AddrValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{":80", false},
|
|||
|
{"127.0.0.1:80", false},
|
|||
|
{"[::1]:80", true},
|
|||
|
{"256.0.0.0:1", false},
|
|||
|
{"[::1]", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
errs := validate.Field(test.param, "tcp6_addr")
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "tcp6_addr" {
|
|||
|
t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestTCP4AddrValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{":80", false},
|
|||
|
{"127.0.0.1:80", true},
|
|||
|
{"[::1]:80", false}, // https://github.com/golang/go/issues/14037
|
|||
|
{"256.0.0.0:1", false},
|
|||
|
{"[::1]", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
errs := validate.Field(test.param, "tcp4_addr")
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Log(test.param, IsEqual(errs, nil))
|
|||
|
t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "tcp4_addr" {
|
|||
|
t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestUDPAddrValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{":80", false},
|
|||
|
{"127.0.0.1:80", true},
|
|||
|
{"[::1]:80", true},
|
|||
|
{"256.0.0.0:1", false},
|
|||
|
{"[::1]", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
errs := validate.Field(test.param, "udp_addr")
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "udp_addr" {
|
|||
|
t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestUDP6AddrValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{":80", false},
|
|||
|
{"127.0.0.1:80", false},
|
|||
|
{"[::1]:80", true},
|
|||
|
{"256.0.0.0:1", false},
|
|||
|
{"[::1]", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
errs := validate.Field(test.param, "udp6_addr")
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "udp6_addr" {
|
|||
|
t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestUDP4AddrValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{":80", false},
|
|||
|
{"127.0.0.1:80", true},
|
|||
|
{"[::1]:80", false}, // https://github.com/golang/go/issues/14037
|
|||
|
{"256.0.0.0:1", false},
|
|||
|
{"[::1]", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
errs := validate.Field(test.param, "udp4_addr")
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Log(test.param, IsEqual(errs, nil))
|
|||
|
t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "udp4_addr" {
|
|||
|
t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestIPAddrValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"127.0.0.1", true},
|
|||
|
{"127.0.0.1:80", false},
|
|||
|
{"::1", true},
|
|||
|
{"256.0.0.0", false},
|
|||
|
{"localhost", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
errs := validate.Field(test.param, "ip_addr")
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "ip_addr" {
|
|||
|
t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestIP6AddrValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"127.0.0.1", false}, // https://github.com/golang/go/issues/14037
|
|||
|
{"127.0.0.1:80", false},
|
|||
|
{"::1", true},
|
|||
|
{"0:0:0:0:0:0:0:1", true},
|
|||
|
{"256.0.0.0", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
errs := validate.Field(test.param, "ip6_addr")
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "ip6_addr" {
|
|||
|
t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestIP4AddrValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"127.0.0.1", true},
|
|||
|
{"127.0.0.1:80", false},
|
|||
|
{"::1", false}, // https://github.com/golang/go/issues/14037
|
|||
|
{"256.0.0.0", false},
|
|||
|
{"localhost", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
errs := validate.Field(test.param, "ip4_addr")
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Log(test.param, IsEqual(errs, nil))
|
|||
|
t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "ip4_addr" {
|
|||
|
t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestUnixAddrValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", true},
|
|||
|
{"v.sock", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
errs := validate.Field(test.param, "unix_addr")
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Log(test.param, IsEqual(errs, nil))
|
|||
|
t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "unix_addr" {
|
|||
|
t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {
|
|||
|
|
|||
|
var m map[string]string
|
|||
|
|
|||
|
errs := validate.Field(m, "required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "required")
|
|||
|
|
|||
|
m = map[string]string{}
|
|||
|
errs = validate.Field(m, "required")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
var arr [5]string
|
|||
|
errs = validate.Field(arr, "required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "required")
|
|||
|
|
|||
|
arr[0] = "ok"
|
|||
|
errs = validate.Field(arr, "required")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
var s []string
|
|||
|
errs = validate.Field(s, "required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "required")
|
|||
|
|
|||
|
s = []string{}
|
|||
|
errs = validate.Field(s, "required")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
var c chan string
|
|||
|
errs = validate.Field(c, "required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "required")
|
|||
|
|
|||
|
c = make(chan string)
|
|||
|
errs = validate.Field(c, "required")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
var tst *int
|
|||
|
errs = validate.Field(tst, "required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "required")
|
|||
|
|
|||
|
one := 1
|
|||
|
tst = &one
|
|||
|
errs = validate.Field(tst, "required")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
var iface interface{}
|
|||
|
|
|||
|
errs = validate.Field(iface, "required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "required")
|
|||
|
|
|||
|
errs = validate.Field(iface, "omitempty,required")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(iface, "")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(nil, iface, "")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
var f func(string)
|
|||
|
|
|||
|
errs = validate.Field(f, "required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "required")
|
|||
|
|
|||
|
f = func(name string) {}
|
|||
|
|
|||
|
errs = validate.Field(f, "required")
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestDatePtrValidationIssueValidation(t *testing.T) {
|
|||
|
|
|||
|
type Test struct {
|
|||
|
LastViewed *time.Time
|
|||
|
Reminder *time.Time
|
|||
|
}
|
|||
|
|
|||
|
test := &Test{}
|
|||
|
|
|||
|
errs := validate.Struct(test)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestCommaAndPipeObfuscationValidation(t *testing.T) {
|
|||
|
s := "My Name Is, |joeybloggs|"
|
|||
|
|
|||
|
errs := validate.Field(s, "excludesall=0x2C")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "excludesall")
|
|||
|
|
|||
|
errs = validate.Field(s, "excludesall=0x7C")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "excludesall")
|
|||
|
}
|
|||
|
|
|||
|
func TestBadKeyValidation(t *testing.T) {
|
|||
|
type Test struct {
|
|||
|
Name string `validate:"required, "`
|
|||
|
}
|
|||
|
|
|||
|
tst := &Test{
|
|||
|
Name: "test",
|
|||
|
}
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.Struct(tst) }, "Undefined validation function on field Name")
|
|||
|
|
|||
|
type Test2 struct {
|
|||
|
Name string `validate:"required,,len=2"`
|
|||
|
}
|
|||
|
|
|||
|
tst2 := &Test2{
|
|||
|
Name: "test",
|
|||
|
}
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.Struct(tst2) }, "Invalid validation tag on field Name")
|
|||
|
}
|
|||
|
|
|||
|
func TestInterfaceErrValidation(t *testing.T) {
|
|||
|
|
|||
|
var v1 interface{}
|
|||
|
var v2 interface{}
|
|||
|
|
|||
|
v2 = 1
|
|||
|
v1 = v2
|
|||
|
|
|||
|
errs := validate.Field(v1, "len=1")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(v2, "len=1")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
type ExternalCMD struct {
|
|||
|
Userid string `json:"userid"`
|
|||
|
Action uint32 `json:"action"`
|
|||
|
Data interface{} `json:"data,omitempty" validate:"required"`
|
|||
|
}
|
|||
|
|
|||
|
s := &ExternalCMD{
|
|||
|
Userid: "123456",
|
|||
|
Action: 10000,
|
|||
|
// Data: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "ExternalCMD.Data", "Data", "required")
|
|||
|
|
|||
|
type ExternalCMD2 struct {
|
|||
|
Userid string `json:"userid"`
|
|||
|
Action uint32 `json:"action"`
|
|||
|
Data interface{} `json:"data,omitempty" validate:"len=1"`
|
|||
|
}
|
|||
|
|
|||
|
s2 := &ExternalCMD2{
|
|||
|
Userid: "123456",
|
|||
|
Action: 10000,
|
|||
|
// Data: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "ExternalCMD2.Data", "Data", "len")
|
|||
|
|
|||
|
s3 := &ExternalCMD2{
|
|||
|
Userid: "123456",
|
|||
|
Action: 10000,
|
|||
|
Data: 2,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s3)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "ExternalCMD2.Data", "Data", "len")
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
Name string `validate:"required"`
|
|||
|
}
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
Name: "",
|
|||
|
}
|
|||
|
|
|||
|
s4 := &ExternalCMD{
|
|||
|
Userid: "123456",
|
|||
|
Action: 10000,
|
|||
|
Data: inner,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s4)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "ExternalCMD.Data.Name", "Name", "required")
|
|||
|
|
|||
|
type TestMapStructPtr struct {
|
|||
|
Errs map[int]interface{} `validate:"gt=0,dive,len=2"`
|
|||
|
}
|
|||
|
|
|||
|
mip := map[int]interface{}{0: &Inner{"ok"}, 3: nil, 4: &Inner{"ok"}}
|
|||
|
|
|||
|
msp := &TestMapStructPtr{
|
|||
|
Errs: mip,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(msp)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "TestMapStructPtr.Errs[3]", "Errs[3]", "len")
|
|||
|
|
|||
|
type TestMultiDimensionalStructs struct {
|
|||
|
Errs [][]interface{} `validate:"gt=0,dive,dive"`
|
|||
|
}
|
|||
|
|
|||
|
var errStructArray [][]interface{}
|
|||
|
|
|||
|
errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
|
|||
|
errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
|
|||
|
|
|||
|
tms := &TestMultiDimensionalStructs{
|
|||
|
Errs: errStructArray,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tms)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 4)
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "required")
|
|||
|
|
|||
|
type TestMultiDimensionalStructsPtr2 struct {
|
|||
|
Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
|
|||
|
}
|
|||
|
|
|||
|
var errStructPtr2Array [][]*Inner
|
|||
|
|
|||
|
errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
|
|||
|
errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
|
|||
|
errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
|
|||
|
|
|||
|
tmsp2 := &TestMultiDimensionalStructsPtr2{
|
|||
|
Errs: errStructPtr2Array,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tmsp2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 6)
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "required")
|
|||
|
|
|||
|
m := map[int]interface{}{0: "ok", 3: "", 4: "ok"}
|
|||
|
|
|||
|
errs = validate.Field(m, "len=3,dive,len=2")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "[3]", "[3]", "len")
|
|||
|
|
|||
|
errs = validate.Field(m, "len=2,dive,required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "", "", "len")
|
|||
|
|
|||
|
arr := []interface{}{"ok", "", "ok"}
|
|||
|
|
|||
|
errs = validate.Field(arr, "len=3,dive,len=2")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "[1]", "[1]", "len")
|
|||
|
|
|||
|
errs = validate.Field(arr, "len=2,dive,required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "", "", "len")
|
|||
|
|
|||
|
type MyStruct struct {
|
|||
|
A, B string
|
|||
|
C interface{}
|
|||
|
}
|
|||
|
|
|||
|
var a MyStruct
|
|||
|
|
|||
|
a.A = "value"
|
|||
|
a.C = "nu"
|
|||
|
|
|||
|
errs = validate.Struct(a)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestMapDiveValidation(t *testing.T) {
|
|||
|
|
|||
|
n := map[int]interface{}{0: nil}
|
|||
|
errs := validate.Field(n, "omitempty,required")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
m := map[int]string{0: "ok", 3: "", 4: "ok"}
|
|||
|
|
|||
|
errs = validate.Field(m, "len=3,dive,required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "[3]", "[3]", "required")
|
|||
|
|
|||
|
errs = validate.Field(m, "len=2,dive,required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "", "", "len")
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
Name string `validate:"required"`
|
|||
|
}
|
|||
|
|
|||
|
type TestMapStruct struct {
|
|||
|
Errs map[int]Inner `validate:"gt=0,dive"`
|
|||
|
}
|
|||
|
|
|||
|
mi := map[int]Inner{0: {"ok"}, 3: {""}, 4: {"ok"}}
|
|||
|
|
|||
|
ms := &TestMapStruct{
|
|||
|
Errs: mi,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(ms)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "TestMapStruct.Errs[3].Name", "Name", "required")
|
|||
|
|
|||
|
// for full test coverage
|
|||
|
s := fmt.Sprint(errs.Error())
|
|||
|
NotEqual(t, s, "")
|
|||
|
|
|||
|
type TestMapTimeStruct struct {
|
|||
|
Errs map[int]*time.Time `validate:"gt=0,dive,required"`
|
|||
|
}
|
|||
|
|
|||
|
t1 := time.Now().UTC()
|
|||
|
|
|||
|
mta := map[int]*time.Time{0: &t1, 3: nil, 4: nil}
|
|||
|
|
|||
|
mt := &TestMapTimeStruct{
|
|||
|
Errs: mta,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(mt)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 2)
|
|||
|
AssertError(t, errs, "TestMapTimeStruct.Errs[3]", "Errs[3]", "required")
|
|||
|
AssertError(t, errs, "TestMapTimeStruct.Errs[4]", "Errs[4]", "required")
|
|||
|
|
|||
|
type TestMapStructPtr struct {
|
|||
|
Errs map[int]*Inner `validate:"gt=0,dive,required"`
|
|||
|
}
|
|||
|
|
|||
|
mip := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
|
|||
|
|
|||
|
msp := &TestMapStructPtr{
|
|||
|
Errs: mip,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(msp)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "TestMapStructPtr.Errs[3]", "Errs[3]", "required")
|
|||
|
|
|||
|
type TestMapStructPtr2 struct {
|
|||
|
Errs map[int]*Inner `validate:"gt=0,dive,omitempty,required"`
|
|||
|
}
|
|||
|
|
|||
|
mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
|
|||
|
|
|||
|
msp2 := &TestMapStructPtr2{
|
|||
|
Errs: mip2,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(msp2)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestArrayDiveValidation(t *testing.T) {
|
|||
|
|
|||
|
arr := []string{"ok", "", "ok"}
|
|||
|
|
|||
|
errs := validate.Field(arr, "len=3,dive,required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "[1]", "[1]", "required")
|
|||
|
|
|||
|
errs = validate.Field(arr, "len=2,dive,required")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "", "", "len")
|
|||
|
|
|||
|
type BadDive struct {
|
|||
|
Name string `validate:"dive"`
|
|||
|
}
|
|||
|
|
|||
|
bd := &BadDive{
|
|||
|
Name: "TEST",
|
|||
|
}
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.Struct(bd) }, "dive error! can't dive on a non slice or map")
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Errs []string `validate:"gt=0,dive,required"`
|
|||
|
}
|
|||
|
|
|||
|
test := &Test{
|
|||
|
Errs: []string{"ok", "", "ok"},
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(test)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "Test.Errs[1]", "Errs[1]", "required")
|
|||
|
|
|||
|
test = &Test{
|
|||
|
Errs: []string{"ok", "ok", ""},
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(test)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 1)
|
|||
|
AssertError(t, errs, "Test.Errs[2]", "Errs[2]", "required")
|
|||
|
|
|||
|
type TestMultiDimensional struct {
|
|||
|
Errs [][]string `validate:"gt=0,dive,dive,required"`
|
|||
|
}
|
|||
|
|
|||
|
var errArray [][]string
|
|||
|
|
|||
|
errArray = append(errArray, []string{"ok", "", ""})
|
|||
|
errArray = append(errArray, []string{"ok", "", ""})
|
|||
|
|
|||
|
tm := &TestMultiDimensional{
|
|||
|
Errs: errArray,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tm)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 4)
|
|||
|
AssertError(t, errs, "TestMultiDimensional.Errs[0][1]", "Errs[0][1]", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensional.Errs[0][2]", "Errs[0][2]", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensional.Errs[1][1]", "Errs[1][1]", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensional.Errs[1][2]", "Errs[1][2]", "required")
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
Name string `validate:"required"`
|
|||
|
}
|
|||
|
|
|||
|
type TestMultiDimensionalStructs struct {
|
|||
|
Errs [][]Inner `validate:"gt=0,dive,dive"`
|
|||
|
}
|
|||
|
|
|||
|
var errStructArray [][]Inner
|
|||
|
|
|||
|
errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
|
|||
|
errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
|
|||
|
|
|||
|
tms := &TestMultiDimensionalStructs{
|
|||
|
Errs: errStructArray,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tms)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 4)
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "required")
|
|||
|
|
|||
|
type TestMultiDimensionalStructsPtr struct {
|
|||
|
Errs [][]*Inner `validate:"gt=0,dive,dive"`
|
|||
|
}
|
|||
|
|
|||
|
var errStructPtrArray [][]*Inner
|
|||
|
|
|||
|
errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
|
|||
|
errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
|
|||
|
errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, nil})
|
|||
|
|
|||
|
tmsp := &TestMultiDimensionalStructsPtr{
|
|||
|
Errs: errStructPtrArray,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tmsp)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 5)
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[2][1].Name", "Name", "required")
|
|||
|
|
|||
|
// for full test coverage
|
|||
|
s := fmt.Sprint(errs.Error())
|
|||
|
NotEqual(t, s, "")
|
|||
|
|
|||
|
type TestMultiDimensionalStructsPtr2 struct {
|
|||
|
Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
|
|||
|
}
|
|||
|
|
|||
|
var errStructPtr2Array [][]*Inner
|
|||
|
|
|||
|
errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
|
|||
|
errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
|
|||
|
errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
|
|||
|
|
|||
|
tmsp2 := &TestMultiDimensionalStructsPtr2{
|
|||
|
Errs: errStructPtr2Array,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tmsp2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 6)
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "required")
|
|||
|
|
|||
|
type TestMultiDimensionalStructsPtr3 struct {
|
|||
|
Errs [][]*Inner `validate:"gt=0,dive,dive,omitempty"`
|
|||
|
}
|
|||
|
|
|||
|
var errStructPtr3Array [][]*Inner
|
|||
|
|
|||
|
errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
|
|||
|
errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
|
|||
|
errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, nil})
|
|||
|
|
|||
|
tmsp3 := &TestMultiDimensionalStructsPtr3{
|
|||
|
Errs: errStructPtr3Array,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tmsp3)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 5)
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "Name", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[2][1].Name", "Name", "required")
|
|||
|
|
|||
|
type TestMultiDimensionalTimeTime struct {
|
|||
|
Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
|
|||
|
}
|
|||
|
|
|||
|
var errTimePtr3Array [][]*time.Time
|
|||
|
|
|||
|
t1 := time.Now().UTC()
|
|||
|
t2 := time.Now().UTC()
|
|||
|
t3 := time.Now().UTC().Add(time.Hour * 24)
|
|||
|
|
|||
|
errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, &t3})
|
|||
|
errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, nil})
|
|||
|
errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, nil, nil})
|
|||
|
|
|||
|
tmtp3 := &TestMultiDimensionalTimeTime{
|
|||
|
Errs: errTimePtr3Array,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tmtp3)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 3)
|
|||
|
AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[1][2]", "Errs[1][2]", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][1]", "Errs[2][1]", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][2]", "Errs[2][2]", "required")
|
|||
|
|
|||
|
type TestMultiDimensionalTimeTime2 struct {
|
|||
|
Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
|
|||
|
}
|
|||
|
|
|||
|
var errTimeArray [][]*time.Time
|
|||
|
|
|||
|
t1 = time.Now().UTC()
|
|||
|
t2 = time.Now().UTC()
|
|||
|
t3 = time.Now().UTC().Add(time.Hour * 24)
|
|||
|
|
|||
|
errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, &t3})
|
|||
|
errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, nil})
|
|||
|
errTimeArray = append(errTimeArray, []*time.Time{&t1, nil, nil})
|
|||
|
|
|||
|
tmtp := &TestMultiDimensionalTimeTime2{
|
|||
|
Errs: errTimeArray,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tmtp)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 3)
|
|||
|
AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[1][2]", "Errs[1][2]", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][1]", "Errs[2][1]", "required")
|
|||
|
AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][2]", "Errs[2][2]", "required")
|
|||
|
}
|
|||
|
|
|||
|
func TestNilStructPointerValidation(t *testing.T) {
|
|||
|
type Inner struct {
|
|||
|
Data string
|
|||
|
}
|
|||
|
|
|||
|
type Outer struct {
|
|||
|
Inner *Inner `validate:"omitempty"`
|
|||
|
}
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
Data: "test",
|
|||
|
}
|
|||
|
|
|||
|
outer := &Outer{
|
|||
|
Inner: inner,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(outer)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
outer = &Outer{
|
|||
|
Inner: nil,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(outer)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
type Inner2 struct {
|
|||
|
Data string
|
|||
|
}
|
|||
|
|
|||
|
type Outer2 struct {
|
|||
|
Inner2 *Inner2 `validate:"required"`
|
|||
|
}
|
|||
|
|
|||
|
inner2 := &Inner2{
|
|||
|
Data: "test",
|
|||
|
}
|
|||
|
|
|||
|
outer2 := &Outer2{
|
|||
|
Inner2: inner2,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(outer2)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
outer2 = &Outer2{
|
|||
|
Inner2: nil,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(outer2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Outer2.Inner2", "Inner2", "required")
|
|||
|
|
|||
|
type Inner3 struct {
|
|||
|
Data string
|
|||
|
}
|
|||
|
|
|||
|
type Outer3 struct {
|
|||
|
Inner3 *Inner3
|
|||
|
}
|
|||
|
|
|||
|
inner3 := &Inner3{
|
|||
|
Data: "test",
|
|||
|
}
|
|||
|
|
|||
|
outer3 := &Outer3{
|
|||
|
Inner3: inner3,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(outer3)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
type Inner4 struct {
|
|||
|
Data string
|
|||
|
}
|
|||
|
|
|||
|
type Outer4 struct {
|
|||
|
Inner4 *Inner4 `validate:"-"`
|
|||
|
}
|
|||
|
|
|||
|
inner4 := &Inner4{
|
|||
|
Data: "test",
|
|||
|
}
|
|||
|
|
|||
|
outer4 := &Outer4{
|
|||
|
Inner4: inner4,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(outer4)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestSSNValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"00-90-8787", false},
|
|||
|
{"66690-76", false},
|
|||
|
{"191 60 2869", true},
|
|||
|
{"191-60-2869", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "ssn")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d SSN failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "ssn" {
|
|||
|
t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestLongitudeValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"-180.000", true},
|
|||
|
{"180.1", false},
|
|||
|
{"+73.234", true},
|
|||
|
{"+382.3811", false},
|
|||
|
{"23.11111111", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "longitude")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d Longitude failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "longitude" {
|
|||
|
t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestLatitudeValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"-90.000", true},
|
|||
|
{"+90", true},
|
|||
|
{"47.1231231", true},
|
|||
|
{"+99.9", false},
|
|||
|
{"108", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "latitude")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "latitude" {
|
|||
|
t.Fatalf("Index: %d Latitude failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestDataURIValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"data:image/png;base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true},
|
|||
|
{"data:text/plain;base64,Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true},
|
|||
|
{"image/gif;base64,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
|
|||
|
{"data:image/gif;base64,MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" +
|
|||
|
"UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" +
|
|||
|
"rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" +
|
|||
|
"FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" +
|
|||
|
"QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" +
|
|||
|
"Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true},
|
|||
|
{"data:image/png;base64,12345", false},
|
|||
|
{"", false},
|
|||
|
{"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "datauri")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "datauri" {
|
|||
|
t.Fatalf("Index: %d DataURI failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestMultibyteValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", true},
|
|||
|
{"abc", false},
|
|||
|
{"123", false},
|
|||
|
{"<>@;.-=", false},
|
|||
|
{"ひらがな・カタカナ、.漢字", true},
|
|||
|
{"あいうえお foobar", true},
|
|||
|
{"test@example.com", true},
|
|||
|
{"test@example.com", true},
|
|||
|
{"1234abcDExyz", true},
|
|||
|
{"カタカナ", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "multibyte")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "multibyte" {
|
|||
|
t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestPrintableASCIIValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", true},
|
|||
|
{"foobar", false},
|
|||
|
{"xyz098", false},
|
|||
|
{"123456", false},
|
|||
|
{"カタカナ", false},
|
|||
|
{"foobar", true},
|
|||
|
{"0987654321", true},
|
|||
|
{"test@example.com", true},
|
|||
|
{"1234abcDEF", true},
|
|||
|
{"newline\n", false},
|
|||
|
{"\x19test\x7F", false},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "printascii")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "printascii" {
|
|||
|
t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestASCIIValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", true},
|
|||
|
{"foobar", false},
|
|||
|
{"xyz098", false},
|
|||
|
{"123456", false},
|
|||
|
{"カタカナ", false},
|
|||
|
{"foobar", true},
|
|||
|
{"0987654321", true},
|
|||
|
{"test@example.com", true},
|
|||
|
{"1234abcDEF", true},
|
|||
|
{"", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "ascii")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "ascii" {
|
|||
|
t.Fatalf("Index: %d ASCII failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestUUID5Validation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
|
|||
|
{"", false},
|
|||
|
{"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
|
|||
|
{"9c858901-8a57-4791-81fe-4c455b099bc9", false},
|
|||
|
{"a987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
|
|||
|
{"987fbc97-4bed-5078-af07-9141ba07c9f3", true},
|
|||
|
{"987fbc97-4bed-5078-9f07-9141ba07c9f3", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "uuid5")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "uuid5" {
|
|||
|
t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestUUID4Validation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
|
|||
|
{"a987fbc9-4bed-5078-af07-9141ba07c9f3", false},
|
|||
|
{"934859", false},
|
|||
|
{"57b73598-8764-4ad0-a76a-679bb6640eb1", true},
|
|||
|
{"625e63f3-58f5-40b7-83a1-a72ad31acffb", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "uuid4")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "uuid4" {
|
|||
|
t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestUUID3Validation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"412452646", false},
|
|||
|
{"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
|
|||
|
{"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false},
|
|||
|
{"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "uuid3")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "uuid3" {
|
|||
|
t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestUUIDValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
|
|||
|
{"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false},
|
|||
|
{"a987fbc94bed3078cf079141ba07c9f3", false},
|
|||
|
{"934859", false},
|
|||
|
{"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false},
|
|||
|
{"aaaaaaaa-1111-1111-aaag-111111111111", false},
|
|||
|
{"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "uuid")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "uuid" {
|
|||
|
t.Fatalf("Index: %d UUID failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestISBNValidation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"foo", false},
|
|||
|
{"3836221195", true},
|
|||
|
{"1-61729-085-8", true},
|
|||
|
{"3 423 21412 0", true},
|
|||
|
{"3 401 01319 X", true},
|
|||
|
{"9784873113685", true},
|
|||
|
{"978-4-87311-368-5", true},
|
|||
|
{"978 3401013190", true},
|
|||
|
{"978-3-8362-2119-1", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "isbn")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "isbn" {
|
|||
|
t.Fatalf("Index: %d ISBN failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestISBN13Validation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"foo", false},
|
|||
|
{"3-8362-2119-5", false},
|
|||
|
{"01234567890ab", false},
|
|||
|
{"978 3 8362 2119 0", false},
|
|||
|
{"9784873113685", true},
|
|||
|
{"978-4-87311-368-5", true},
|
|||
|
{"978 3401013190", true},
|
|||
|
{"978-3-8362-2119-1", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "isbn13")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "isbn13" {
|
|||
|
t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestISBN10Validation(t *testing.T) {
|
|||
|
tests := []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"", false},
|
|||
|
{"foo", false},
|
|||
|
{"3423214121", false},
|
|||
|
{"978-3836221191", false},
|
|||
|
{"3-423-21412-1", false},
|
|||
|
{"3 423 21412 1", false},
|
|||
|
{"3836221195", true},
|
|||
|
{"1-61729-085-8", true},
|
|||
|
{"3 423 21412 0", true},
|
|||
|
{"3 401 01319 X", true},
|
|||
|
}
|
|||
|
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "isbn10")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "isbn10" {
|
|||
|
t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestExcludesRuneValidation(t *testing.T) {
|
|||
|
|
|||
|
tests := []struct {
|
|||
|
Value string `validate:"excludesrune=☻"`
|
|||
|
Tag string
|
|||
|
ExpectedNil bool
|
|||
|
}{
|
|||
|
{Value: "a☺b☻c☹d", Tag: "excludesrune=☻", ExpectedNil: false},
|
|||
|
{Value: "abcd", Tag: "excludesrune=☻", ExpectedNil: true},
|
|||
|
}
|
|||
|
|
|||
|
for i, s := range tests {
|
|||
|
errs := validate.Field(s.Value, s.Tag)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestExcludesAllValidation(t *testing.T) {
|
|||
|
|
|||
|
tests := []struct {
|
|||
|
Value string `validate:"excludesall=@!{}[]"`
|
|||
|
Tag string
|
|||
|
ExpectedNil bool
|
|||
|
}{
|
|||
|
{Value: "abcd@!jfk", Tag: "excludesall=@!{}[]", ExpectedNil: false},
|
|||
|
{Value: "abcdefg", Tag: "excludesall=@!{}[]", ExpectedNil: true},
|
|||
|
}
|
|||
|
|
|||
|
for i, s := range tests {
|
|||
|
errs := validate.Field(s.Value, s.Tag)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
username := "joeybloggs "
|
|||
|
|
|||
|
errs := validate.Field(username, "excludesall=@ ")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "excludesall")
|
|||
|
|
|||
|
excluded := ","
|
|||
|
|
|||
|
errs = validate.Field(excluded, "excludesall=!@#$%^&*()_+.0x2C?")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "excludesall")
|
|||
|
|
|||
|
excluded = "="
|
|||
|
|
|||
|
errs = validate.Field(excluded, "excludesall=!@#$%^&*()_+.0x2C=?")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "excludesall")
|
|||
|
}
|
|||
|
|
|||
|
func TestExcludesValidation(t *testing.T) {
|
|||
|
|
|||
|
tests := []struct {
|
|||
|
Value string `validate:"excludes=@"`
|
|||
|
Tag string
|
|||
|
ExpectedNil bool
|
|||
|
}{
|
|||
|
{Value: "abcd@!jfk", Tag: "excludes=@", ExpectedNil: false},
|
|||
|
{Value: "abcdq!jfk", Tag: "excludes=@", ExpectedNil: true},
|
|||
|
}
|
|||
|
|
|||
|
for i, s := range tests {
|
|||
|
errs := validate.Field(s.Value, s.Tag)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestContainsRuneValidation(t *testing.T) {
|
|||
|
|
|||
|
tests := []struct {
|
|||
|
Value string `validate:"containsrune=☻"`
|
|||
|
Tag string
|
|||
|
ExpectedNil bool
|
|||
|
}{
|
|||
|
{Value: "a☺b☻c☹d", Tag: "containsrune=☻", ExpectedNil: true},
|
|||
|
{Value: "abcd", Tag: "containsrune=☻", ExpectedNil: false},
|
|||
|
}
|
|||
|
|
|||
|
for i, s := range tests {
|
|||
|
errs := validate.Field(s.Value, s.Tag)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestContainsAnyValidation(t *testing.T) {
|
|||
|
|
|||
|
tests := []struct {
|
|||
|
Value string `validate:"containsany=@!{}[]"`
|
|||
|
Tag string
|
|||
|
ExpectedNil bool
|
|||
|
}{
|
|||
|
{Value: "abcd@!jfk", Tag: "containsany=@!{}[]", ExpectedNil: true},
|
|||
|
{Value: "abcdefg", Tag: "containsany=@!{}[]", ExpectedNil: false},
|
|||
|
}
|
|||
|
|
|||
|
for i, s := range tests {
|
|||
|
errs := validate.Field(s.Value, s.Tag)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestContainsValidation(t *testing.T) {
|
|||
|
|
|||
|
tests := []struct {
|
|||
|
Value string `validate:"contains=@"`
|
|||
|
Tag string
|
|||
|
ExpectedNil bool
|
|||
|
}{
|
|||
|
{Value: "abcd@!jfk", Tag: "contains=@", ExpectedNil: true},
|
|||
|
{Value: "abcdq!jfk", Tag: "contains=@", ExpectedNil: false},
|
|||
|
}
|
|||
|
|
|||
|
for i, s := range tests {
|
|||
|
errs := validate.Field(s.Value, s.Tag)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
|
|||
|
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
|
|||
|
t.Fatalf("Index: %d failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func TestIsNeFieldValidation(t *testing.T) {
|
|||
|
|
|||
|
var j uint64
|
|||
|
var k float64
|
|||
|
s := "abcd"
|
|||
|
i := 1
|
|||
|
j = 1
|
|||
|
k = 1.543
|
|||
|
arr := []string{"test"}
|
|||
|
now := time.Now().UTC()
|
|||
|
|
|||
|
var j2 uint64
|
|||
|
var k2 float64
|
|||
|
s2 := "abcdef"
|
|||
|
i2 := 3
|
|||
|
j2 = 2
|
|||
|
k2 = 1.5434456
|
|||
|
arr2 := []string{"test", "test2"}
|
|||
|
arr3 := []string{"test"}
|
|||
|
now2 := now
|
|||
|
|
|||
|
errs := validate.FieldWithValue(s, s2, "nefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(i2, i, "nefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(j2, j, "nefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(k2, k, "nefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(arr2, arr, "nefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(now2, now, "nefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "nefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(arr3, arr, "nefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "nefield")
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Start *time.Time `validate:"nefield=End"`
|
|||
|
End *time.Time
|
|||
|
}
|
|||
|
|
|||
|
sv := &Test{
|
|||
|
Start: &now,
|
|||
|
End: &now,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(sv)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.Start", "Start", "nefield")
|
|||
|
|
|||
|
now3 := time.Now().UTC()
|
|||
|
|
|||
|
sv = &Test{
|
|||
|
Start: &now,
|
|||
|
End: &now3,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(sv)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(nil, 1, "nefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(sv, now, "nefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
type Test2 struct {
|
|||
|
Start *time.Time `validate:"nefield=NonExistantField"`
|
|||
|
End *time.Time
|
|||
|
}
|
|||
|
|
|||
|
sv2 := &Test2{
|
|||
|
Start: &now,
|
|||
|
End: &now,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(sv2)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestIsNeValidation(t *testing.T) {
|
|||
|
|
|||
|
var j uint64
|
|||
|
var k float64
|
|||
|
s := "abcdef"
|
|||
|
i := 3
|
|||
|
j = 2
|
|||
|
k = 1.5434
|
|||
|
arr := []string{"test"}
|
|||
|
now := time.Now().UTC()
|
|||
|
|
|||
|
errs := validate.Field(s, "ne=abcd")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(i, "ne=1")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(j, "ne=1")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(k, "ne=1.543")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(arr, "ne=2")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(arr, "ne=1")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ne")
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.Field(now, "ne=now") }, "Bad field type time.Time")
|
|||
|
}
|
|||
|
|
|||
|
func TestIsEqFieldValidation(t *testing.T) {
|
|||
|
|
|||
|
var j uint64
|
|||
|
var k float64
|
|||
|
s := "abcd"
|
|||
|
i := 1
|
|||
|
j = 1
|
|||
|
k = 1.543
|
|||
|
arr := []string{"test"}
|
|||
|
now := time.Now().UTC()
|
|||
|
|
|||
|
var j2 uint64
|
|||
|
var k2 float64
|
|||
|
s2 := "abcd"
|
|||
|
i2 := 1
|
|||
|
j2 = 1
|
|||
|
k2 = 1.543
|
|||
|
arr2 := []string{"test"}
|
|||
|
arr3 := []string{"test", "test2"}
|
|||
|
now2 := now
|
|||
|
|
|||
|
errs := validate.FieldWithValue(s, s2, "eqfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(i2, i, "eqfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(j2, j, "eqfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(k2, k, "eqfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(arr2, arr, "eqfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(now2, now, "eqfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(arr3, arr, "eqfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "eqfield")
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Start *time.Time `validate:"eqfield=End"`
|
|||
|
End *time.Time
|
|||
|
}
|
|||
|
|
|||
|
sv := &Test{
|
|||
|
Start: &now,
|
|||
|
End: &now,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(sv)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
now3 := time.Now().UTC()
|
|||
|
|
|||
|
sv = &Test{
|
|||
|
Start: &now,
|
|||
|
End: &now3,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(sv)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.Start", "Start", "eqfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(nil, 1, "eqfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "eqfield")
|
|||
|
|
|||
|
channel := make(chan string)
|
|||
|
errs = validate.FieldWithValue(5, channel, "eqfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "eqfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(5, now, "eqfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "eqfield")
|
|||
|
|
|||
|
type Test2 struct {
|
|||
|
Start *time.Time `validate:"eqfield=NonExistantField"`
|
|||
|
End *time.Time
|
|||
|
}
|
|||
|
|
|||
|
sv2 := &Test2{
|
|||
|
Start: &now,
|
|||
|
End: &now,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(sv2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test2.Start", "Start", "eqfield")
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
Name string
|
|||
|
}
|
|||
|
|
|||
|
type TStruct struct {
|
|||
|
Inner *Inner
|
|||
|
CreatedAt *time.Time `validate:"eqfield=Inner"`
|
|||
|
}
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
Name: "NAME",
|
|||
|
}
|
|||
|
|
|||
|
test := &TStruct{
|
|||
|
Inner: inner,
|
|||
|
CreatedAt: &now,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(test)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TStruct.CreatedAt", "CreatedAt", "eqfield")
|
|||
|
}
|
|||
|
|
|||
|
func TestIsEqValidation(t *testing.T) {
|
|||
|
|
|||
|
var j uint64
|
|||
|
var k float64
|
|||
|
s := "abcd"
|
|||
|
i := 1
|
|||
|
j = 1
|
|||
|
k = 1.543
|
|||
|
arr := []string{"test"}
|
|||
|
now := time.Now().UTC()
|
|||
|
|
|||
|
errs := validate.Field(s, "eq=abcd")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(i, "eq=1")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(j, "eq=1")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(k, "eq=1.543")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(arr, "eq=1")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.Field(arr, "eq=2")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "eq")
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.Field(now, "eq=now") }, "Bad field type time.Time")
|
|||
|
}
|
|||
|
|
|||
|
func TestBase64Validation(t *testing.T) {
|
|||
|
|
|||
|
s := "dW5pY29ybg=="
|
|||
|
|
|||
|
errs := validate.Field(s, "base64")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "dGhpIGlzIGEgdGVzdCBiYXNlNjQ="
|
|||
|
errs = validate.Field(s, "base64")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = ""
|
|||
|
errs = validate.Field(s, "base64")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "base64")
|
|||
|
|
|||
|
s = "dW5pY29ybg== foo bar"
|
|||
|
errs = validate.Field(s, "base64")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "base64")
|
|||
|
}
|
|||
|
|
|||
|
func TestNoStructLevelValidation(t *testing.T) {
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
Test string `validate:"len=5"`
|
|||
|
}
|
|||
|
|
|||
|
type Outer struct {
|
|||
|
InnerStruct *Inner `validate:"required,nostructlevel"`
|
|||
|
}
|
|||
|
|
|||
|
outer := &Outer{
|
|||
|
InnerStruct: nil,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(outer)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required")
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
Test: "1234",
|
|||
|
}
|
|||
|
|
|||
|
outer = &Outer{
|
|||
|
InnerStruct: inner,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(outer)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestStructOnlyValidation(t *testing.T) {
|
|||
|
|
|||
|
type Inner struct {
|
|||
|
Test string `validate:"len=5"`
|
|||
|
}
|
|||
|
|
|||
|
type Outer struct {
|
|||
|
InnerStruct *Inner `validate:"required,structonly"`
|
|||
|
}
|
|||
|
|
|||
|
outer := &Outer{
|
|||
|
InnerStruct: nil,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(outer)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required")
|
|||
|
|
|||
|
inner := &Inner{
|
|||
|
Test: "1234",
|
|||
|
}
|
|||
|
|
|||
|
outer = &Outer{
|
|||
|
InnerStruct: inner,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(outer)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestGtField(t *testing.T) {
|
|||
|
|
|||
|
type TimeTest struct {
|
|||
|
Start *time.Time `validate:"required,gt"`
|
|||
|
End *time.Time `validate:"required,gt,gtfield=Start"`
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now()
|
|||
|
start := now.Add(time.Hour * 24)
|
|||
|
end := start.Add(time.Hour * 24)
|
|||
|
|
|||
|
timeTest := &TimeTest{
|
|||
|
Start: &start,
|
|||
|
End: &end,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(timeTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
timeTest = &TimeTest{
|
|||
|
Start: &end,
|
|||
|
End: &start,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(timeTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TimeTest.End", "End", "gtfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(&start, &end, "gtfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(&end, &start, "gtfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(&timeTest, &end, "gtfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue("test", "test bigger", "gtfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
type IntTest struct {
|
|||
|
Val1 int `validate:"required"`
|
|||
|
Val2 int `validate:"required,gtfield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
intTest := &IntTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(intTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
intTest = &IntTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(intTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "IntTest.Val2", "Val2", "gtfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(int(1), int(5), "gtfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(int(5), int(1), "gtfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtfield")
|
|||
|
|
|||
|
type UIntTest struct {
|
|||
|
Val1 uint `validate:"required"`
|
|||
|
Val2 uint `validate:"required,gtfield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
uIntTest := &UIntTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(uIntTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
uIntTest = &UIntTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(uIntTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "UIntTest.Val2", "Val2", "gtfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(uint(1), uint(5), "gtfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(uint(5), uint(1), "gtfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtfield")
|
|||
|
|
|||
|
type FloatTest struct {
|
|||
|
Val1 float64 `validate:"required"`
|
|||
|
Val2 float64 `validate:"required,gtfield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
floatTest := &FloatTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(floatTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
floatTest = &FloatTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(floatTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "FloatTest.Val2", "Val2", "gtfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(float32(1), float32(5), "gtfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(float32(5), float32(1), "gtfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(nil, 1, "gtfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(5, "T", "gtfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(5, start, "gtfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtfield")
|
|||
|
|
|||
|
type TimeTest2 struct {
|
|||
|
Start *time.Time `validate:"required"`
|
|||
|
End *time.Time `validate:"required,gtfield=NonExistantField"`
|
|||
|
}
|
|||
|
|
|||
|
timeTest2 := &TimeTest2{
|
|||
|
Start: &start,
|
|||
|
End: &end,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(timeTest2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TimeTest2.End", "End", "gtfield")
|
|||
|
}
|
|||
|
|
|||
|
func TestLtField(t *testing.T) {
|
|||
|
|
|||
|
type TimeTest struct {
|
|||
|
Start *time.Time `validate:"required,lt,ltfield=End"`
|
|||
|
End *time.Time `validate:"required,lt"`
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now()
|
|||
|
start := now.Add(time.Hour * 24 * -1 * 2)
|
|||
|
end := start.Add(time.Hour * 24)
|
|||
|
|
|||
|
timeTest := &TimeTest{
|
|||
|
Start: &start,
|
|||
|
End: &end,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(timeTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
timeTest = &TimeTest{
|
|||
|
Start: &end,
|
|||
|
End: &start,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(timeTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TimeTest.Start", "Start", "ltfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(&end, &start, "ltfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(&start, &end, "ltfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(timeTest, &end, "ltfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue("test", "tes", "ltfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
type IntTest struct {
|
|||
|
Val1 int `validate:"required"`
|
|||
|
Val2 int `validate:"required,ltfield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
intTest := &IntTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(intTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
intTest = &IntTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(intTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "IntTest.Val2", "Val2", "ltfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(int(5), int(1), "ltfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(int(1), int(5), "ltfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltfield")
|
|||
|
|
|||
|
type UIntTest struct {
|
|||
|
Val1 uint `validate:"required"`
|
|||
|
Val2 uint `validate:"required,ltfield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
uIntTest := &UIntTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(uIntTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
uIntTest = &UIntTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(uIntTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "UIntTest.Val2", "Val2", "ltfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(uint(5), uint(1), "ltfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(uint(1), uint(5), "ltfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltfield")
|
|||
|
|
|||
|
type FloatTest struct {
|
|||
|
Val1 float64 `validate:"required"`
|
|||
|
Val2 float64 `validate:"required,ltfield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
floatTest := &FloatTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(floatTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
floatTest = &FloatTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(floatTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "FloatTest.Val2", "Val2", "ltfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(float32(5), float32(1), "ltfield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(float32(1), float32(5), "ltfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(nil, 5, "ltfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(1, "T", "ltfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltfield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(1, end, "ltfield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltfield")
|
|||
|
|
|||
|
type TimeTest2 struct {
|
|||
|
Start *time.Time `validate:"required"`
|
|||
|
End *time.Time `validate:"required,ltfield=NonExistantField"`
|
|||
|
}
|
|||
|
|
|||
|
timeTest2 := &TimeTest2{
|
|||
|
Start: &end,
|
|||
|
End: &start,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(timeTest2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TimeTest2.End", "End", "ltfield")
|
|||
|
}
|
|||
|
|
|||
|
func TestLteField(t *testing.T) {
|
|||
|
|
|||
|
type TimeTest struct {
|
|||
|
Start *time.Time `validate:"required,lte,ltefield=End"`
|
|||
|
End *time.Time `validate:"required,lte"`
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now()
|
|||
|
start := now.Add(time.Hour * 24 * -1 * 2)
|
|||
|
end := start.Add(time.Hour * 24)
|
|||
|
|
|||
|
timeTest := &TimeTest{
|
|||
|
Start: &start,
|
|||
|
End: &end,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(timeTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
timeTest = &TimeTest{
|
|||
|
Start: &end,
|
|||
|
End: &start,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(timeTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TimeTest.Start", "Start", "ltefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(&end, &start, "ltefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(&start, &end, "ltefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(timeTest, &end, "ltefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue("test", "tes", "ltefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue("test", "test", "ltefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
type IntTest struct {
|
|||
|
Val1 int `validate:"required"`
|
|||
|
Val2 int `validate:"required,ltefield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
intTest := &IntTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(intTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
intTest = &IntTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(intTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "IntTest.Val2", "Val2", "ltefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(int(5), int(1), "ltefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(int(1), int(5), "ltefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltefield")
|
|||
|
|
|||
|
type UIntTest struct {
|
|||
|
Val1 uint `validate:"required"`
|
|||
|
Val2 uint `validate:"required,ltefield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
uIntTest := &UIntTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(uIntTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
uIntTest = &UIntTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(uIntTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "UIntTest.Val2", "Val2", "ltefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(uint(5), uint(1), "ltefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(uint(1), uint(5), "ltefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltefield")
|
|||
|
|
|||
|
type FloatTest struct {
|
|||
|
Val1 float64 `validate:"required"`
|
|||
|
Val2 float64 `validate:"required,ltefield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
floatTest := &FloatTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(floatTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
floatTest = &FloatTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(floatTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "FloatTest.Val2", "Val2", "ltefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(float32(5), float32(1), "ltefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(float32(1), float32(5), "ltefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(nil, 5, "ltefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(1, "T", "ltefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(1, end, "ltefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "ltefield")
|
|||
|
|
|||
|
type TimeTest2 struct {
|
|||
|
Start *time.Time `validate:"required"`
|
|||
|
End *time.Time `validate:"required,ltefield=NonExistantField"`
|
|||
|
}
|
|||
|
|
|||
|
timeTest2 := &TimeTest2{
|
|||
|
Start: &end,
|
|||
|
End: &start,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(timeTest2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TimeTest2.End", "End", "ltefield")
|
|||
|
}
|
|||
|
|
|||
|
func TestGteField(t *testing.T) {
|
|||
|
|
|||
|
type TimeTest struct {
|
|||
|
Start *time.Time `validate:"required,gte"`
|
|||
|
End *time.Time `validate:"required,gte,gtefield=Start"`
|
|||
|
}
|
|||
|
|
|||
|
now := time.Now()
|
|||
|
start := now.Add(time.Hour * 24)
|
|||
|
end := start.Add(time.Hour * 24)
|
|||
|
|
|||
|
timeTest := &TimeTest{
|
|||
|
Start: &start,
|
|||
|
End: &end,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(timeTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
timeTest = &TimeTest{
|
|||
|
Start: &end,
|
|||
|
End: &start,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(timeTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TimeTest.End", "End", "gtefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(&start, &end, "gtefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(&end, &start, "gtefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(timeTest, &start, "gtefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue("test", "test", "gtefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue("test", "test bigger", "gtefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
type IntTest struct {
|
|||
|
Val1 int `validate:"required"`
|
|||
|
Val2 int `validate:"required,gtefield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
intTest := &IntTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(intTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
intTest = &IntTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(intTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "IntTest.Val2", "Val2", "gtefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(int(1), int(5), "gtefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(int(5), int(1), "gtefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtefield")
|
|||
|
|
|||
|
type UIntTest struct {
|
|||
|
Val1 uint `validate:"required"`
|
|||
|
Val2 uint `validate:"required,gtefield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
uIntTest := &UIntTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(uIntTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
uIntTest = &UIntTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(uIntTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "UIntTest.Val2", "Val2", "gtefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(uint(1), uint(5), "gtefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(uint(5), uint(1), "gtefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtefield")
|
|||
|
|
|||
|
type FloatTest struct {
|
|||
|
Val1 float64 `validate:"required"`
|
|||
|
Val2 float64 `validate:"required,gtefield=Val1"`
|
|||
|
}
|
|||
|
|
|||
|
floatTest := &FloatTest{
|
|||
|
Val1: 1,
|
|||
|
Val2: 5,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(floatTest)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
floatTest = &FloatTest{
|
|||
|
Val1: 5,
|
|||
|
Val2: 1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(floatTest)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "FloatTest.Val2", "Val2", "gtefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(float32(1), float32(5), "gtefield")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(float32(5), float32(1), "gtefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(nil, 1, "gtefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(5, "T", "gtefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtefield")
|
|||
|
|
|||
|
errs = validate.FieldWithValue(5, start, "gtefield")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gtefield")
|
|||
|
|
|||
|
type TimeTest2 struct {
|
|||
|
Start *time.Time `validate:"required"`
|
|||
|
End *time.Time `validate:"required,gtefield=NonExistantField"`
|
|||
|
}
|
|||
|
|
|||
|
timeTest2 := &TimeTest2{
|
|||
|
Start: &start,
|
|||
|
End: &end,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(timeTest2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TimeTest2.End", "End", "gtefield")
|
|||
|
}
|
|||
|
|
|||
|
func TestValidateByTagAndValue(t *testing.T) {
|
|||
|
|
|||
|
val := "test"
|
|||
|
field := "test"
|
|||
|
errs := validate.FieldWithValue(val, field, "required")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
fn := func(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
|||
|
|
|||
|
return current.String() == field.String()
|
|||
|
}
|
|||
|
|
|||
|
validate.RegisterValidation("isequaltestfunc", fn)
|
|||
|
|
|||
|
errs = validate.FieldWithValue(val, field, "isequaltestfunc")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
val = "unequal"
|
|||
|
|
|||
|
errs = validate.FieldWithValue(val, field, "isequaltestfunc")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "isequaltestfunc")
|
|||
|
}
|
|||
|
|
|||
|
func TestAddFunctions(t *testing.T) {
|
|||
|
|
|||
|
fn := func(v *Validate, topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
|
|||
|
|
|||
|
return true
|
|||
|
}
|
|||
|
|
|||
|
config := &Config{
|
|||
|
TagName: "validateme",
|
|||
|
}
|
|||
|
|
|||
|
validate := New(config)
|
|||
|
|
|||
|
errs := validate.RegisterValidation("new", fn)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.RegisterValidation("", fn)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
|
|||
|
validate.RegisterValidation("new", nil)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
|
|||
|
errs = validate.RegisterValidation("new", fn)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.RegisterValidation("dive", fn) }, "Tag 'dive' either contains restricted characters or is the same as a restricted tag needed for normal operation")
|
|||
|
}
|
|||
|
|
|||
|
func TestChangeTag(t *testing.T) {
|
|||
|
|
|||
|
config := &Config{
|
|||
|
TagName: "val",
|
|||
|
}
|
|||
|
validate := New(config)
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Name string `val:"len=4"`
|
|||
|
}
|
|||
|
s := &Test{
|
|||
|
Name: "TEST",
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(s)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestUnexposedStruct(t *testing.T) {
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Name string
|
|||
|
unexposed struct {
|
|||
|
A string `validate:"required"`
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
s := &Test{
|
|||
|
Name: "TEST",
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(s)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestBadParams(t *testing.T) {
|
|||
|
|
|||
|
i := 1
|
|||
|
errs := validate.Field(i, "-")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.Field(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
|
|||
|
PanicMatches(t, func() { validate.Field(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
|
|||
|
|
|||
|
var ui uint = 1
|
|||
|
PanicMatches(t, func() { validate.Field(ui, "len=a") }, "strconv.ParseUint: parsing \"a\": invalid syntax")
|
|||
|
|
|||
|
f := 1.23
|
|||
|
PanicMatches(t, func() { validate.Field(f, "len=a") }, "strconv.ParseFloat: parsing \"a\": invalid syntax")
|
|||
|
}
|
|||
|
|
|||
|
func TestLength(t *testing.T) {
|
|||
|
|
|||
|
i := true
|
|||
|
PanicMatches(t, func() { validate.Field(i, "len") }, "Bad field type bool")
|
|||
|
}
|
|||
|
|
|||
|
func TestIsGt(t *testing.T) {
|
|||
|
|
|||
|
myMap := map[string]string{}
|
|||
|
errs := validate.Field(myMap, "gt=0")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
|
|||
|
f := 1.23
|
|||
|
errs = validate.Field(f, "gt=5")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gt")
|
|||
|
|
|||
|
var ui uint = 5
|
|||
|
errs = validate.Field(ui, "gt=10")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gt")
|
|||
|
|
|||
|
i := true
|
|||
|
PanicMatches(t, func() { validate.Field(i, "gt") }, "Bad field type bool")
|
|||
|
|
|||
|
tm := time.Now().UTC()
|
|||
|
tm = tm.Add(time.Hour * 24)
|
|||
|
|
|||
|
errs = validate.Field(tm, "gt")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
t2 := time.Now().UTC().Add(-time.Hour)
|
|||
|
|
|||
|
errs = validate.Field(t2, "gt")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gt")
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Now *time.Time `validate:"gt"`
|
|||
|
}
|
|||
|
s := &Test{
|
|||
|
Now: &tm,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = &Test{
|
|||
|
Now: &t2,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.Now", "Now", "gt")
|
|||
|
}
|
|||
|
|
|||
|
func TestIsGte(t *testing.T) {
|
|||
|
|
|||
|
i := true
|
|||
|
PanicMatches(t, func() { validate.Field(i, "gte") }, "Bad field type bool")
|
|||
|
|
|||
|
t1 := time.Now().UTC()
|
|||
|
t1 = t1.Add(time.Hour * 24)
|
|||
|
|
|||
|
errs := validate.Field(t1, "gte")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
t2 := time.Now().UTC().Add(-time.Hour)
|
|||
|
|
|||
|
errs = validate.Field(t2, "gte")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "gte")
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Now *time.Time `validate:"gte"`
|
|||
|
}
|
|||
|
s := &Test{
|
|||
|
Now: &t1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = &Test{
|
|||
|
Now: &t2,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.Now", "Now", "gte")
|
|||
|
}
|
|||
|
|
|||
|
func TestIsLt(t *testing.T) {
|
|||
|
|
|||
|
myMap := map[string]string{}
|
|||
|
errs := validate.Field(myMap, "lt=0")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "lt")
|
|||
|
|
|||
|
f := 1.23
|
|||
|
errs = validate.Field(f, "lt=0")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "lt")
|
|||
|
|
|||
|
var ui uint = 5
|
|||
|
errs = validate.Field(ui, "lt=0")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "lt")
|
|||
|
|
|||
|
i := true
|
|||
|
PanicMatches(t, func() { validate.Field(i, "lt") }, "Bad field type bool")
|
|||
|
|
|||
|
t1 := time.Now().UTC().Add(-time.Hour)
|
|||
|
|
|||
|
errs = validate.Field(t1, "lt")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
t2 := time.Now().UTC()
|
|||
|
t2 = t2.Add(time.Hour * 24)
|
|||
|
|
|||
|
errs = validate.Field(t2, "lt")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "lt")
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Now *time.Time `validate:"lt"`
|
|||
|
}
|
|||
|
|
|||
|
s := &Test{
|
|||
|
Now: &t1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = &Test{
|
|||
|
Now: &t2,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.Now", "Now", "lt")
|
|||
|
}
|
|||
|
|
|||
|
func TestIsLte(t *testing.T) {
|
|||
|
|
|||
|
i := true
|
|||
|
PanicMatches(t, func() { validate.Field(i, "lte") }, "Bad field type bool")
|
|||
|
|
|||
|
t1 := time.Now().UTC().Add(-time.Hour)
|
|||
|
|
|||
|
errs := validate.Field(t1, "lte")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
t2 := time.Now().UTC()
|
|||
|
t2 = t2.Add(time.Hour * 24)
|
|||
|
|
|||
|
errs = validate.Field(t2, "lte")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "lte")
|
|||
|
|
|||
|
type Test struct {
|
|||
|
Now *time.Time `validate:"lte"`
|
|||
|
}
|
|||
|
|
|||
|
s := &Test{
|
|||
|
Now: &t1,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = &Test{
|
|||
|
Now: &t2,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(s)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
}
|
|||
|
|
|||
|
func TestUrl(t *testing.T) {
|
|||
|
|
|||
|
var tests = []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"http://foo.bar#com", true},
|
|||
|
{"http://foobar.com", true},
|
|||
|
{"https://foobar.com", true},
|
|||
|
{"foobar.com", false},
|
|||
|
{"http://foobar.coffee/", true},
|
|||
|
{"http://foobar.中文网/", true},
|
|||
|
{"http://foobar.org/", true},
|
|||
|
{"http://foobar.org:8080/", true},
|
|||
|
{"ftp://foobar.ru/", true},
|
|||
|
{"http://user:pass@www.foobar.com/", true},
|
|||
|
{"http://127.0.0.1/", true},
|
|||
|
{"http://duckduckgo.com/?q=%2F", true},
|
|||
|
{"http://localhost:3000/", true},
|
|||
|
{"http://foobar.com/?foo=bar#baz=qux", true},
|
|||
|
{"http://foobar.com?foo=bar", true},
|
|||
|
{"http://www.xn--froschgrn-x9a.net/", true},
|
|||
|
{"", false},
|
|||
|
{"xyz://foobar.com", true},
|
|||
|
{"invalid.", false},
|
|||
|
{".com", false},
|
|||
|
{"rtmp://foobar.com", true},
|
|||
|
{"http://www.foo_bar.com/", true},
|
|||
|
{"http://localhost:3000/", true},
|
|||
|
{"http://foobar.com/#baz", true},
|
|||
|
{"http://foobar.com#baz=qux", true},
|
|||
|
{"http://foobar.com/t$-_.+!*\\'(),", true},
|
|||
|
{"http://www.foobar.com/~foobar", true},
|
|||
|
{"http://www.-foobar.com/", true},
|
|||
|
{"http://www.foo---bar.com/", true},
|
|||
|
{"mailto:someone@example.com", true},
|
|||
|
{"irc://irc.server.org/channel", true},
|
|||
|
{"irc://#channel@network", true},
|
|||
|
{"/abs/test/dir", false},
|
|||
|
{"./rel/test/dir", false},
|
|||
|
}
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "url")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d URL failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d URL failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "url" {
|
|||
|
t.Fatalf("Index: %d URL failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
i := 1
|
|||
|
PanicMatches(t, func() { validate.Field(i, "url") }, "Bad field type int")
|
|||
|
}
|
|||
|
|
|||
|
func TestUri(t *testing.T) {
|
|||
|
|
|||
|
var tests = []struct {
|
|||
|
param string
|
|||
|
expected bool
|
|||
|
}{
|
|||
|
{"http://foo.bar#com", true},
|
|||
|
{"http://foobar.com", true},
|
|||
|
{"https://foobar.com", true},
|
|||
|
{"foobar.com", false},
|
|||
|
{"http://foobar.coffee/", true},
|
|||
|
{"http://foobar.中文网/", true},
|
|||
|
{"http://foobar.org/", true},
|
|||
|
{"http://foobar.org:8080/", true},
|
|||
|
{"ftp://foobar.ru/", true},
|
|||
|
{"http://user:pass@www.foobar.com/", true},
|
|||
|
{"http://127.0.0.1/", true},
|
|||
|
{"http://duckduckgo.com/?q=%2F", true},
|
|||
|
{"http://localhost:3000/", true},
|
|||
|
{"http://foobar.com/?foo=bar#baz=qux", true},
|
|||
|
{"http://foobar.com?foo=bar", true},
|
|||
|
{"http://www.xn--froschgrn-x9a.net/", true},
|
|||
|
{"", false},
|
|||
|
{"xyz://foobar.com", true},
|
|||
|
{"invalid.", false},
|
|||
|
{".com", false},
|
|||
|
{"rtmp://foobar.com", true},
|
|||
|
{"http://www.foo_bar.com/", true},
|
|||
|
{"http://localhost:3000/", true},
|
|||
|
{"http://foobar.com#baz=qux", true},
|
|||
|
{"http://foobar.com/t$-_.+!*\\'(),", true},
|
|||
|
{"http://www.foobar.com/~foobar", true},
|
|||
|
{"http://www.-foobar.com/", true},
|
|||
|
{"http://www.foo---bar.com/", true},
|
|||
|
{"mailto:someone@example.com", true},
|
|||
|
{"irc://irc.server.org/channel", true},
|
|||
|
{"irc://#channel@network", true},
|
|||
|
{"/abs/test/dir", true},
|
|||
|
{"./rel/test/dir", false},
|
|||
|
}
|
|||
|
for i, test := range tests {
|
|||
|
|
|||
|
errs := validate.Field(test.param, "uri")
|
|||
|
|
|||
|
if test.expected {
|
|||
|
if !IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d URI failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
} else {
|
|||
|
if IsEqual(errs, nil) {
|
|||
|
t.Fatalf("Index: %d URI failed Error: %s", i, errs)
|
|||
|
} else {
|
|||
|
val := errs.(ValidationErrors)[""]
|
|||
|
if val.Tag != "uri" {
|
|||
|
t.Fatalf("Index: %d URI failed Error: %s", i, errs)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
i := 1
|
|||
|
PanicMatches(t, func() { validate.Field(i, "uri") }, "Bad field type int")
|
|||
|
}
|
|||
|
|
|||
|
func TestOrTag(t *testing.T) {
|
|||
|
s := "rgba(0,31,255,0.5)"
|
|||
|
errs := validate.Field(s, "rgb|rgba")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "rgba(0,31,255,0.5)"
|
|||
|
errs = validate.Field(s, "rgb|rgba|len=18")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "this ain't right"
|
|||
|
errs = validate.Field(s, "rgb|rgba")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgb|rgba")
|
|||
|
|
|||
|
s = "this ain't right"
|
|||
|
errs = validate.Field(s, "rgb|rgba|len=10")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgb|rgba|len")
|
|||
|
|
|||
|
s = "this is right"
|
|||
|
errs = validate.Field(s, "rgb|rgba|len=13")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = ""
|
|||
|
errs = validate.Field(s, "omitempty,rgb|rgba")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "this is right, but a blank or isn't"
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.Field(s, "rgb||len=13") }, "Invalid validation tag on field")
|
|||
|
PanicMatches(t, func() { validate.Field(s, "rgb|rgbaa|len=13") }, "Undefined validation function on field")
|
|||
|
}
|
|||
|
|
|||
|
func TestHsla(t *testing.T) {
|
|||
|
|
|||
|
s := "hsla(360,100%,100%,1)"
|
|||
|
errs := validate.Field(s, "hsla")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "hsla(360,100%,100%,0.5)"
|
|||
|
errs = validate.Field(s, "hsla")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "hsla(0,0%,0%, 0)"
|
|||
|
errs = validate.Field(s, "hsla")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "hsl(361,100%,50%,1)"
|
|||
|
errs = validate.Field(s, "hsla")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hsla")
|
|||
|
|
|||
|
s = "hsl(361,100%,50%)"
|
|||
|
errs = validate.Field(s, "hsla")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hsla")
|
|||
|
|
|||
|
s = "hsla(361,100%,50%)"
|
|||
|
errs = validate.Field(s, "hsla")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hsla")
|
|||
|
|
|||
|
s = "hsla(360,101%,50%)"
|
|||
|
errs = validate.Field(s, "hsla")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hsla")
|
|||
|
|
|||
|
s = "hsla(360,100%,101%)"
|
|||
|
errs = validate.Field(s, "hsla")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hsla")
|
|||
|
|
|||
|
i := 1
|
|||
|
validate.Field(i, "hsla")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hsla")
|
|||
|
}
|
|||
|
|
|||
|
func TestHsl(t *testing.T) {
|
|||
|
|
|||
|
s := "hsl(360,100%,50%)"
|
|||
|
errs := validate.Field(s, "hsl")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "hsl(0,0%,0%)"
|
|||
|
errs = validate.Field(s, "hsl")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "hsl(361,100%,50%)"
|
|||
|
errs = validate.Field(s, "hsl")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hsl")
|
|||
|
|
|||
|
s = "hsl(361,101%,50%)"
|
|||
|
errs = validate.Field(s, "hsl")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hsl")
|
|||
|
|
|||
|
s = "hsl(361,100%,101%)"
|
|||
|
errs = validate.Field(s, "hsl")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hsl")
|
|||
|
|
|||
|
s = "hsl(-10,100%,100%)"
|
|||
|
errs = validate.Field(s, "hsl")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hsl")
|
|||
|
|
|||
|
i := 1
|
|||
|
errs = validate.Field(i, "hsl")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hsl")
|
|||
|
}
|
|||
|
|
|||
|
func TestRgba(t *testing.T) {
|
|||
|
|
|||
|
s := "rgba(0,31,255,0.5)"
|
|||
|
errs := validate.Field(s, "rgba")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "rgba(0,31,255,0.12)"
|
|||
|
errs = validate.Field(s, "rgba")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "rgba(12%,55%,100%,0.12)"
|
|||
|
errs = validate.Field(s, "rgba")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "rgba( 0, 31, 255, 0.5)"
|
|||
|
errs = validate.Field(s, "rgba")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "rgba(12%,55,100%,0.12)"
|
|||
|
errs = validate.Field(s, "rgba")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgba")
|
|||
|
|
|||
|
s = "rgb(0, 31, 255)"
|
|||
|
errs = validate.Field(s, "rgba")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgba")
|
|||
|
|
|||
|
s = "rgb(1,349,275,0.5)"
|
|||
|
errs = validate.Field(s, "rgba")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgba")
|
|||
|
|
|||
|
s = "rgb(01,31,255,0.5)"
|
|||
|
errs = validate.Field(s, "rgba")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgba")
|
|||
|
|
|||
|
i := 1
|
|||
|
errs = validate.Field(i, "rgba")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgba")
|
|||
|
}
|
|||
|
|
|||
|
func TestRgb(t *testing.T) {
|
|||
|
|
|||
|
s := "rgb(0,31,255)"
|
|||
|
errs := validate.Field(s, "rgb")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "rgb(0, 31, 255)"
|
|||
|
errs = validate.Field(s, "rgb")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "rgb(10%, 50%, 100%)"
|
|||
|
errs = validate.Field(s, "rgb")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "rgb(10%, 50%, 55)"
|
|||
|
errs = validate.Field(s, "rgb")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgb")
|
|||
|
|
|||
|
s = "rgb(1,349,275)"
|
|||
|
errs = validate.Field(s, "rgb")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgb")
|
|||
|
|
|||
|
s = "rgb(01,31,255)"
|
|||
|
errs = validate.Field(s, "rgb")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgb")
|
|||
|
|
|||
|
s = "rgba(0,31,255)"
|
|||
|
errs = validate.Field(s, "rgb")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgb")
|
|||
|
|
|||
|
i := 1
|
|||
|
errs = validate.Field(i, "rgb")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "rgb")
|
|||
|
}
|
|||
|
|
|||
|
func TestEmail(t *testing.T) {
|
|||
|
|
|||
|
s := "test@mail.com"
|
|||
|
errs := validate.Field(s, "email")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "Dörte@Sörensen.example.com"
|
|||
|
errs = validate.Field(s, "email")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "θσερ@εχαμπλε.ψομ"
|
|||
|
errs = validate.Field(s, "email")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "юзер@екзампл.ком"
|
|||
|
errs = validate.Field(s, "email")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "उपयोगकर्ता@उदाहरण.कॉम"
|
|||
|
errs = validate.Field(s, "email")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "用户@例子.广告"
|
|||
|
errs = validate.Field(s, "email")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = ""
|
|||
|
errs = validate.Field(s, "email")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "email")
|
|||
|
|
|||
|
s = "test@email"
|
|||
|
errs = validate.Field(s, "email")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "email")
|
|||
|
|
|||
|
s = "test@email."
|
|||
|
errs = validate.Field(s, "email")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "email")
|
|||
|
|
|||
|
s = "@email.com"
|
|||
|
errs = validate.Field(s, "email")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "email")
|
|||
|
|
|||
|
i := true
|
|||
|
errs = validate.Field(i, "email")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "email")
|
|||
|
}
|
|||
|
|
|||
|
func TestHexColor(t *testing.T) {
|
|||
|
|
|||
|
s := "#fff"
|
|||
|
errs := validate.Field(s, "hexcolor")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "#c2c2c2"
|
|||
|
errs = validate.Field(s, "hexcolor")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "fff"
|
|||
|
errs = validate.Field(s, "hexcolor")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hexcolor")
|
|||
|
|
|||
|
s = "fffFF"
|
|||
|
errs = validate.Field(s, "hexcolor")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hexcolor")
|
|||
|
|
|||
|
i := true
|
|||
|
errs = validate.Field(i, "hexcolor")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hexcolor")
|
|||
|
}
|
|||
|
|
|||
|
func TestHexadecimal(t *testing.T) {
|
|||
|
|
|||
|
s := "ff0044"
|
|||
|
errs := validate.Field(s, "hexadecimal")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "abcdefg"
|
|||
|
errs = validate.Field(s, "hexadecimal")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hexadecimal")
|
|||
|
|
|||
|
i := true
|
|||
|
errs = validate.Field(i, "hexadecimal")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "hexadecimal")
|
|||
|
}
|
|||
|
|
|||
|
func TestNumber(t *testing.T) {
|
|||
|
|
|||
|
s := "1"
|
|||
|
errs := validate.Field(s, "number")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "+1"
|
|||
|
errs = validate.Field(s, "number")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "number")
|
|||
|
|
|||
|
s = "-1"
|
|||
|
errs = validate.Field(s, "number")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "number")
|
|||
|
|
|||
|
s = "1.12"
|
|||
|
errs = validate.Field(s, "number")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "number")
|
|||
|
|
|||
|
s = "+1.12"
|
|||
|
errs = validate.Field(s, "number")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "number")
|
|||
|
|
|||
|
s = "-1.12"
|
|||
|
errs = validate.Field(s, "number")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "number")
|
|||
|
|
|||
|
s = "1."
|
|||
|
errs = validate.Field(s, "number")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "number")
|
|||
|
|
|||
|
s = "1.o"
|
|||
|
errs = validate.Field(s, "number")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "number")
|
|||
|
|
|||
|
i := 1
|
|||
|
errs = validate.Field(i, "number")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "number")
|
|||
|
}
|
|||
|
|
|||
|
func TestNumeric(t *testing.T) {
|
|||
|
|
|||
|
s := "1"
|
|||
|
errs := validate.Field(s, "numeric")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "+1"
|
|||
|
errs = validate.Field(s, "numeric")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "-1"
|
|||
|
errs = validate.Field(s, "numeric")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "1.12"
|
|||
|
errs = validate.Field(s, "numeric")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "+1.12"
|
|||
|
errs = validate.Field(s, "numeric")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "-1.12"
|
|||
|
errs = validate.Field(s, "numeric")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "1."
|
|||
|
errs = validate.Field(s, "numeric")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "numeric")
|
|||
|
|
|||
|
s = "1.o"
|
|||
|
errs = validate.Field(s, "numeric")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "numeric")
|
|||
|
|
|||
|
i := 1
|
|||
|
errs = validate.Field(i, "numeric")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "numeric")
|
|||
|
}
|
|||
|
|
|||
|
func TestAlphaNumeric(t *testing.T) {
|
|||
|
|
|||
|
s := "abcd123"
|
|||
|
errs := validate.Field(s, "alphanum")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "abc!23"
|
|||
|
errs = validate.Field(s, "alphanum")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "alphanum")
|
|||
|
|
|||
|
errs = validate.Field(1, "alphanum")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "alphanum")
|
|||
|
}
|
|||
|
|
|||
|
func TestAlpha(t *testing.T) {
|
|||
|
|
|||
|
s := "abcd"
|
|||
|
errs := validate.Field(s, "alpha")
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
s = "abc®"
|
|||
|
errs = validate.Field(s, "alpha")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "alpha")
|
|||
|
|
|||
|
s = "abc÷"
|
|||
|
errs = validate.Field(s, "alpha")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "alpha")
|
|||
|
|
|||
|
s = "abc1"
|
|||
|
errs = validate.Field(s, "alpha")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "alpha")
|
|||
|
|
|||
|
errs = validate.Field(1, "alpha")
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "", "", "alpha")
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
func TestStructStringValidation(t *testing.T) {
|
|||
|
|
|||
|
tSuccess := &TestString{
|
|||
|
Required: "Required",
|
|||
|
Len: "length==10",
|
|||
|
Min: "min=1",
|
|||
|
Max: "1234567890",
|
|||
|
MinMax: "12345",
|
|||
|
Lt: "012345678",
|
|||
|
Lte: "0123456789",
|
|||
|
Gt: "01234567890",
|
|||
|
Gte: "0123456789",
|
|||
|
OmitEmpty: "",
|
|||
|
Sub: &SubTest{
|
|||
|
Test: "1",
|
|||
|
},
|
|||
|
SubIgnore: &SubTest{
|
|||
|
Test: "",
|
|||
|
},
|
|||
|
Anonymous: struct {
|
|||
|
A string `validate:"required"`
|
|||
|
}{
|
|||
|
A: "1",
|
|||
|
},
|
|||
|
Iface: &Impl{
|
|||
|
F: "123",
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(tSuccess)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
tFail := &TestString{
|
|||
|
Required: "",
|
|||
|
Len: "",
|
|||
|
Min: "",
|
|||
|
Max: "12345678901",
|
|||
|
MinMax: "",
|
|||
|
Lt: "0123456789",
|
|||
|
Lte: "01234567890",
|
|||
|
Gt: "1",
|
|||
|
Gte: "1",
|
|||
|
OmitEmpty: "12345678901",
|
|||
|
Sub: &SubTest{
|
|||
|
Test: "",
|
|||
|
},
|
|||
|
Anonymous: struct {
|
|||
|
A string `validate:"required"`
|
|||
|
}{
|
|||
|
A: "",
|
|||
|
},
|
|||
|
Iface: &Impl{
|
|||
|
F: "12",
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tFail)
|
|||
|
|
|||
|
// Assert Top Level
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 13)
|
|||
|
|
|||
|
// Assert Fields
|
|||
|
AssertError(t, errs, "TestString.Required", "Required", "required")
|
|||
|
AssertError(t, errs, "TestString.Len", "Len", "len")
|
|||
|
AssertError(t, errs, "TestString.Min", "Min", "min")
|
|||
|
AssertError(t, errs, "TestString.Max", "Max", "max")
|
|||
|
AssertError(t, errs, "TestString.MinMax", "MinMax", "min")
|
|||
|
AssertError(t, errs, "TestString.Lt", "Lt", "lt")
|
|||
|
AssertError(t, errs, "TestString.Lte", "Lte", "lte")
|
|||
|
AssertError(t, errs, "TestString.Gt", "Gt", "gt")
|
|||
|
AssertError(t, errs, "TestString.Gte", "Gte", "gte")
|
|||
|
AssertError(t, errs, "TestString.OmitEmpty", "OmitEmpty", "max")
|
|||
|
|
|||
|
// Nested Struct Field Errs
|
|||
|
AssertError(t, errs, "TestString.Anonymous.A", "A", "required")
|
|||
|
AssertError(t, errs, "TestString.Sub.Test", "Test", "required")
|
|||
|
AssertError(t, errs, "TestString.Iface.F", "F", "len")
|
|||
|
}
|
|||
|
|
|||
|
func TestStructInt32Validation(t *testing.T) {
|
|||
|
|
|||
|
tSuccess := &TestInt32{
|
|||
|
Required: 1,
|
|||
|
Len: 10,
|
|||
|
Min: 1,
|
|||
|
Max: 10,
|
|||
|
MinMax: 5,
|
|||
|
Lt: 9,
|
|||
|
Lte: 10,
|
|||
|
Gt: 11,
|
|||
|
Gte: 10,
|
|||
|
OmitEmpty: 0,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(tSuccess)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
tFail := &TestInt32{
|
|||
|
Required: 0,
|
|||
|
Len: 11,
|
|||
|
Min: -1,
|
|||
|
Max: 11,
|
|||
|
MinMax: -1,
|
|||
|
Lt: 10,
|
|||
|
Lte: 11,
|
|||
|
Gt: 10,
|
|||
|
Gte: 9,
|
|||
|
OmitEmpty: 11,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tFail)
|
|||
|
|
|||
|
// Assert Top Level
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 10)
|
|||
|
|
|||
|
// Assert Fields
|
|||
|
AssertError(t, errs, "TestInt32.Required", "Required", "required")
|
|||
|
AssertError(t, errs, "TestInt32.Len", "Len", "len")
|
|||
|
AssertError(t, errs, "TestInt32.Min", "Min", "min")
|
|||
|
AssertError(t, errs, "TestInt32.Max", "Max", "max")
|
|||
|
AssertError(t, errs, "TestInt32.MinMax", "MinMax", "min")
|
|||
|
AssertError(t, errs, "TestInt32.Lt", "Lt", "lt")
|
|||
|
AssertError(t, errs, "TestInt32.Lte", "Lte", "lte")
|
|||
|
AssertError(t, errs, "TestInt32.Gt", "Gt", "gt")
|
|||
|
AssertError(t, errs, "TestInt32.Gte", "Gte", "gte")
|
|||
|
AssertError(t, errs, "TestInt32.OmitEmpty", "OmitEmpty", "max")
|
|||
|
}
|
|||
|
|
|||
|
func TestStructUint64Validation(t *testing.T) {
|
|||
|
|
|||
|
tSuccess := &TestUint64{
|
|||
|
Required: 1,
|
|||
|
Len: 10,
|
|||
|
Min: 1,
|
|||
|
Max: 10,
|
|||
|
MinMax: 5,
|
|||
|
OmitEmpty: 0,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(tSuccess)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
tFail := &TestUint64{
|
|||
|
Required: 0,
|
|||
|
Len: 11,
|
|||
|
Min: 0,
|
|||
|
Max: 11,
|
|||
|
MinMax: 0,
|
|||
|
OmitEmpty: 11,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tFail)
|
|||
|
|
|||
|
// Assert Top Level
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 6)
|
|||
|
|
|||
|
// Assert Fields
|
|||
|
AssertError(t, errs, "TestUint64.Required", "Required", "required")
|
|||
|
AssertError(t, errs, "TestUint64.Len", "Len", "len")
|
|||
|
AssertError(t, errs, "TestUint64.Min", "Min", "min")
|
|||
|
AssertError(t, errs, "TestUint64.Max", "Max", "max")
|
|||
|
AssertError(t, errs, "TestUint64.MinMax", "MinMax", "min")
|
|||
|
AssertError(t, errs, "TestUint64.OmitEmpty", "OmitEmpty", "max")
|
|||
|
}
|
|||
|
|
|||
|
func TestStructFloat64Validation(t *testing.T) {
|
|||
|
|
|||
|
tSuccess := &TestFloat64{
|
|||
|
Required: 1,
|
|||
|
Len: 10,
|
|||
|
Min: 1,
|
|||
|
Max: 10,
|
|||
|
MinMax: 5,
|
|||
|
OmitEmpty: 0,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(tSuccess)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
tFail := &TestFloat64{
|
|||
|
Required: 0,
|
|||
|
Len: 11,
|
|||
|
Min: 0,
|
|||
|
Max: 11,
|
|||
|
MinMax: 0,
|
|||
|
OmitEmpty: 11,
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tFail)
|
|||
|
|
|||
|
// Assert Top Level
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 6)
|
|||
|
|
|||
|
// Assert Fields
|
|||
|
AssertError(t, errs, "TestFloat64.Required", "Required", "required")
|
|||
|
AssertError(t, errs, "TestFloat64.Len", "Len", "len")
|
|||
|
AssertError(t, errs, "TestFloat64.Min", "Min", "min")
|
|||
|
AssertError(t, errs, "TestFloat64.Max", "Max", "max")
|
|||
|
AssertError(t, errs, "TestFloat64.MinMax", "MinMax", "min")
|
|||
|
AssertError(t, errs, "TestFloat64.OmitEmpty", "OmitEmpty", "max")
|
|||
|
}
|
|||
|
|
|||
|
func TestStructSliceValidation(t *testing.T) {
|
|||
|
|
|||
|
tSuccess := &TestSlice{
|
|||
|
Required: []int{1},
|
|||
|
Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
|
|||
|
Min: []int{1, 2},
|
|||
|
Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
|
|||
|
MinMax: []int{1, 2, 3, 4, 5},
|
|||
|
OmitEmpty: nil,
|
|||
|
}
|
|||
|
|
|||
|
errs := validate.Struct(tSuccess)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
tFail := &TestSlice{
|
|||
|
Required: nil,
|
|||
|
Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
|
|||
|
Min: []int{},
|
|||
|
Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
|
|||
|
MinMax: []int{},
|
|||
|
OmitEmpty: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
|
|||
|
}
|
|||
|
|
|||
|
errs = validate.Struct(tFail)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs.(ValidationErrors)), 6)
|
|||
|
|
|||
|
// Assert Field Errors
|
|||
|
AssertError(t, errs, "TestSlice.Required", "Required", "required")
|
|||
|
AssertError(t, errs, "TestSlice.Len", "Len", "len")
|
|||
|
AssertError(t, errs, "TestSlice.Min", "Min", "min")
|
|||
|
AssertError(t, errs, "TestSlice.Max", "Max", "max")
|
|||
|
AssertError(t, errs, "TestSlice.MinMax", "MinMax", "min")
|
|||
|
AssertError(t, errs, "TestSlice.OmitEmpty", "OmitEmpty", "max")
|
|||
|
}
|
|||
|
|
|||
|
func TestInvalidStruct(t *testing.T) {
|
|||
|
s := &SubTest{
|
|||
|
Test: "1",
|
|||
|
}
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.Struct(s.Test) }, "value passed for validation is not a struct")
|
|||
|
}
|
|||
|
|
|||
|
func TestInvalidValidatorFunction(t *testing.T) {
|
|||
|
s := &SubTest{
|
|||
|
Test: "1",
|
|||
|
}
|
|||
|
|
|||
|
PanicMatches(t, func() { validate.Field(s.Test, "zzxxBadFunction") }, "Undefined validation function on field")
|
|||
|
}
|
|||
|
|
|||
|
func TestCustomFieldName(t *testing.T) {
|
|||
|
type A struct {
|
|||
|
B string `schema:"b" validate:"required"`
|
|||
|
C string `schema:"c" validate:"required"`
|
|||
|
D []bool `schema:"d" validate:"required"`
|
|||
|
E string `schema:"-" validate:"required"`
|
|||
|
}
|
|||
|
|
|||
|
a := &A{}
|
|||
|
|
|||
|
errs := New(&Config{TagName: "validate", FieldNameTag: "schema"}).Struct(a).(ValidationErrors)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs), 4)
|
|||
|
Equal(t, errs["A.B"].Name, "b")
|
|||
|
Equal(t, errs["A.C"].Name, "c")
|
|||
|
Equal(t, errs["A.D"].Name, "d")
|
|||
|
Equal(t, errs["A.E"].Name, "E")
|
|||
|
|
|||
|
errs = New(&Config{TagName: "validate"}).Struct(a).(ValidationErrors)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
Equal(t, len(errs), 4)
|
|||
|
Equal(t, errs["A.B"].Name, "B")
|
|||
|
Equal(t, errs["A.C"].Name, "C")
|
|||
|
Equal(t, errs["A.D"].Name, "D")
|
|||
|
Equal(t, errs["A.E"].Name, "E")
|
|||
|
}
|
|||
|
|
|||
|
func TestMutipleRecursiveExtractStructCache(t *testing.T) {
|
|||
|
|
|||
|
type Recursive struct {
|
|||
|
Field *string `validate:"exists,required,len=5,ne=string"`
|
|||
|
}
|
|||
|
|
|||
|
var test Recursive
|
|||
|
|
|||
|
current := reflect.ValueOf(test)
|
|||
|
name := "Recursive"
|
|||
|
proceed := make(chan struct{})
|
|||
|
|
|||
|
sc := validate.extractStructCache(current, name)
|
|||
|
ptr := fmt.Sprintf("%p", sc)
|
|||
|
|
|||
|
for i := 0; i < 100; i++ {
|
|||
|
|
|||
|
go func() {
|
|||
|
<-proceed
|
|||
|
sc := validate.extractStructCache(current, name)
|
|||
|
Equal(t, ptr, fmt.Sprintf("%p", sc))
|
|||
|
}()
|
|||
|
}
|
|||
|
|
|||
|
close(proceed)
|
|||
|
}
|
|||
|
|
|||
|
// Thanks @robbrockbank, see https://github.com/go-playground/validator/issues/249
|
|||
|
func TestPointerAndOmitEmpty(t *testing.T) {
|
|||
|
|
|||
|
type Test struct {
|
|||
|
MyInt *int `validate:"omitempty,gte=2,lte=255"`
|
|||
|
}
|
|||
|
|
|||
|
val1 := 0
|
|||
|
val2 := 256
|
|||
|
|
|||
|
t1 := Test{MyInt: &val1} // This should fail validation on gte because value is 0
|
|||
|
t2 := Test{MyInt: &val2} // This should fail validate on lte because value is 256
|
|||
|
t3 := Test{MyInt: nil} // This should succeed validation because pointer is nil
|
|||
|
|
|||
|
errs := validate.Struct(t1)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.MyInt", "MyInt", "gte")
|
|||
|
|
|||
|
errs = validate.Struct(t2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "Test.MyInt", "MyInt", "lte")
|
|||
|
|
|||
|
errs = validate.Struct(t3)
|
|||
|
Equal(t, errs, nil)
|
|||
|
|
|||
|
type TestIface struct {
|
|||
|
MyInt interface{} `validate:"omitempty,gte=2,lte=255"`
|
|||
|
}
|
|||
|
|
|||
|
ti1 := TestIface{MyInt: &val1} // This should fail validation on gte because value is 0
|
|||
|
ti2 := TestIface{MyInt: &val2} // This should fail validate on lte because value is 256
|
|||
|
ti3 := TestIface{MyInt: nil} // This should succeed validation because pointer is nil
|
|||
|
|
|||
|
errs = validate.Struct(ti1)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestIface.MyInt", "MyInt", "gte")
|
|||
|
|
|||
|
errs = validate.Struct(ti2)
|
|||
|
NotEqual(t, errs, nil)
|
|||
|
AssertError(t, errs, "TestIface.MyInt", "MyInt", "lte")
|
|||
|
|
|||
|
errs = validate.Struct(ti3)
|
|||
|
Equal(t, errs, nil)
|
|||
|
}
|