Skip to content

Commit

Permalink
Fix: panic for nil entries in a slice
Browse files Browse the repository at this point in the history
  • Loading branch information
samlown committed Jul 29, 2024
1 parent 84750cc commit fcb2a7c
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 5 deletions.
1 change: 0 additions & 1 deletion each_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ func TestEach(t *testing.T) {
{"t13", []interface{}{nil, a}, "0: cannot be blank; 1: cannot be blank."},
{"t14", []interface{}{c0, c1, f}, "0: cannot be blank."},
}

for _, test := range tests {
r := Each(Required)
err := r.Validate(test.value)
Expand Down
7 changes: 7 additions & 0 deletions struct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func TestValidateStruct(t *testing.T) {
m3 := Model2{}
m4 := Model2{M3: Model3{A: "abc"}, Model3: Model3{A: "abc"}}
m5 := Model2{Model3: Model3{A: "internal"}}
m6 := Model2{M3AP: []*Model3{nil}}
tests := []struct {
tag string
model interface{}
Expand Down Expand Up @@ -120,6 +121,8 @@ func TestValidateStruct(t *testing.T) {
{"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"},
{"t8.9", &m6, []*FieldRules{Field(&m6.M3AP)}, ""},
{"t8.10", &m6, []*FieldRules{Field(&m6.M3AP, Each(NotNil))}, "M3AP: (0: is required.)."},
// internal error
{"t9.1", &m5, []*FieldRules{Field(&m5.A, &validateAbc{}), Field(&m5.B, Required), Field(&m5.A, &validateInternalError{})}, "error internal"},
}
Expand Down Expand Up @@ -149,6 +152,7 @@ func TestValidateStructWithContext(t *testing.T) {
m1 := Model1{A: "abc", B: "xyz", c: "abc", G: "xyz"}
m2 := Model2{Model3: Model3{A: "internal"}}
m3 := Model5{}
m6 := Model2{M4AP: []*Model4{nil}}
tests := []struct {
tag string
model interface{}
Expand All @@ -165,6 +169,9 @@ func TestValidateStructWithContext(t *testing.T) {
{"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"},
// with custom validate methods
{"t4.1", &m6, []*FieldRules{Field(&m6.M4AP)}, ""},
{"t4.2", &m6, []*FieldRules{Field(&m6.M4AP, Each(NotNil))}, "M4AP: (0: is required.)."},
}
for _, test := range tests {
err := ValidateStructWithContext(context.Background(), test.model, test.rules...)
Expand Down
12 changes: 10 additions & 2 deletions validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,11 @@ func validateSlice(rv reflect.Value) error {
errs := Errors{}
l := rv.Len()
for i := 0; i < l; i++ {
if ev := rv.Index(i).Interface(); ev != nil {
v := rv.Index(i)
if v.Kind() == reflect.Ptr && v.IsNil() {
continue
}
if ev := v.Interface(); ev != nil {
if err := ev.(Validatable).Validate(); err != nil {
errs[strconv.Itoa(i)] = err
}
Expand All @@ -216,7 +220,11 @@ func validateSliceWithContext(ctx context.Context, rv reflect.Value) error {
errs := Errors{}
l := rv.Len()
for i := 0; i < l; i++ {
if ev := rv.Index(i).Interface(); ev != nil {
v := rv.Index(i)
if v.Kind() == reflect.Ptr && v.IsNil() {
continue
}
if ev := v.Interface(); ev != nil {
if err := ev.(ValidatableWithContext).ValidateWithContext(ctx); err != nil {
errs[strconv.Itoa(i)] = err
}
Expand Down
6 changes: 4 additions & 2 deletions validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,10 @@ func (s String123) Validate() error {

type Model2 struct {
Model3
M3 Model3
B string
M3 Model3
M3AP []*Model3
M4AP []*Model4
B string
}

type Model3 struct {
Expand Down

0 comments on commit fcb2a7c

Please sign in to comment.