| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 | 
							- package valid
 
- import (
 
- 	"context"
 
- 	"reflect"
 
- 	"testing"
 
- 	"github.com/stretchr/testify/assert"
 
- )
 
- type Struct1 struct {
 
- 	Field1 int
 
- 	Field2 *int
 
- 	Field3 []int
 
- 	Field4 [4]int
 
- 	field5 int
 
- 	Struct2
 
- 	S1               *Struct2
 
- 	S2               Struct2
 
- 	JSONField        int `json:"some_json_field"`
 
- 	JSONIgnoredField int `json:"-"`
 
- }
 
- type Struct2 struct {
 
- 	Field21 string
 
- 	Field22 string
 
- }
 
- type Struct3 struct {
 
- 	*Struct2
 
- 	S1 string
 
- }
 
- func TestFindStructField(t *testing.T) {
 
- 	var s1 Struct1
 
- 	v1 := reflect.ValueOf(&s1).Elem()
 
- 	assert.NotNil(t, findStructField(v1, reflect.ValueOf(&s1.Field1)))
 
- 	assert.Nil(t, findStructField(v1, reflect.ValueOf(s1.Field2)))
 
- 	assert.NotNil(t, findStructField(v1, reflect.ValueOf(&s1.Field2)))
 
- 	assert.Nil(t, findStructField(v1, reflect.ValueOf(s1.Field3)))
 
- 	assert.NotNil(t, findStructField(v1, reflect.ValueOf(&s1.Field3)))
 
- 	assert.NotNil(t, findStructField(v1, reflect.ValueOf(&s1.Field4)))
 
- 	assert.NotNil(t, findStructField(v1, reflect.ValueOf(&s1.field5)))
 
- 	assert.NotNil(t, findStructField(v1, reflect.ValueOf(&s1.Struct2)))
 
- 	assert.Nil(t, findStructField(v1, reflect.ValueOf(s1.S1)))
 
- 	assert.NotNil(t, findStructField(v1, reflect.ValueOf(&s1.S1)))
 
- 	assert.NotNil(t, findStructField(v1, reflect.ValueOf(&s1.Field21)))
 
- 	assert.NotNil(t, findStructField(v1, reflect.ValueOf(&s1.Field22)))
 
- 	assert.NotNil(t, findStructField(v1, reflect.ValueOf(&s1.Struct2.Field22)))
 
- 	s2 := reflect.ValueOf(&s1.Struct2).Elem()
 
- 	assert.NotNil(t, findStructField(s2, reflect.ValueOf(&s1.Field21)))
 
- 	assert.NotNil(t, findStructField(s2, reflect.ValueOf(&s1.Struct2.Field21)))
 
- 	assert.NotNil(t, findStructField(s2, reflect.ValueOf(&s1.Struct2.Field22)))
 
- 	s3 := Struct3{
 
- 		Struct2: &Struct2{},
 
- 	}
 
- 	v3 := reflect.ValueOf(&s3).Elem()
 
- 	assert.NotNil(t, findStructField(v3, reflect.ValueOf(&s3.Struct2)))
 
- 	assert.NotNil(t, findStructField(v3, reflect.ValueOf(&s3.Field21)))
 
- }
 
- func TestValidateStruct(t *testing.T) {
 
- 	var m0 *Model1
 
- 	m1 := Model1{A: "abc", B: "xyz", c: "abc", G: "xyz", H: []string{"abc", "abc"}, I: map[string]string{"foo": "abc"}}
 
- 	m2 := Model1{E: String123("xyz")}
 
- 	m3 := Model2{}
 
- 	m4 := Model2{M3: Model3{A: "abc"}, Model3: Model3{A: "abc"}}
 
- 	m5 := Model2{Model3: Model3{A: "internal"}}
 
- 	tests := []struct {
 
- 		tag   string
 
- 		model interface{}
 
- 		rules []*FieldRules
 
- 		err   string
 
- 	}{
 
- 		// empty rules
 
- 		{"t1.1", &m1, []*FieldRules{}, ""},
 
- 		{"t1.2", &m1, []*FieldRules{Field(&m1.A), Field(&m1.B)}, ""},
 
- 		// normal rules
 
- 		{"t2.1", &m1, []*FieldRules{Field(&m1.A, &validateAbc{}), Field(&m1.B, &validateXyz{})}, ""},
 
- 		{"t2.2", &m1, []*FieldRules{Field(&m1.A, &validateXyz{}), Field(&m1.B, &validateAbc{})}, "A: error xyz; B: error abc."},
 
- 		{"t2.3", &m1, []*FieldRules{Field(&m1.A, &validateXyz{}), Field(&m1.c, &validateXyz{})}, "A: error xyz; c: error xyz."},
 
- 		{"t2.4", &m1, []*FieldRules{Field(&m1.D, Length(0, 5))}, ""},
 
- 		{"t2.5", &m1, []*FieldRules{Field(&m1.F, Length(0, 5))}, ""},
 
- 		{"t2.6", &m1, []*FieldRules{Field(&m1.H, Each(&validateAbc{})), Field(&m1.I, Each(&validateAbc{}))}, ""},
 
- 		{"t2.7", &m1, []*FieldRules{Field(&m1.H, Each(&validateXyz{})), Field(&m1.I, Each(&validateXyz{}))}, "H: (0: error xyz; 1: error xyz.); I: (foo: error xyz.)."},
 
- 		// non-struct pointer
 
- 		{"t3.1", m1, []*FieldRules{}, ErrStructPointer.Error()},
 
- 		{"t3.2", nil, []*FieldRules{}, ErrStructPointer.Error()},
 
- 		{"t3.3", m0, []*FieldRules{}, ""},
 
- 		{"t3.4", &m0, []*FieldRules{}, ErrStructPointer.Error()},
 
- 		// invalid field spec
 
- 		{"t4.1", &m1, []*FieldRules{Field(m1)}, ErrFieldPointer(0).Error()},
 
- 		{"t4.2", &m1, []*FieldRules{Field(&m1)}, ErrFieldNotFound(0).Error()},
 
- 		// struct tag
 
- 		{"t5.1", &m1, []*FieldRules{Field(&m1.G, &validateAbc{})}, "g: error abc."},
 
- 		// validatable field
 
- 		{"t6.1", &m2, []*FieldRules{Field(&m2.E)}, "E: error 123."},
 
- 		{"t6.2", &m2, []*FieldRules{Field(&m2.E, Skip)}, ""},
 
- 		{"t6.3", &m2, []*FieldRules{Field(&m2.E, Skip.When(true))}, ""},
 
- 		{"t6.4", &m2, []*FieldRules{Field(&m2.E, Skip.When(false))}, "E: error 123."},
 
- 		// Required, NotNil
 
- 		{"t7.1", &m2, []*FieldRules{Field(&m2.F, Required)}, "F: cannot be blank."},
 
- 		{"t7.2", &m2, []*FieldRules{Field(&m2.F, NotNil)}, "F: is required."},
 
- 		{"t7.3", &m2, []*FieldRules{Field(&m2.F, Skip, Required)}, ""},
 
- 		{"t7.4", &m2, []*FieldRules{Field(&m2.F, Skip, NotNil)}, ""},
 
- 		{"t7.5", &m2, []*FieldRules{Field(&m2.F, Skip.When(true), Required)}, ""},
 
- 		{"t7.6", &m2, []*FieldRules{Field(&m2.F, Skip.When(true), NotNil)}, ""},
 
- 		{"t7.7", &m2, []*FieldRules{Field(&m2.F, Skip.When(false), Required)}, "F: cannot be blank."},
 
- 		{"t7.8", &m2, []*FieldRules{Field(&m2.F, Skip.When(false), NotNil)}, "F: is required."},
 
- 		// embedded structs
 
- 		{"t8.1", &m3, []*FieldRules{Field(&m3.M3, Skip)}, ""},
 
- 		{"t8.2", &m3, []*FieldRules{Field(&m3.M3)}, "M3: (A: error abc.)."},
 
- 		{"t8.3", &m3, []*FieldRules{Field(&m3.Model3, Skip)}, ""},
 
- 		{"t8.4", &m3, []*FieldRules{Field(&m3.Model3)}, "A: error abc."},
 
- 		{"t8.5", &m4, []*FieldRules{Field(&m4.M3)}, ""},
 
- 		{"t8.6", &m4, []*FieldRules{Field(&m4.Model3)}, ""},
 
- 		{"t8.7", &m3, []*FieldRules{Field(&m3.A, Required), Field(&m3.B, Required)}, "A: cannot be blank; B: cannot be blank."},
 
- 		{"t8.8", &m3, []*FieldRules{Field(&m4.A, Required)}, "field #0 cannot be found in the struct"},
 
- 		// internal error
 
- 		{"t9.1", &m5, []*FieldRules{Field(&m5.A, &validateAbc{}), Field(&m5.B, Required), Field(&m5.A, &validateInternalError{})}, "error internal"},
 
- 	}
 
- 	for _, test := range tests {
 
- 		err1 := ValidateStruct(test.model, test.rules...)
 
- 		err2 := ValidateStructWithContext(context.Background(), test.model, test.rules...)
 
- 		assertError(t, test.err, err1, test.tag)
 
- 		assertError(t, test.err, err2, test.tag)
 
- 	}
 
- 	// embedded struct
 
- 	err := Validate(&m3)
 
- 	assert.EqualError(t, err, "A: error abc.")
 
- 	a := struct {
 
- 		Name  string
 
- 		Value string
 
- 	}{"name", "demo"}
 
- 	err = ValidateStruct(&a,
 
- 		Field(&a.Name, Required),
 
- 		Field(&a.Value, Required, Length(5, 10)),
 
- 	)
 
- 	assert.EqualError(t, err, "Value: the length must be between 5 and 10.")
 
- }
 
- func TestValidateStructWithContext(t *testing.T) {
 
- 	m1 := Model1{A: "abc", B: "xyz", c: "abc", G: "xyz"}
 
- 	m2 := Model2{Model3: Model3{A: "internal"}}
 
- 	m3 := Model5{}
 
- 	tests := []struct {
 
- 		tag   string
 
- 		model interface{}
 
- 		rules []*FieldRules
 
- 		err   string
 
- 	}{
 
- 		// normal rules
 
- 		{"t1.1", &m1, []*FieldRules{Field(&m1.A, &validateContextAbc{}), Field(&m1.B, &validateContextXyz{})}, ""},
 
- 		{"t1.2", &m1, []*FieldRules{Field(&m1.A, &validateContextXyz{}), Field(&m1.B, &validateContextAbc{})}, "A: error xyz; B: error abc."},
 
- 		{"t1.3", &m1, []*FieldRules{Field(&m1.A, &validateContextXyz{}), Field(&m1.c, &validateContextXyz{})}, "A: error xyz; c: error xyz."},
 
- 		{"t1.4", &m1, []*FieldRules{Field(&m1.G, &validateContextAbc{})}, "g: error abc."},
 
- 		// skip rule
 
- 		{"t2.1", &m1, []*FieldRules{Field(&m1.G, Skip, &validateContextAbc{})}, ""},
 
- 		{"t2.2", &m1, []*FieldRules{Field(&m1.G, &validateContextAbc{}, Skip)}, "g: error abc."},
 
- 		// internal error
 
- 		{"t3.1", &m2, []*FieldRules{Field(&m2.A, &validateContextAbc{}), Field(&m2.B, Required), Field(&m2.A, &validateInternalError{})}, "error internal"},
 
- 	}
 
- 	for _, test := range tests {
 
- 		err := ValidateStructWithContext(context.Background(), test.model, test.rules...)
 
- 		assertError(t, test.err, err, test.tag)
 
- 	}
 
- 	//embedded struct
 
- 	err := ValidateWithContext(context.Background(), &m3)
 
- 	if assert.NotNil(t, err) {
 
- 		assert.Equal(t, "A: error abc.", err.Error())
 
- 	}
 
- 	a := struct {
 
- 		Name  string
 
- 		Value string
 
- 	}{"name", "demo"}
 
- 	err = ValidateStructWithContext(context.Background(), &a,
 
- 		Field(&a.Name, Required),
 
- 		Field(&a.Value, Required, Length(5, 10)),
 
- 	)
 
- 	if assert.NotNil(t, err) {
 
- 		assert.Equal(t, "Value: the length must be between 5 and 10.", err.Error())
 
- 	}
 
- }
 
- func Test_getErrorFieldName(t *testing.T) {
 
- 	var s1 Struct1
 
- 	v1 := reflect.ValueOf(&s1).Elem()
 
- 	sf1 := findStructField(v1, reflect.ValueOf(&s1.Field1))
 
- 	assert.NotNil(t, sf1)
 
- 	assert.Equal(t, "Field1", getErrorFieldName(sf1))
 
- 	jsonField := findStructField(v1, reflect.ValueOf(&s1.JSONField))
 
- 	assert.NotNil(t, jsonField)
 
- 	assert.Equal(t, "some_json_field", getErrorFieldName(jsonField))
 
- 	jsonIgnoredField := findStructField(v1, reflect.ValueOf(&s1.JSONIgnoredField))
 
- 	assert.NotNil(t, jsonIgnoredField)
 
- 	assert.Equal(t, "JSONIgnoredField", getErrorFieldName(jsonIgnoredField))
 
- }
 
 
  |